1.4.1 SSRF利用
SSRF漏洞的出现场景如下。
● 需要本地访问,请求头无法绕过。
● 在URL中提交参数获取文件。
● 对外发起网络请求。
● 从远程服务器请求资源。
● 数据库内置功能。
● WebMail收取其他邮件。
● 文件处理、编码处理、属性信息处理。
1.内网访问
在CTF中,SSRF漏洞最常见的利用方式就是探测内网,根据127.0.0.1或找到的内网IP,对内网进行访问,结合BurpSuite可快速对目标端口进行检测。
靶场环境为CTFHub技能树-Web-SSRF-内网访问。
靶场中的URL通过GET方式传递参数变量url的值,通过该参数调用外部资源,所以成了SSRF漏洞的入口。构造Payload访问服务器本地资源:?url=127.0.0.1/flag.php。发送伪造后的请求,即可获取flag。
2.伪协议
伪协议就是利用不同URL协议类型配合SSRF,也就是URL scheme机制。URL scheme是系统提供的一种机制,由应用程序注册,其他程序通过URL scheme调用该应用程序,包括系统默认的URL scheme与应用程序自定义的URL scheme。https://www.ctfhub.com中https://就属于系统默认的机制。
以CURL工具为例,其支持的协议如下。
● file://:访问本地文件系统(不受allow_url_fopen与allow_url_include的影响)。
● dict://:约定服务器端侦听的端口号。
● sftp://:基于SSH的文件传输协议。
● tftp://:基于lockstep机制的文件传输协议。
● ldap://:轻量化目录访问协议。
● gopher://:分布式文档传递服务。
举个例子,CTFHub技能树-Web-SSRF-伪协议读取文件,使用file://协议读取flag.php的源码,构造Payload,?url=file:///var/www/html/flag.php,发送请求即可得到flag。
3.端口扫描
内网的防护相较于外网来说较为薄弱,通过扫描服务器与内网主机的端口,可发现外网无法访问的服务,扩大可攻击范围,增加攻破系统的可能性。
靶场环境为CTFHub技能树-Web-SSRF端口扫描。与上一题环境类似,构造Payload ?url=127.0.0.1:8000可直接使用BurpSuite对端口进行爆破,使用Intruder模块中的Sniper类型,选中8000端口号为变量,如图1-84所示。
图1-84 爆破端口
设置Payload类型为Numbers,这是因为题目提示端口号范围在8000~9000之间,设置如图1-85所示。
图1-85 设置端口范围
通过爆破结果的长度,获取flag,如图1-86所示。
图1-86 8910端口获得flag
也可以结合dict://协议对端口进行爆破,构造Payload ?url=dict://127.0.0.1:8000,同样设置8000为变量,如图1-87所示。
图1-87 设置爆破端口
与之前的Payload设置相同,获得爆破结果,如图1-88所示。
图1-88 爆破结果
根据页面响应状态(即返回长度)判断结果。
4.Gopher协议
Gopher协议是HTTP出现之前在互联网上最常见,也是最常用的协议。Gopher协议能够传递底层的TCP数据流,攻击内网的FTP、Telnet、Redis、Memcache,也可以进行GET、POST请求,所以在SSRF中Gopher协议的攻击面最广。
Gopher协议的格式为gopher://127.0.0.1:70/_+ TCP/IP数据,这里的_是一种数据连接格式,也可以是任意字符。Gopher协议在各种编程语言中的使用限制如表1-5所示。
表1-5 Gopher协议的使用限制
下面通过CTFHub的靶场举几个Gopher协议在SSRF中被利用的例子。
以CTFHub技能树-Web-SSRF-POST请求题目为例,通过GET方式传参访问:?url=127.0.0.1/flag.php。查看网页源码,代码如下。
其中含有key=51457bb0a50c1eb2c92dcc3ec3c2cc13,将key值添加到输入框中并提交,得到回显,如图1-89所示。
使用file://协议读取index.php以及flag.php页面源码:?url=file:///var/www/html/flag.php。得到index.php页面的源码,如图1-90所示。
图1-89 页面回显
图1-90 index.php页面源码
得到flag.php页面的源码,如图1-91所示。
图1-91 flag.php页面源码
尝试使用Gopher协议向服务器发送POST包。首先构造Gopher协议所需的POST请求,请求包如图1-92所示。
图1-92 构造请求包
在使用Gopher协议发送POST请求包时,Host、Content-Type和Content-Length请求头是必不可少的,但在GET请求中可以没有。
在向服务器发送请求时,浏览器会进行一次URL解码,服务器收到请求后,在执行CURL功能时,进行第二次URL解码,所以我们需要对构造的请求包进行两次URL编码。
首先将构造好的请求包进行第一次URL编码,如图1-93所示。
图1-93 第一次URL编码
将第一次编码后的数据中的%0A全部替换为%0D%0A。因为Gopher协议包含的请求数据包中,可能包含=、&等特殊字符,为避免与服务器解析传入的参数键值对混淆,所以对数据包进行第二次URL编码,这样服务端会把%后的字节当作普通字节。进行第二次URL编码,得到如下Gopher请求内容。
因为flag.php中的$_SERVER["REMOTE_ADDR"]无法绕过,所以只能通过index.php页面中的CURL功能向目标发送POST请求,构造如下Payload。
向目标发送数据包,得到flag,如图1-94所示。
图1-94 获取flag
以CTFHub技能树-Web-SSRF-POST上传文件题目为例,通过GET传参访问?url=127.0.0.1/flag.php,得到一个空上传功能点,如图1-95所示。
提示需要上传WebShell,只能选择文件,没有提交按钮。使用file://协议读取flag.php的源码:?url=file:///var/www/html/flag.php。得到目标源码,如图1-96所示。
图1-95 空上传功能点
图1-96 flag.php源码
后端无任何过滤,也无文件类型限制,上传文件大小大于0即可,如图1-97所示。
在flag.php页面中,还须满足请求只允许从本地访问,使用BurpSuite抓取数据包,如图1-98所示。
图1-97 上传页面源码
图1-98 BurpSuite抓包
构造Gopher协议所需的POST请求,如图1-99所示。
图1-99 POST请求
与之前相同,将第一次URL编码后的数据中的%0A替换为%0D%0A,并进行二次URL编码,如图1-100所示。
图1-100 URL编码
构造Payload,发送数据包,得到flag,代码如下。
5.攻击Redis
Redis是一个key-value存储系统,根据题目的提示,需要使用SSRF攻击内网的Redis服务,使用Gopherus工具生成攻击Redis的Payload,如图1-101所示。
选择PHPShell,根目录路径为默认值,使用默认的PHPShell,得到构造好的Gopher协议Payload,其默认经过了一次URL编码,将%0A替换为%0D%0A,对其进行二次URL编码,如图1-102所示。
图1-101 使用工具生成攻击Redis的Payload
图1-102 进行二次URL编码
构造最终的Payload,代码如下。
发送数据包,题目环境显示504,但Shell已经写入,访问shell.php,结果如图1-103所示。
图1-103 访问结果
虽然有脏数据,但是页面已经存在,WebShell参数为cmd,尝试寻找flag:shell.php?cmd=ls/。得到flag文件名,如图1-104所示。
图1-104 得到flag文件名
使用cat命令查看flag:shell.php?cmd=cat/flag_2596562d0e4a36c94823864f1d7a505b得到flag。其中Redis写WebShell用到的命令如下。
需要先将其转化为Redis RESP协议的格式,再进行URL编码。