十、目录遍历漏洞
概述
目录遍历漏洞也叫路径穿越漏洞,是一种web安全漏洞,指攻击者通过构造特殊输入(如../),突破web程序目录访问限制,读取或者操作服务器上非预期目录中的文件(配置文件、敏感数据)
../:表示向上一级目录跳转,可通过它来跳转至服务器的其他目录
危害
读取服务器敏感文件(如数据库密码、系统配置)
结合其他漏洞(如文件包含)执行恶意代码
泄露文件结构,为进一步攻击提供信息
防御:
输入过滤,严格限制../、..\等路径符号;
目录白名单,通过realpath()规范化路径,将路径转化为绝对路径再进行验证是否在允许目录内,仅允许访问指定的安全目录,拒绝其他路径请求
禁用危险协议
示例
查看便发现title是实现目录遍历的关键变量,通过下面的报错提示存在漏洞

使用../构造payload,逐个尝试,跳转回到根目录下
在根目录下放置了一个flag.txt

构造payload:文件位置决定向上跳跃几级
http://localhost/pikachu-master/vul/dir/dir_list.php?title=../../../../flag.txt
得到文件内容

代码审计

漏洞形成
程序直接将$_GET['title']的值拼接到soup/后,然后通过require包含文件
攻击者可以通过../跳转目录,突破soup目录限制,读取服务器任意文件
十一、敏感信息泄露
概述
敏感信息泄露漏洞:是指在软件、系统或网络应用中,由于设计缺陷、配置错误或管理疏忽,导致未经授权的攻击者能够非法获取敏感数据的一类高危安全缺陷。敏感数据包括但不限于口令、密钥、证书、会话标识、个人隐私数据(如姓名、住址、电话)、授权凭据以及业务核心数据等。此类漏洞极易被黑客利用,可能导致严重的信息泄露、系统服务中断或权限被非法获取等后果
根据泄露的敏感信息类型:可分为物理路径泄露、身份信息泄露以及其他敏感数据泄露
根据漏洞产生的主要原因:主要可分为由版本管理软件(如.git、SVN)导致的泄露、由不安全文件包含导致的泄露以及由配置错误(如开启目录浏览、调试信息暴露)导致的泄露
涉及的敏感数据:包括但不限于口令、密钥、证书、会话标识、License、隐私数据(如短消息的内容)、授权凭据、个人数据(如姓名、住址、电话等),这些数据常存在于程序文件、配置文件、日志文件、备份文件、数据库中
常见漏洞形式
敏感信息泄露漏洞的常见形式多样,主要源于配置错误、开发遗留或应用程序设计缺陷。
配置或默认文件泄露:例如robots.txt文件泄露、服务器默认配置文件或测试脚本如phpinfo泄露,是常见形式之一。
版本管理信息泄露:如.git、.svn目录泄露,导致源代码暴露。
程序报错泄露:应用程序报错时显示详细调试信息导致的泄露。
备份文件泄露:指备份文件存放在Web可访问目录下。目录遍历漏洞允许攻击者绕过限制浏览目录结构。
项目开发环境泄露:如JetBrains IDEA项目目录部署到生产环境,也常见。
日志文件泄露涉及日志文件包含敏感数据且访问未控。此外,包含敏感数据的页面缓存或客户端存储,如Cookie中明文存储敏感信息,也是漏洞形式
漏洞危害
攻击者可通过分析数据包、触发程序报错等方式获取敏感信息,并直接利用这些信息发起进一步攻击。其直接危害包括为SQL注入、代码执行、文件上传等攻击提供关键凭据,以及为精准的社会工程学攻击提供素材 。
泄露的服务器路径、内网地址等信息可能被用于扫描内网开放服务、向内部主机发送攻击载荷,从而实施内网横向移动,攻击内网其他Web应用。攻击者还可能通过请求大文件并保持长连接的方式,利用泄露的路径发起拒绝服务攻击
修复建议
1.针对敏感信息泄露漏洞:应从配置管理、文件处理、数据保护及错误处理等多个层面进行综合防护。配置好服务端语言解析并关闭网站错误调试机制,可防止因解析失败或报错导致的源码泄露。同时应关闭Web容器(如IIS/Apache等)的目录浏览功能以及数据库的错误调试机制,防止目录遍历和SQL报错信息泄露。
2.应删除或移走网站目录下的备份文件、版本管理文件(如.git、.svn目录)、日志文件、phpinfo文件、服务器环境探针文件(如iprober.php)、JSP示例文件及服务端统计信息文件,并避免使用版本管理目录作为网站目录。
3.禁止在代码、数据库、文件、Cookie或隐藏域中以明文形式存储口令、密钥、个人数据等敏感数据。必须使用公开、安全的标准加密算法,而非自行开发的算法。用户密码在存储、传输、显示时都必须加密,优先选择不对称加密算法。
尽可能使用通用错误消息,并对系统默认报错页面进行重新设计,使用自定义报错页面,以免暴露系统敏感信息。
确保开发与运维人员充分了解何为敏感信息。定期审计并分离网站中的敏感目录,将其改为不易猜测的路径,并配置严格的访问权限。生产环境中应禁用任何调试或诊断功能
示例
检查网页源码,发现以一个测试账号,这可能就是开发人员的疏忽造成的

