XSS
一、什么是XSS?
Cross-Site Scripting(跨站脚本攻击)为了与CSS作区分故简称 XSS,是一种代码注入攻击。攻击者通过在目标网站上注入恶意脚本,使之在用户的浏览器上运行。利用这些恶意脚本,攻击者可获取用户的敏感信息如 Cookie、SessionID 等,进而危害数据安全。本质
恶意代码未经过滤,与网站正常的代码混在一起;浏览器无法分辨哪些脚本是可信的,导致恶意脚本被执行。 可能被注入恶意脚本的内容
来自用户的 UGC 信息来自第三方的链接URL 参数POST 参数Referer (可能来自不可信的来源)Cookie (可能来自其他子域注入)
二、XSS攻击方式
分为三种:存储型 、反射型 、DOM 型
存储型XSS
它不需要用户手动触发,所有浏览者访问页面时都会被XSS常见于带有用户保存数据的网站功能,如论坛发帖、商品评论、用户私信等 反射型XSS
需要用户主动打开恶意的 URL 才能生效,攻击者往往会结合多种手段诱导用户点击常见于通过 URL 传递参数的功能,如网站搜索、跳转等 DOM型XSS
属于前端 JavaScript 自身的安全漏洞 区别
特征存储型 XSS反射型 XSSDOM 型 XSS存储位置恶意代码存储在服务器数据库恶意代码不存储,仅存在于URL参数恶意代码不存储,存在于URL片段触发条件用户访问被感染的页面用户点击包含恶意参数的链接用户点击包含恶意片段(#)的链接数据流服务器 → 用户浏览器服务器反射参数 → 用户浏览器完全在客户端处理(不经过服务器)持久性长期存在(直到数据被删除)一次性(仅当用户点击链接时)一次性(仅当用户点击链接时)攻击范围所有访问该页面的用户仅点击特定链接的用户仅点击特定链接的用户
三、常见的XSS攻击场景
社交媒体评论——存储型XSS
攻击者在评论区提交恶意脚本(如 ),该评论被存储到服务器。其他用户访问该页面时,恶意脚本自动加载并窃取其会话Cookie。
搜索功能——反射型XSS
网站搜索功能未过滤输入参数,攻击者构造恶意链接:https://example.com/search?q=,用户点击链接后,服务器返回的页面包含未过滤的恶意脚本。 单页面应用路由——DOM型XSS
SPA前端路由根据URL参数动态加载内容,但未对参数过滤。攻击者构造链接:https://example.com/#/profile?username=,用户点击链接,前端脚本将 username 参数直接渲染到页面,触发XSS。
四、防御策略
预防存储型XSS
输入过滤
对于明确的输入类型
如数字、URL、电话号码、邮件,使用escapeHTML()可以把用户的输入内容进行转义
原始字符转义后实体编码<<>>&&""'' // 用户输入:
const escaped = escapeHTML(userInput);
document.getElementById('content').innerHTML = escaped;
// 输出:<script>alert('XSS攻击')</script>
更推荐使用成熟且完善的现有库 // 使用 DOMPurify(支持更复杂的净化)
import DOMPurify from 'dompurify';
DOMPurify.sanitize(userInput, { ALLOWED_TAGS: [] });
特殊场景补充
场景额外需要转义的字符方法URL参数% #配合使用 encodeURIComponentCSS属性\ ()使用 CSS.escape()JSON数据\u2028 \u2029JSON.stringify 对于不明确的类型
最好不要使用输入过滤,因为当把转义后的数据发送到后端再回到前端,赋值给一个变量之后,展示出来的效果会变成乱码(如5<7会变成5<7) 预防存储型XSS和反射型XSS
纯前端渲染
现代框架的自动防护
React:默认转义所有插值内容
function UserContent({ text }) {
return
}
// 用户输入 `` 会显示为文本,不会执行
Vue:模板插值自动编码
Angular:插值绑定安全处理
安全API危险替代品场景textContentinnerHTML插入纯文本内容setAttributeinnerHTML设置元素属性document.createElement + appendChildinsertAdjacentHTML动态创建节点 转义HTML
使用更完善更细致的转义库org.owasp.encoder,以下代码引用自 org.owasp.encoder 的官方说明。
var msg = "<%= Encode.forJavaScript(UNTRUSTED) %>";
alert(msg);
var __INITIAL_STATE__ = JSON.parse('<%= Encoder.forJavaScript(data.to_json) %>');
link
预防DOM型XSS
使用.innerHTML、.outerHTML、document.write() 时要特别小心,不要把不可信的数据作为 HTML 插到页面上,而应尽量使用 .textContent、.setAttribute()DOM 中的内联事件监听器,如 location、onclick、onerror、onload、onmouseover 等, 标签的 href 属性,JavaScript 的 eval()、setTimeout()、setInterval() 等,都能把字符串作为代码运行 其他预防方法
httpOnly: 在 cookie 中设置 HttpOnly 属性后,js脚本将无法读取到 cookie 信息。
// 后端实现
app.post('/login', (req, res) => {
res.cookie('sessionID', 'xxxx', {
httpOnly: true, // 关键:禁止JS访问
secure: true, // 仅通过HTTPS传输
sameSite: 'Lax' // 防御CSRF
});
res.send('登录成功');
});
白名单:
输入白名单验证
function validateInput(input) {
// 只允许字母、数字、空格以及特定的标签
const whiteListPattern = /^[a-zA-Z0-9\s<>/bB/iI]*$/;
return whiteListPattern.test(input);
}
const userInput = "";
if (!validateInput(userInput)) {
// 处理非法输入
console.log("Invalid input!");
}
HTML标签/属性白名单
// 使用DOMPurify库配置白名单
import DOMPurify from 'dompurify';
const dirtyHTML = '合法内容';
const cleanHTML = DOMPurify.sanitize(dirtyHTML, {
ALLOWED_TAGS: ['b', 'i', 'em'], // 允许的标签
ALLOWED_ATTR: ['class', 'style'], // 允许的属性
FORBID_TAGS: ['style', 'script'] // 强制禁止的标签
});
console.log(cleanHTML);
// 输出:合法内容
CSP:
基础配置
Content-Security-Policy:
default-src 'self'; # 默认只允许同源资源
script-src 'self' # 脚本仅限同源
https://trusted.cdn.com
'nonce-abc123'; # 允许带特定nonce的内联脚本
style-src 'self' 'unsafe-inline'; # 允许内联样式(慎用)
img-src * data:; # 允许所有图片源(根据需求收紧)
font-src 'self';
frame-src 'none'; # 禁止嵌入iframe
report-uri /csp-report; # 违规报告地址
参考资料 https://juejin.cn/post/6844903685122703367 https://juejin.cn/post/6844903781704925191
🎈 相关推荐
有请使用东方财富通L2极速版的同学,告诉我一下好用吗?
华为P8的基本信息
梦幻西游坐骑剧情:完整任务步骤及奖励一览
打印机扫描怎么操作 打印机扫描操作步骤指南
这篇文章写得真好!