📚 网络安全 Kali 学习系列
模块 0 基础阶段 ✅ 已完成
01-18 Linux系统 → 计算机网络 → 密码学 → Python/Bash/PHP/JS → Docker
模块 1 信息收集与侦察 ✅ 已完成
19 nmap 主动扫描 → 20 masscan 高速扫描 → 21 指纹识别与目录爆破 → 22 漏洞扫描与 Web 安全基础
模块 2 Web 应用渗透(攻击技术阶段)
✓ 23 sqlmap 注入与 Burp 抓包
✓ 24 XSS 跨站脚本攻击
25 CSRF 与文件上传漏洞(当前篇)
26 命令执行与代码执行漏洞(预告)
模块 3-5 共 XX 篇,后续持续更新
CSRF 与文件上传漏洞:借刀杀人和后门潜入
模块 2 Web 应用渗透 · 进阶篇 · 两大经典客户端漏洞
读完本篇你将能:理解 CSRF 跨站请求伪造的本质——"借用户的手干坏事",掌握 CSRF 的利用方式和防御手段(Token、SameSite、Referer 校验);同时掌握文件上传漏洞的检测方法、常见绕过技巧(前端校验绕过、MIME 绕过、黑名单绕过),以及上传 WebShell 后的利用思路。两种漏洞一攻客户端信任、一攻服务器入口,是 Web 渗透测试中必须掌握的核心技能。
📑 本文目录
01CSRF 是什么:被信任的"伪造请求"
02CSRF 利用场景与攻击构造
03CSRF 防御:Token 与 SameSite
04文件上传漏洞:服务器的后门入口
05上传绕过技巧大全
06WebShell 与上传后的利用
07道德边界与法律红线
08分级练习与知识回顾
一、CSRF 是什么:被信任的"伪造请求"
CSRF(Cross-Site Request Forgery,跨站请求伪造)是一种攻击者诱导受害者在已登录的 Web 应用上执行非预期操作的攻击方式。与 XSS 不同,CSRF 不注入脚本——它利用的是浏览器的一个"特性":浏览器会自动带上目标网站的 Cookie 发送请求,不管这个请求是从哪个页面发起的。
举个例子:你登录了银行网站,Cookie 还在有效期内。这时你打开了另一个恶意网站,这个网站的页面里有一个指向银行转账接口的表单,页面加载时自动提交。浏览器会带着你银行网站的 Cookie 发送这个转账请求——银行服务器收到请求,看到 Cookie 有效,就以为是你本人操作的。
类比:想象你住在一个需要刷门禁卡的小区。你出门时把门禁卡挂在脖子上,路过一家商店,商店门口有个装置,看到带门禁卡的人就自动帮你按下"打开小区快递柜"的按钮。你根本没碰那个按钮,但因为你带着卡,快递柜就开了——这就是 CSRF。攻击者不需要偷你的卡(那是 XSS 干的事),只需要在你带着卡的时候,让你"路过"一个会自动发请求的页面。
1.1 CSRF 的两个必要条件
CSRF 攻击要成立,必须同时满足两个条件:
1
受害者处于登录状态:用户在目标网站已经登录,浏览器中保存了有效的会话 Cookie
2
目标操作只依赖 Cookie 认证:服务器只通过 Cookie 来验证用户身份,没有其他验证机制(如 Token、验证码等)
缺一个条件,CSRF 就无法成立。如果用户没登录,攻击者伪造的请求没有有效 Cookie,服务器会拒绝。如果服务器除了 Cookie 还校验其他参数(比如请求头中的 Token),攻击者不知道这个 Token,伪造的请求也会失败。
1.2 CSRF vs XSS 对比
初学者经常把 CSRF 和 XSS 搞混,它们确实有相似之处(都是客户端攻击、都需要诱导用户),但本质完全不同:
| 对比维度 |
XSS |
CSRF |
| 攻击目标 |
用户浏览器 |
服务器接口 |
| 核心原理 |
注入脚本并执行 |
利用 Cookie 自动发送 |
| 攻击者能力 |
执行任意 JS(读 Cookie、发请求) |
只能发送预定义请求(无返回结果) |
| 是否需要交互 |
不一定(存储型自动触发) |
需要用户访问恶意页面 |
| 危害范围 |
窃取数据、篡改页面、操作执行 |
仅执行状态变更类操作 |
简单说:XSS 是"把脚本注入目标网站,让用户执行",CSRF 是"利用用户的登录状态,替用户发请求"。XSS 的能力更强(能执行任意 JS),CSRF 更隐蔽(不需要注入代码,只需要一个自动提交的表单)。
二、CSRF 利用场景与攻击构造
2.1 GET 型 CSRF
最简单的 CSRF 是 GET 型的——如果某个危险操作可以通过 GET 请求完成(比如 /transfer?to=xxx&amount=1000),攻击者只需要构造一个 <img> 标签即可:
HTML - GET 型 CSRF Payload
<!-- 放在恶意网站的页面中,页面加载即触发 -->
<img src="http://bank.com/transfer?to=hacker&amount=10000" style="display:none;">
用户访问恶意页面时,浏览器会自动加载 img 的 src,向银行网站发送 GET 请求,并自动带上 Cookie。银行服务器收到请求,验证 Cookie 通过,就执行了转账操作。用户全程可能根本不知道发生了什么——img 是隐藏的,页面看起来一切正常。
2.2 POST 型 CSRF
大多数危险操作(转账、改密码、删帖子)使用的是 POST 请求。POST 型 CSRF 需要构造一个自动提交的表单:
HTML - POST 型 CSRF Payload
<form id="csrfForm" action="http://bank.com/transfer" method="POST">
<input type="hidden" name="to" value="hacker">
<input type="hidden" name="amount" value="10000">
</form>
<script>
document.getElementById("csrfForm").submit();
</script>
用户访问恶意页面后,JavaScript 自动提交表单,浏览器带着 Cookie 向目标网站发送 POST 请求。整个过程用户可能毫无察觉——表单是隐藏的,提交后页面可能跳转到一个看起来正常的页面。
💡 小贴士
CSRF 有一个重要的限制:攻击者无法读取响应内容。由于浏览器的同源策略,恶意网站的 JavaScript 无法读取跨域请求的返回结果。所以 CSRF 只能用来执行"写操作"(转账、改密码、删数据),不能用来"读数据"。如果攻击者需要读数据,通常会结合 XSS 来绕过同源限制。
三、CSRF 防御:Token 与 SameSite
CSRF 的核心问题是"服务器只认 Cookie,不认请求来源"。防御思路也很直接:要么加一个攻击者无法伪造的验证信息,要么限制 Cookie 的发送范围。
3.1 CSRF Token(最主流方案)
CSRF Token 是目前最常用、最有效的防御手段。原理很简单:在每个表单中放入一个随机生成的 Token 值,这个值同时存在于用户的会话中。提交表单时,服务器检查表单中的 Token 和会话中的 Token 是否一致。
由于攻击者无法获取用户页面中的 Token(同源策略限制),他们构造的伪造请求就无法携带正确的 Token,服务器会直接拒绝。
用户访问页面
→
服务器生成 Token
→
Token 放入表单 + Session
→
提交时校验 Token
3.2 SameSite Cookie
SameSite 是 Cookie 的一个属性,可以限制 Cookie 在跨站请求中是否被发送。它有三个值:
•
Strict:最严格,完全禁止跨站发送 Cookie。用户从 A 站点击链接到 B 站,B 站的 Cookie 不会被发送,需要重新登录
•
Lax:宽松模式,GET 请求的顶级导航(点击链接跳转)可以带 Cookie,但 POST 表单、img/iframe 等子资源请求不带 Cookie。这是大多数浏览器的默认值
•
None:不限制,跨站请求也会发送 Cookie(必须同时设置 Secure 属性)
SameSite=Lax 能有效防御大部分 CSRF 攻击(尤其是 POST 型),但它不是万能的——GET 型 CSRF 通过顶级导航跳转仍然可以触发。所以 SameSite 通常作为 CSRF Token 的补充,而不是替代方案。
3.3 其他防御手段
1
Referer / Origin 校验:检查请求头中的 Referer 或 Origin 是否来自本站。但 Referer 可以被伪造或关闭,单独使用不够可靠
2
二次验证:敏感操作(转账、改密码)要求用户再次输入密码或输入验证码,确保是本人操作
3
自定义请求头:使用 AJAX 发送请求时添加自定义 Header(如 X-CSRF-Token),浏览器不会在跨站请求中自动添加自定义头
⚠️ 常见错误
"用验证码防 CSRF 就够了" — 验证码用户体验差,不能每个操作都加
✓ 正确理解:最佳实践是"CSRF Token 为主,SameSite Cookie 为辅,敏感操作加二次验证"的纵深防御体系。CSRF Token 覆盖所有状态变更操作,SameSite 提供浏览器层面的兜底,二次验证保护最核心的敏感操作。
四、文件上传漏洞:服务器的后门入口
文件上传功能在 Web 应用中非常普遍——头像上传、附件上传、图片上传……但如果上传功能没有做好安全校验,攻击者就可以上传恶意脚本文件(如 PHP 一句话木马),然后访问这个文件让服务器执行,从而获得服务器的控制权。这就是文件上传漏洞。
文件上传漏洞通常是危害最大的 Web 漏洞之一,因为它直接给了攻击者在服务器上执行代码的能力。从"上传一个脚本"到"拿到服务器权限",往往只差一步。
类比:如果把服务器比作一栋办公楼,文件上传功能就像大楼的快递收发室。正常情况下,收发室只收包裹(图片、文档),但如果保安不检查包裹里装的是什么,攻击者就可以把一个"机器人"(WebShell)塞进包裹里寄进去。机器人被送到大楼内部后,就可以在大楼里自由行动——这就是文件上传漏洞。快递单上写的是"日用品"(文件名后缀 .jpg),但里面装的是机器人(实际内容是 PHP 代码)。
4.1 漏洞产生的条件
文件上传漏洞的利用需要同时满足三个条件:
能上传恶意文件
+
知道上传后的路径
+
文件能被服务器执行
•
能上传:上传校验不严格,可以绕过检测上传脚本文件
•
能找到:上传后的文件路径可预测或可获取,攻击者知道去哪里访问
•
能执行:上传目录在 Web 可访问范围内,且服务器会解析该类型的文件(如 PHP 文件会被 PHP 解释器执行)
三个条件缺一不可。如果只能上传但找不到文件在哪(比如文件名被随机重命名且不返回路径),或者文件虽然上传了但存放在非 Web 目录下,漏洞都无法被利用。
4.2 DVWA 上传靶场演示
以 DVWA 的 File Upload 模块为例。在 low 级别下,上传功能完全没有校验——你可以直接上传一个 .php 文件:
shell.php - 最简单的一句话木马
<?php
eval($_POST['cmd']);
?>
上传成功后,DVWA 会显示文件路径。用浏览器访问 http://靶机地址/hackable/uploads/shell.php,然后通过 POST 参数 cmd 传递命令,就能在服务器上执行任意 PHP 代码。
五、上传绕过技巧大全
真实场景中,上传功能通常会有一些校验。但校验方式不同,绕过的难度也不同。下面介绍几种常见的校验方式和对应的绕过技巧。
5.1 前端 JS 校验绕过
有些网站只在前端用 JavaScript 检查文件后缀(比如 onChange 事件中判断文件名是否以 .jpg 结尾)。这种校验等于形同虚设——攻击者可以:
•
浏览器禁用 JavaScript
•
用 Burp Suite 抓包改文件名(先传 .jpg,拦截请求后改成 .php)
•
直接构造 POST 请求上传(绕过前端页面)
前端校验只能防普通用户,防不了攻击者。任何前端校验都必须在后端再校验一次。
5.2 MIME 类型校验绕过
有些网站会检查 HTTP 请求头中的 Content-Type 字段,比如只允许 image/jpeg 或 image/png。但 Content-Type 是客户端可以随意设置的——用 Burp 抓包修改 Content-Type 即可绕过。
Burp 中修改 Content-Type 绕过 MIME 校验
# 修改前(默认值,来自浏览器)
Content-Type: application/x-php
# 修改后(伪装成图片)
Content-Type: image/jpeg
5.3 黑名单绕过
黑名单过滤是列出不允许上传的后缀(如 .php、.asp、.jsp)。但黑名单往往不完整,可以通过以下方式绕过:
•
特殊后缀:.phtml、.php3、.php5、.pht 等在某些 PHP 配置下也会被解析
•
大小写绕过:如果黑名单是大小写敏感的,用 .Php、.PHP、.pHp 等
•
空格和点绕过:Windows 系统下,文件名末尾的空格和点会被自动去除,上传 shell.php. 或 shell.php (末尾空格)可能绕过黑名单
•
双写绕过:如果过滤只删除一次 .php,用 .pphphp 绕过(删除中间的 php 后变成 .php)
•
.htaccess 绕过:上传一个 .htaccess 文件,设置让某个其他后缀(如 .jpg)按 PHP 解析(仅 Apache 有效)
5.4 %00 截断绕过
在 PHP 版本低于 5.3.4 且 magic_quotes_gpc 关闭的情况下,可以使用 %00 截断。原理是 C 语言的字符串以 \0 结尾,当路径中出现 %00(URL 解码后就是 \0)时,底层函数会认为字符串到这里就结束了。
%00 截断示例
# 上传文件名为 shell.php%00.jpg
shell.php%00.jpg
# 后端校验后缀:检查 .jpg → 通过
# 保存文件时遇到 %00 → 截断,实际保存为
shell.php // .jpg 被截断丢弃了
%00 截断是一个比较老的漏洞,现代 PHP 版本已经修复,但在一些老系统中仍然可能遇到。
六、WebShell 与上传后的利用
6.1 一句话木马原理
一句话木马是最常见的 WebShell 形式,它只有一行核心代码,但功能强大:
常见一句话木马
// PHP 版(最常见)
<?php eval($_POST['cmd']); ?>
// 执行系统命令版
<?php system($_GET['c']); ?>
eval() 函数会把传入的字符串当作 PHP 代码执行,所以攻击者可以通过 POST 参数传递任意 PHP 代码。system() 则直接执行系统命令。两者都非常危险。
6.2 上传后的利用路径
成功上传 WebShell 后,攻击者通常会按以下路径逐步扩大权限:
| 阶段 |
目标 |
常用操作 |
| 1. 信息收集 |
了解服务器环境 |
phpinfo、whoami、ipconfig/ifconfig |
| 2. 文件操作 |
浏览、下载、修改文件 |
读配置文件、找数据库密码、挂黑页 |
| 3. 权限提升 |
从 Web 权限到系统权限 |
提权漏洞利用、计划任务、启动项 |
| 4. 内网渗透 |
以服务器为跳板攻击内网 |
端口转发、内网扫描、横向移动 |
⚠️ 法律红线
上传 WebShell 并利用属于严重的非法入侵行为。根据《刑法》第二百八十五条,非法侵入计算机信息系统或非法获取计算机信息系统数据、非法控制计算机信息系统,情节严重的处三年以下有期徒刑,情节特别严重的处三年以上七年以下有期徒刑。以上内容仅用于安全研究和授权测试,严禁用于非法用途。
七、道德边界与法律红线
CSRF 和文件上传漏洞都是威力巨大的攻击手段,学习它们的目的是为了防御,而不是攻击。在实践中必须严格遵守以下原则:
•
仅限授权测试:只能对自己搭建的靶场(DVWA、pikachu 等)或有书面授权的系统进行测试,禁止对任何未授权网站进行 CSRF 验证或上传测试
•
禁止上传 WebShell:即使发现了上传漏洞,也不得上传任何后门或恶意脚本,更不能用于获取服务器权限
•
禁止构造 CSRF 攻击:不得利用 CSRF 漏洞对真实用户进行任何操作,包括但不限于转账、改密、发帖等
•
漏洞报告走正规渠道:发现漏洞后应通过漏洞赏金平台、厂商安全响应中心(SRC)等正规渠道报告,不得私下利用或泄露
根据《中华人民共和国刑法》第二百八十五条和第二百八十六条,非法侵入计算机信息系统、非法获取计算机信息系统数据、破坏计算机信息系统等行为,均属刑事犯罪,最高可处五年以上有期徒刑。学习安全技术的目的是保护系统,不是破坏系统。
✏️ 动手练习
🟢 基础验证
在 DVWA 的 CSRF 模块(low 级别)中,观察修改密码的请求格式,然后构造一个 HTML 页面,用自动提交的表单实现 CSRF 修改密码。提示:分析 GET 请求的参数结构,用 img 或 iframe 触发。
🟡 组合应用
在 DVWA File Upload(medium 级别)中,上传功能对 Content-Type 做了校验。请使用 Burp Suite 抓包修改 Content-Type,成功上传一个 PHP 一句话木马,并验证可以通过 POST 参数执行 phpinfo()。
🔴 开放挑战
搭建一个本地 PHP 环境,实现一个带文件上传功能的页面,要求使用白名单校验文件后缀且对文件内容进行头部检测(检查是否为真实图片)。然后尝试寻找绕过方法——比如制作一张"图片马"(在正常图片末尾追加 PHP 代码),并思考在什么条件下图片马可以被执行。提示:需要结合文件包含漏洞或服务器配置缺陷。
📖 知识回顾
CSRF 跨站请求伪造
GET/POST 型 CSRF
CSRF Token
SameSite Cookie
文件上传漏洞
前端校验绕过
MIME 绕过
%00 截断
黑名单 vs 白名单
一句话木马
WebShell 利用
下篇预告
26 命令执行与代码执行漏洞
XSS 是注入到浏览器执行,文件上传是上传到服务器执行——而命令执行漏洞则是直接让操作系统执行命令。下一篇将学习命令注入、代码注入、eval 危险函数等高危漏洞的原理、检测与利用,以及如何防御这些"直接拿到服务器权限"的致命漏洞。