登录该账号


虽然使用了 escape() 函数,但 SQL 语句仍为字符串拼接

登录成功后,直接将用户名和密码哈希存入 Cookie且未设置 HttpOnly 和 Secure 等安全属性
密码哈希(MD5)存储在客户端,一旦被窃取,攻击者可直接用于伪造登录。
缺少 HttpOnly 属性,易被 XSS 攻击窃取 Cookie。
缺少 Secure 属性,在 HTTP 连接中明文传输,易被中间人攻击截获
十二、PHP反序列化
概述
1.PHP序列化
序列化:是将变量转换为可保存或可传输的字符串的过程;实现函数:serialize()
反序列化:就是在需要时将字符串再转化为原来的变量来使用,序列化的逆过程;实现函数unserialize()
2.PHP反序列化漏洞
也称对象注入,本质是:
程序在执行 unserialize() 函数时,会自动调用类中的一些 "魔术方法"(如 __wakeup()、__destruct()、__toString())
如果攻击者可以控制传入 unserialize() 的序列化字符串,就能通过构造恶意对象,让这些魔术方法执行恶意代码,从而实现文件读取、代码执行甚至服务器权限控制。
3.关键触发条件
3.1可控的输入:用户可以控制传入 unserialize() 的序列化字符串
3.2危险的魔术方法:目标代码中存在包含危险操作(如文件读写、系统命令执行)的魔术方法
3.3属性可被控制:魔术方法的行为依赖于类的属性,而这些属性可以通过序列化字符串来篡改
4.典型流程:POP 链(Property Oriented Programming)
4.1审计代码:找到包含unserialize()的入口点,分析相关类的魔术方法
4.2构造恶意对象:可在反序列化时触发危险魔术方法
4.3生成序列化字符串:将构造的对象序列化为字符串,作为输入传入目标程序
4.4触发漏洞:目标程序执行unserialize()时触发魔术方法中的恶意代码
5.魔术方法(Magic Methods)
PHP 魔术方法是一组以双下划线 __ 开头和结尾的特殊方法,会在特定场景下被自动调用,用来实现对象的特殊行为或者提供额外功能。
在反序列化漏洞中,它们是构造攻击链(POP 链)的核心,因为反序列化过程会触发特定的魔术方法,而攻击者可以通过控制对象属性来执行恶意代码。
5.1、对象生命周期相关
|---------------|-------------------------------------------------------------------------------|
| 魔术方法 | 触发时机 |
| __construct() | 类的构造函数,在类实例化对象时自动调用构造函数 |
| __destruct() | 类的析构函数,在对象销毁之前自动调用析构函数 |
| _sleep() | 在对象被序列化(使用 serialize () 函数)之前自动调用,可以在此方法中指定需要被序列化的属性,返回一个包含对象中所有应被序列化的变量名称的数组 |
| __wakeup() | 在对象被反序列化(使用 unserialize () 函数)之前自动调用,可以在此方法中重新初始化对象状态。 |
5.2、属性访问控制相关
|-------------------------|-------------------------------------------------------------|
| 魔术方法 | 触发时机 |
| __set(property,value) | 当给一个对象的不存在或不可访问 (private 修饰) 的属性赋值时自动调用,传递属性名和属性值作为参数。 |
| _get(property) | 当访问一个对象的不存在或不可访问的属性时自动调用,传递属性名作为参数。 |
| __isset(property) | 当对一个对象的不存在或不可访问的属性使用 isset () 或 empty () 函数时自动调用,传递属性名作为参数。 |
| __unset($property) | 当对一个对象的不存在或不可访问的属性使用 unset () 函数时自动调用,传递属性名作为参数。 |
5.3、方法调用控制相关
|-----------------------------------|------------------------------------------------|
| 魔术方法 | 触发时机 |
| __call(method,arguments) | 调用不存在或不可见的成员方法时,PHP 会先调用__call () 方法来存储方法名及其参数 |
| __callStatic(method, arguments) | 当调用一个静态方法中不存在的方法时自动调用,传递方法名和参数数组作为参数。 |
5.4、类型转换 / 输出相关
|---------------|-------------------------------------------------------|
| 魔术方法 | 触发时机 |
| __toString() | 当使用 echo 或 print 输出对象将对象转化为字符串形式时,会调用__toString () 方法 |
| __invoke() | 当将一个对象作为函数进行调用时自动调用。 |
| __debugInfo() | 在使用 var_dump () 打印对象时自动调用,用于自定义对象的调试信息。 |
5.5、克隆 / 导出相关
|---------------------|-----------------------------------------------|
| 魔术方法 | 触发时机 |
| __clone() | 当使用 clone 关键字复制一个对象时自动调用。 |
| __set_state($array) | 在使用 var_export () 导出类时自动调用,用于返回一个包含类的静态成员的数组。 |
序列化serialize()
序列化说通俗点就是把一个对象变成可以传输的字符串,比如下面是一个对象:
class S{
public $test="pikachu";
}
$s=new S(); //创建一个对象
serialize($s); //把这个对象进行序列化
序列化后得到的结果是这个样子的:O:1:"S":1:{s:4:"test";s:7:"pikachu";}
O:代表object
1:代表对象名字长度为一个字符
S:对象的名称
1:代表对象里面有一个变量
s:数据类型
4:变量名称的长度
test:变量名称
s:数据类型
7:变量值的长度
pikachu:变量值
反序列化unserialize()
就是把被序列化的字符串还原为对象,然后在接下来的代码中继续使用。
$u=unserialize("O:1:"S":1:{s:4:"test";s:7:"pikachu";}");
echo $u->test; //得到的结果为pikachu
序列化和反序列化本身没有问题,但是如果反序列化的内容是用户可以控制的,且后台不正当的使用了PHP中的魔法函数,就会导致安全问题
常见的几个魔法函数:
__construct()当一个对象创建时被调用
__destruct()当一个对象销毁时被调用
__toString()当一个对象被当作一个字符串使用
__sleep() 在对象在被序列化之前运行
__wakeup将在序列化之后立即被调用
漏洞举例:
class S{
var $test = "pikachu";
function __destruct(){
echo $this->test;
}
}
$s = $_GET['test'];
@$unser = unserialize($a);
payload:O:1:"S":1:{s:4:"test";s:29:"<script>alert('xss')</script>";}
漏洞点:
代码直接将用户可控的_GET\['test'\]进行反序列化,并且S类的__destruct()方法会直接输出 this->test的值,不进行任何的过滤
触发逻辑:
当脚本运行结束时,__destruct()会被调用用,将$test属性的内容输出到页面
Payload:恶意的反序列化字符串,用户将payload作为test参数传入
alert('xss')\";}" >http://WWW.baidu.com/?test=O:1:"S":1:{s:4:"test";s:29:"<script>alert('xss')</script>";}
代码执行unserialize()时,将payload还原为S类对象,其中test属性已经被赋值了XSS代码,脚本运行结束,__destruct()被触发,将test 的值(XSS代码)输出到页面,用户的浏览器解析并执行XSS代码,弹出"XSS"
代码审计


