什么是 XSS 攻击?
这几天整理的一下过往的文章和笔记,备份到了 Github 上,地址👉 blog。
如果我的内容帮助到了您,欢迎点个 Star
🎉🎉🎉 鼓励鼓励 :) ~~ 👆
我希望我的内容可以帮助你。现在我专注于前端领域,但我也将分享我在有限的时间内看到和感受到的东西。
XSS(Cross Site Scripting)是跨站脚本攻击。它是一种网站应用程序的安全漏洞攻击,是代码注入的一种。它允许恶意用户将代码注入到网页上,其他用户在观看网页时就会受到影响。这类攻击通常包含了 HTML 以及用户端脚本语言。
XSS 攻击原理
在 XSS 攻击中,恶意代码会被注入您的网站,然后被执行。例如:当注入具有渲染完整标签的属性的字符串时是可能的(如 Element.innerHTML
和Element.outerHTML
),而不仅仅是文本(如 Node.textContent
和 Element.innerText
)。
不过,有一个内置的保护措施。
仅仅注入一个 script
标签不会让你受到攻击,因为您注入的 DOM 部分已经被解析并运行了。
// 这行不通
const div = document.querySelector('#app')
div.innerHTML = '<script>alert("XSS 攻击")</script>'
但是,稍后运行的 JavaScript 将继续运行。
在此示例中,我们尝试从无效来源加载图像。当它失败时,onerror
事件会运行一些恶意 JavaScript。
// 这将运行
div.innerHTML = `<img src="/path/to" onerror="alert('XSS 攻击')">`
在这种情况下,它只是在提醒一条消息。但在真实的场景中,代码可能会从我们的网站上抓取敏感数据,并将其发送给第三方来源。
链接是另一个潜在的攻击媒介。如果 href
或 src
属性是从第三方数据中设置的,则有恶意的用户可以在 URL 前加上 javascript:
或 data:text/html
,并在用户单击链接或元素加载时运行代码。
div.innerHTML = `<a href="javascript:alert('另一个 XSS 攻击')">点我有惊喜</a>`
这些攻击方式不需要你做任何的登录认证,只是通过简单、合法的操作,向你的页面注入脚本。
XSS 的攻击方式
- 反射性 XSS
- 存储型 XSS
- DOM 型 XSS
这里不过多介绍,关于 XSS 攻击方式可以查看最后附加的链接,我们重点来看看如何防范 XSS 攻击。
XSS 防范措施
HTML 转义特殊字符
const escapeHTML = function (handleString){
return handleString
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/ /g, " ")
.replace(/\'/g, "'")
.replace(/\"/g, """)
}
escapeHTML('<script>alert("xss")</script>')
使用 XSS 库针对用户输入源过滤,设置标签白名单
使用白名单指定的配置对不受信任的 HTML 进行清理(以防止 XSS),这里我们可以使用 jsxss:
import xss from 'xss'
const html = xss('<script>alert("xss")</script>')
console.log(html)
Cookie 设置 HttpOnly
在 HTTP 的响应头 set-cookie
时设置 httpOnly
,让浏览器知道不能通过 document.cookie
的方式获取到 cookie 内容。
app.get('/', (req, res) => {
if (req.cookies.isVisit) {
console.log(req.cookies)
res.send('欢迎再次光临')
} else {
res.cookie('isVisit', 1, { maxAge: 3600 * 1000, httpOnly: true })
res.send('欢迎初次光临')
}
})
虽然避免了攻击者直接获取到 cookie,但是攻击者仍然可以在页面内发起别的请求,直接篡改用户的信息。我们可以配合 token 或者验证码的形式来防止这种情况的放生。而这两种相比,验证码的安全性会更搞些。
设置 CSP 安全策略
内容安全策略(CSP)用于检测和减轻用于 Web 站点的特定类型的攻击,例如 XSS 和数据注入等。
启用 CSP 的方式有 2 种:
- 添加
meta
标签http-equive
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';">
- 服务器响应头设置
总结
- 合适的 HTML 转义可以有效避免 XSS 漏洞,阻止浏览器将用户输入解析为实际 HTML,因此不会执行脚本
- 对于不受信任的输入字段,限制其输入长度
- 使用
textContent
而不是innerHTML
可以阻止浏览器通过 HTML 解析器运行字符串,而 HTML 解析器将在其中执行脚本 - 针对用户输入源和不可信数据源必须进行过滤和校验。如
<script>
、<img>
、<a>
等标签要进行过滤 - 避免标签中使用
onLoad
等事件,在 JavaScript 中通过.addEventlistener()
事件绑定会更安全 - 避免拼接 HTML,采用比较成熟的渲染框架,如 Vue/React 等
- 通过 CSP 安全策略和其他 HTTP 响应头的设置等进一步确保安全性
- 为 cookie 设置
httpOnly
来禁止 JavaScript 读取某些敏感 Cookie,攻击者完成 XSS 注入后也无法窃取此 Cookie - 使用验证码可以防止脚本冒充用户提交危险操作
- 使用 XSS 攻击字符串和自动扫描工具寻找潜在的 XSS 漏洞