payload:
O:1:"S":1:{s:4:"test";s:29:"<script>alert('xss')</script>";}

十二、XXE(xml外部实体注入漏洞)
概述
什么是XML外部实体注入?
XML外部实体注入(也称为XXE)是一种网络安全漏洞,允许攻击者干扰应用程序对XML数据的处理。它通常允许攻击者查看应用服务器文件系统上的文件,并与应用程序本身能够访问的任何后端或外部系统进行交互。
在某些情况下,攻击者可以利用 XXE 漏洞升级,通过服务器端请求伪造(SSRF)攻击,升级攻击底层服务器或其他后端基础设施。
什么是XML?
XML代表"可扩展标记语言"(extensible markup language)。XML 是一种用于存储和传输数据的语言。像 HTML 一样,XML 采用树状结构的标签和数据结构。与HTML不同,XML不使用预定义标签,因此标签可以命名以描述数据。在网络早期,XML 作为一种数据传输格式非常流行("AJAX"中的"X"代表"XML")。但现在,JSON格式的流行度已经下降。
什么是XML实体?
XML实体是一种在XML文档中表示数据项的方式,而不是直接使用数据本身。XML语言规范中内置了各种实体。例如,实体和表示字符和。这些是用来表示XML标签的元字符,因此通常必须用它们在数据中出现的实体来表示。<><>
什么是文档类型定义?
XML 文档类型定义(DTD)包含可以定义 XML 文档结构、可包含的数据值类型及其他项的声明。DTD 在 XML 文档开头的可选元素中声明。DTD可以完全自包含在文档内部(称为"内部DTD"),也可以从其他地方加载(称为"外部DTD"),或者两者结合。DOCTYPE
什么是XML自定义实体?
XML 允许在 DTD 内定义自定义实体。例如:
<!DOCTYPE foo [ <!ENTITY myentity "my entity value" > ]>
该定义意味着在 XML 文档中对实体引用的任何使用都将被定义的值所替代:"。&myentity;my entity value
什么是XML外部实体?
XML 外部实体是一种自定义实体,其定义位于声明的 DTD 之外。
外部实体的声明使用该关键字,并必须指定一个 URL,从该URL加载该实体的值。例如:SYSTEM
<!DOCTYPE foo [ <!ENTITY ext SYSTEM "http://normal-website.com" > ]>
URL可以使用该协议,因此可以从文件加载外部实体。例如:file://
<!DOCTYPE foo [ <!ENTITY ext SYSTEM "file:///path/to/file" > ]>
XML 外部实体是 XML 外部实体攻击的主要方式。
XXE漏洞是如何产生的?
一些应用程序使用 XML 格式在浏览器和服务器之间传输数据。执行此作的应用程序几乎总是使用标准库或平台 API 来处理服务器上的 XML 数据。XXE 漏洞的出现是因为 XML 规范包含了各种潜在危险的功能,而标准解析器即使应用通常不使用这些功能,也支持这些功能。
XXE攻击有多种类型:
利用 XXE 检索文件,即定义包含文件内容的外部实体,并在应用程序响应中返回。
利用 XXE 进行 SSRF 攻击,即基于后端系统的 URL 定义外部实体。
利用盲目XXE会导致带外数据泄露,即敏感数据从应用服务器传输到攻击者控制的系统。
利用盲目XXE通过错误消息获取数据,攻击者可以触发包含敏感数据的解析错误消息。
XXE -"xml external entity injection"
既"xml外部实体注入漏洞"。
概括一下就是"攻击者通过向服务器注入指定的xml实体内容,从而让服务器按照指定的配置进行执行,导致问题"
也就是说服务端接收和解析了来自用户端的xml数据,而又没有做严格的安全控制,从而导致xml外部实体注入。
具体的关于xml实体的介绍,网络上有很多,自己动手先查一下。
现在很多语言里面对应的解析xml的函数默认是禁止解析外部实体内容的,从而也就直接避免了这个漏洞。
以PHP为例,在PHP里面解析xml用的是libxml,其在≥2.9.0的版本中,默认是禁止解析xml外部实体内容的。
XML+DTD基本语法
<!--声明xml的版本号-->
<?xml version="1.0"?>
<!--定义此文档是note类型的文档-->
<!DOCTYPE note[
<!--外部实体声明-->
<!ENTITY entity-name SYSTEM "URI/URL">
]>
<!--文档元素-->
<note>
<head>Reminder</head>
<body>You are a good man</body>
</note>

代码审计

漏洞核心原因
启用了外部实体解析:代码中显式传入了 LIBXML_NOENT 参数,这个参数会强制 simplexml_load_string() 解析 XML 外部实体。
直接处理用户输入:未对用户提交的 XML 内容做任何过滤,攻击者可以构造包含恶意外部实体的 XML,读取服务器本地文件或发起 SSRF 攻击。
结果直接输出:解析后的 XML 数据直接通过 echo 返回给用户,导致敏感信息泄露
XML:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [
<!ENTITY xxe SYSTEM "file:///D:/application/phpstudy/phpstudy_pro/WWW/flag.txt">
]>
<root>&xxe;</root>

措施:
1.禁用外部实体解析
2.使用更安全的解析方式
3.严格验证输入:对用户提交的 XML 进行 Schema 验证,确保只包含预期的标签和内容。
十四、URL重定向
概述
开放重定向,也叫 URL 跳转漏洞,本质是服务端未对用户传入的跳转目标 URL 做严格校验,导致攻击者可以构造恶意链接,诱导用户从一个可信网站跳转到钓鱼、恶意网站。
因为跳转是从用户信任的站点发起的,所以用户更容易放松警惕。
URL跳转的四种实现方式
1.a标签跳转:前端 HTML 直接通过<a href="xxx">实现,属于纯前端跳转
2.meta标签内跳转:通过<meta http-equiv="refresh" content="0;url=xxx">实现自动跳转
3.JavaScript跳转:通过window.location.href或window,open()等脚本触发跳转
4.header头跳转:服务端通过http响应头(如location:xxx)触发跳转
漏洞产生原因
代码层忽视 URL 跳转漏洞,或不知道/不认为这是个漏洞。
代码层过滤不严,用去取子串、取后缀等方法简单判断,代码逻辑可以被绕过。
对传入参数操作(域名剪切/拼接/重组)和判断不当,导致绕过
原始语言自带的解析 URL,判断域名的函数库出现逻辑漏洞或者意外特性
服务器/容器特性、浏览器登对标准 URL 协议解析处理等差异性导致被绕过
漏洞危害
钓鱼攻击:攻击者可以利用URL重定向漏洞,在看似官方的网站上诱导用户访问非法网站、下载恶意软件或执行其他恶意操作等。
窃取用户信息:攻击者可以伪造一个看起来和原网站相似的假冒网站,诱使用户输入敏感信息,如用户名、密码、银行账户等,从而窃取用户的信息。
XSS漏洞: 通过 javascript:alert(0) 或 CRLF;
获取用户权限:伪造钓鱼网站、窃取登录凭证 token;
绕过检测:窃取 CSRF token, 绕过 SSRF, RCE 和名单
高级利用方法:配合其他功能 / 漏洞
URL重定向漏洞认定标准
可成功跳转至非法网站、白名单外网站或其他可实行钓鱼攻击、窃取信息等高危行为的仿冒网站。
是否需要做出除点击链接外的其他操作(如是否存在跳转确认页面等)实现URL重定向。
可以成功显示跳转页面内容。
数据包中响应状态码为301、302、307或308
常见的URL跳转代码
Java:
javascript
response.sendRedirect(request.getParameter("url"))
PHP:
php
$redirect_url = $_GET\['url']; header("Location: " . $redirect_url)
.NET:
string redirect_url = request.QueryString["url"]; Response.Redirect(redirect_url);
Django:
redirect_url = request.GET.get("url") HttpResponseRedirect(redirect_url)
Flask:
redirect_url = request.form['url'] redirect(redirect_url)
Rails:
redirect_to params[:url\]
常见的路由参数名:
redirect
redirect_to
redirect_url
url
jump
jump_to
target
to
绕过方式
绕过是针对某些开发对有漏洞的参数未完全过滤或控制而进行的
绕过的原理是程序或浏览器对这些特殊符号的解析,可以让URL重定向到我们指定的地址
javascript
@绕过:利用 URL 解析规则,@ 后的内容会被当作实际目标地址,前面的内容会被忽略
http://xxx.com/?url=http://xxx.com@baidu.com
解析 URL 并提取 host,验证其是否在白名单内,不要只检查开头。
?绕过:后端验证逻辑可能只检查到第一个 ? 之前的内容,导致后续被当作参数忽略。
http://xxx.com?url=http://baidu.com?xxx.com
对整个 URL 进行规范化解析,不要简单截断
.绕过:利用子域名格式,让验证逻辑误判为可信域名的子域名。
http://xxx.com?url=http://xxx.com.baidu.com
严格匹配域名,不允许模糊匹配,可使用 parse_url 提取主机名。
#绕过:# 后的内容是锚点,不会发送到服务器,验证逻辑可能只检查到 # 之前。
http://xxx.com?url=http://baidu.com#xxx.com
解析时去除锚点部分,再对真实 URL 进行验证。
/绕过:多斜杠在浏览器解析时会被合并为单斜杠,但可能绕过简单的字符串检查
http://xxx.com?url=http:////baidu.com
规范化 URL,将多斜杠替换为单斜杠后再验证。
\绕过:部分后端语言会将 \ 当作路径分隔符,而浏览器会将其解析为普通字符。
http://xxx.com?url=http://baidu.com\xxx.com
对 URL 进行编码和解码,统一处理特殊字符。
双写参数绕过:后端可能只取第一个参数,而浏览器会优先使用最后一个参数。
http://xxx.com?url=http://xxx.com&url=http://baidu.com
确保只处理一个参数,或对所有同名参数进行验证。
进制绕过:将 IP 地址转为十进制(如 192.168.1.1 → 3232235777),绕过 IP 地址检查。
http://xxx.com?url=http://3232235777
解析 URL 时,将十进制 IP 转换回点分格式,再验证是否为内部 IP
不安全的url跳转
不安全的url跳转问题可能发生在一切执行了url地址跳转的地方。
如果后端采用了前端传进来的(可能是用户传参,或者之前预埋在前端页面的url地址)参数作为了跳转的目的地,而又没有做判断的话
就可能发生"跳错对象"的问题。
url跳转比较直接的危害是:
-->钓鱼 ,既攻击者使用漏洞方的域名(比如一个比较出名的公司域名往往会让用户放心的点击)做掩盖,而最终跳转的确实钓鱼网站


代码审计

代码仅对 url == 'i' 这一种特殊情况做了处理,其他所有输入都会直接通过 header("location:{url}") 进行跳转。
因为没有对用户传入的 $url 做任何域名或协议的验证,攻击者可以构造任意恶意 URL,诱导用户跳转到钓鱼网站或恶意网站。
十五、SSRF(Server-Side Request Forgery:服务器端请求伪造)
概述
是一种常见且危害严重的web安全漏洞。
当应用程序从服务器端发起外部请求,但未对请求目标进行充分验证时 ,攻击者可以利用这一漏洞诱导服务器向其指定的内部或外部目标发送请求,从而实现内网探测、数据窃取、端口扫描甚至远程代码执行等攻击。

SSRF漏洞危害等级评估
javascript
├── 严重
│ ├── 内网服务探测
│ ├── 敏感数据泄露
│ ├── 远程代码执行
│ └── 云服务元数据攻击
├── 高
│ ├── 端口扫描
│ ├── 绕过防火墙限制
│ └── 拒绝服务攻击
└── 中
├── 信息收集
├── 代理转发攻击
└── 缓存投毒
概念与本质
一般发生场景:
1.URL参数处理:当应用程序接受用户提供的URL并发起请求时
- 外部API调用:当应用程序调用外部API,但未验证API端点时
- 文件处理:当应用程序从远程URL加载文件时
- Webhook处理:当应用程序接受Webhook URL并向其发送数据时
- 镜像/预览功能:当应用程序提供URL预览或页面镜像功能时
形成原因:
本质在于应用程序过度信任用户输入,未对请求目标进行充分验证和限制,允许攻击者操纵服务器发起不应该发起的请求。

攻击场景与危害
1.内网探测:攻击者可以利用SSRF探测内部网络结构和服务
2.敏感数据窃取:攻击者可以访问内部服务上的敏感数据
3.云服务元数据攻击:攻击者可以访问云服务实例的元数据,获取凭证和配置信息
4.端口扫描:攻击者可以利用SSRF对内部网络进行端口扫描
5.绕过防火墙:攻击者可以绕过防火墙限制,访问被防火墙保护的资源
6.远程代码执行:在某些情况下,SSRF可以与其他漏洞结合,实现远程代码执行
7.拒绝服务攻击:攻击者可以利用SSRF发起拒绝服务攻击,消耗服务器资源
与其他漏洞大的区别与联系
- XSS:是在客户端执行恶意代码,SSRF是在服务器端发起恶意请求
- CSRF:诱导用户发起请求,SSRF是诱导服务器发起请求
- 注入:某些SSRF漏洞可以被利用来执行系统命令
- 文件包含:SSRF与远程文件包含(RFI)漏洞有相似之处,但SSRF不限于文件包含
- 不安全的反序列化:在某些情况下,SSRF可以与不安全的反序列化结合,造成更严重的后果
工作原理
应用程序接受用户提供的URL或其他请求目标信息,然后在服务器端发起相应的请求,但未对目标进行充分验证和限制
攻击者构造恶意的URL或者请求目标->发送到应用程序->程序在服务端向该目标发起请求->程序返回结果给攻击者->获取敏感信息或者其他
通俗说:
1.你(攻击者 )想偷看小区里某个住户(目标服务器)的东西,但你自己进不去。
2.小区门口有个快递员(目标应用程序),他可以帮你进去送东西。
3.你给快递员一个假地址(恶意 URL),说 "帮我把这个包裹送到这个地方",其实这个地址是你真正想偷看的住户家。
4.快递员没仔细核对地址(没有验证和限制目标),就直接进去了。
5.快递员不仅把包裹送到了,还顺便把住户家里的情况(敏感信息)拍了照片带回来给你。
6.你就这样拿到了本不该让你看到的信息,甚至还能让快递员帮你干点别的坏事。
简单来说:SSRF 就是攻击者利用目标应用程序作为 "中间人" ,去访问那些本不该被外部访问的内部资源,从而窃取信息或发起进一步攻击。
触发机制:本质上是利用了应用程序的信任漏洞和验证缺陷
1.直接URL参数:应用程序直接使用用户提供的URL参数发起请求
javascript
程序提供一个输入框或接口参数,让用户指定一个URL
用户可以输入http://192.168.1.1/admin这类内部地址让服务器发起请求从而获取管理页面信息
2.重定向利用:利用应用程序允许URL重定向的特性,将请求重定向到恶意目标
javascript
应用先验证用户输入的URL是否在白名单里(比如只允许https://example.com开头)
用户可以先提交一个看似合法的URL,然后让这个URL在服务器访问时自动重定向到内部地址,例如,提交 https://evil.com/redirect,这个链接会自动跳转到 http://127.0.0.1/secret,以此绕过初始验证。
3.DNS绑定攻击:利用DNS缓存漏洞,将域名先解析为允许的IP,然后快速更改为不允许的IP
javascript
用户会注册一个域名,在应用程序做初始验证时,让这个域名解析为一个被允许的外部 IP。一旦验证通过,攻击者会立刻修改 DNS 记录,让同一个域名解析为内部敏感 IP(如 192.168.1.1)。因为应用程序已经信任了这个域名,就会用这个新的恶意 IP 发起请求。
4.URL解析绕过:攻击者利用URL解析库的缺陷,绕过URL验证逻辑
不同的编程语言和库对 URL 的解析规则可能存在差异。用户会利用这个特性构造畸形 URL。比如:
javascript
http://example.com@192.168.1.1:有些解析库会把 @ 后面的部分当作真实目标 IP。
http://127.0.0.1:80#@example.com:利用锚点 # 让验证逻辑只检查前面的合法域名,而实际请求的是 127.0.0.1。
5.自定义协议处理:利用应用程序支持的自定义协议(如file://、dict://等)发起恶意请求
很多应用服务器不仅支持 http:// 和 https://,还支持一些危险的自定义协议,用户可以通过这些协议直接读取服务器文件或访问内部服务
javascript
file://:访问本地文件系统
dict://:与字典服务器通信
gopher://:访问Gopher协议服务
ldap:///ldaps://:访问LDAP服务
ftp://:访问FTP服务
sftp://:访问SFTP服务
tftp://:访问TFTP服务
伪URL:如127.0.0.1、localhost等本地地址
SSRF(Server-Side Request Forgery:服务器端请求伪造)
其形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能,但又没有对目标地址做严格过滤与限制
导致攻击者可以传入任意的地址来让后端服务器对其发起请求,并返回对该目标地址请求的数据
数据流:攻击者----->服务器---->目标地址
根据后台使用的函数的不同,对应的影响和利用方法又有不一样
PHP中下面函数的使用不当会导致SSRF:
javascript
file_get_contents()
fsockopen()
curl_exec()
如果一定要通过后台服务器远程去对用户指定("或者预埋在前端的请求")的地址进行资源请求,则请做好目标地址的过滤。
1.SSRF(curl)
curl_exec() 是 PHP 中 cURL 扩展的核心函数,用于执行一个预先初始化的 cURL
会话(由 curl_init() 创建),并返回请求的结果(或 TRUE/FALSE 表示成功 / 失
败,取决于会话设置)。它是服务器端发起 HTTP/HTTPS 等网络请求的常用工具,但如
果使用不当,可能成为 SSRF 漏洞的触发点。
在这里我们可以看到,URL是通过参数传递进来的,它向目标地址请求后返回数据到前端

在这里我们可以直接修改参数,以百度为我们的目标地址

在这里,用户通过向服务器发送请求访问目标地址,服务器对目标地址进行访问并将数据返回到前端,而不是用户通过浏览器自行访问
代码审计

漏洞核心原因
直接信任用户输入:代码直接获取 $_GET['url'] 参数,没有做任何验证和过滤,就交给 curl_exec() 去执行请求。
curl 支持多协议:curl 不仅支持 http:///https://,还支持 file://、gopher://、dict:// 等危险协议,这为攻击者提供了多种利用途径。
无输出限制:请求结果直接通过 echo $RES 返回给用户,导致攻击者可以获取服务器内部信息。
防范措施
协议白名单:只允许 http:// 和 https:// 协议,拒绝 file://、gopher:// 等危险协议。
目标地址验证:禁止访问内部 IP(如 127.0.0.1、192.168.x.x)和敏感域名。
禁用重定向:设置 CURLOPT_FOLLOWLOCATION 为 false,防止通过重定向绕过验证。
输入规范化:对 URL 进行解析和规范化,避免使用 @、# 等字符的畸形 URL 绕过验证。
2.SSRF(file-get-content)
file_get_contents() 是 PHP 中用于读取文件内容的函数,不仅能读取本地文件,
还能通过 URL 读取远程资源(如 HTTP/HTTPS 协议的内容)。但如果使用不当,也可
能成为 SSRF 漏洞的触发点,风险与 curl_exec()类似。
这里是 GET 请求传入参数 file,在这里可用通过http访问我们的目标地址


file_get_content()支持 PHP 伪协议
我们可以通过 php://filter 去读取后台文件
javascript
?file=PHP://filter/read=convert.base64-encode/resource=c:../../../windows/win.ini
php://filter/read=convert.base64-encode/resource=:这是伪协议的固定格式,指定读取文件并进行 Base64 编码,以避免直接输出二进制或特殊字符导致的乱码。
c:../../../../windows/win.ini:这是目标文件路径,通过../进行路径穿越,从 Web 根目录向上跳转,最终定位到 Windows 系统的win.ini配置文件

进行base64解码拿到明文内容

代码审计

漏洞核心原因
完全信任用户输入:代码直接接收 $_GET['file'] 参数,没有任何验证或过滤。
危险函数直接使用:file_get_contents() 函数可以读取本地文件、网络资源等任意内容。
结果直接输出:读取到的内容通过 echo $str 返回给用户,导致敏感信息泄露。
防范措施
使用白名单机制:仅允许读取指定目录下的特定文件
限制文件路径:将文件访问限制在特定目录内,防止路径穿越
禁止敏感文件类型:拒绝访问 .php、.ini 等敏感后缀的文件