前端安全
请解释一下什么是 XSS,有哪些类型,以及如何防御
Section titled “请解释一下什么是 XSS,有哪些类型,以及如何防御”XSS(Cross-Site Scripting,跨站脚本攻击) 是一种常见的 Web 安全漏洞,其本质是攻击者成功地向目标用户的浏览器中 注入并执行了不受信任的恶意代码(通常是 JavaScript)。一旦恶意代码被执行,它就能利用浏览器和用户当前的权限,在用户的会话中执行任意操作。
XSS 的类型
Section titled “XSS 的类型”存储型 XSS(Stored XSS)
Section titled “存储型 XSS(Stored XSS)”恶意代码被存储在服务器数据库或文件里,其他用户访问页面时,脚本被取出并执行。
例如:在评论区输入 <script>alert("XSS")</script>,被存入数据库,之后所有访问评论的人都会弹窗
反射型 XSS(Reflected XSS)
Section titled “反射型 XSS(Reflected XSS)”恶意脚本通过 URL 参数直接传递。服务器未做过滤,原样返回到页面。用户点击恶意链接时,脚本立即执行。
例如:https://example.com/search?q=<script>alert('XSS')</script>
DOM 型 XSS(基于 DOM 的 XSS)
Section titled “DOM 型 XSS(基于 DOM 的 XSS)”漏洞出在前端 JavaScript 代码本身。前端直接把用户输入写进 DOM,而没有经过安全处理。
例如:document.body.innerHTML = location.hash;
XSS 的危害
Section titled “XSS 的危害”XSS 的核心危害在于 执行了不受信任的代码。具体地,取决于这些攻击代码,可能实现:
- 窃取用户身份认证信息: 通过
document.cookie窃取用户的 Cookie 并发送给攻击者 - 会话劫持: 利用窃取的 Cookie 或其他会话凭证,冒充用户身份
- 伪造用户操作: 在用户不知情的情况下,发送恶意 AJAX 请求、修改密码、转账等(可与 CSRF 配合)
- 页面劫持/钓鱼: 修改页面内容(如登录框),引导用户输入敏感信息
- 挂马/恶意重定向: 注入代码进一步下载木马、挖矿程序或将用户重定向到恶意网站
防御 XSS 的措施
Section titled “防御 XSS 的措施”防御 XSS 的关键在于 彻底遏制不受信任的代码被浏览器解析和执行。防御手段应覆盖输入、输出和环境配置三个层面:
1. 输出编码与转义(针对服务器生成的内容)
Section titled “1. 输出编码与转义(针对服务器生成的内容)”关键点:将用户输入的内容,作为“数据”而不是“代码”输出。
- 对 HTML 内容进行转义: 将用户输入中的特殊字符(如
< > " ' &)编码为 HTML 实体(如<编码为<,"编码为"),防止浏览器将其解析为标签或属性。 - 针对不同上下文进行编码: 根据内容将要被放置的位置(如 HTML 体内、HTML 属性、JavaScript 字符串、CSS 值等),采用相应的编码函数进行处理。
- 使用安全的库: 对于富文本(Rich Text)等需要保留部分标签的场景,必须使用专业的白名单过滤工具(如 DOMPurify),绝不能自己编写正则表达式进行过滤。
2. 避免使用危险的 API(针对前端代码)
Section titled “2. 避免使用危险的 API(针对前端代码)”关键点:消除客户端代码中可能导致 DOM 污染的漏洞源。
- 使用
textContent替代innerHTML: 当需要设置元素内容时,优先使用textContent,它会自动将内容视为纯文本处理。 - 避免使用危险的 DOM API: 避免使用
document.write()、element.setAttribute('on...')、eval()、setTimeout()/setInterval()传入字符串等能够动态执行代码的函数。 - DOM 型 XSS 防御库: 在必须操作 DOM 的场景,对输入进行验证和清洗。
3. 环境与配置加强(阻止代码执行和限制执行权限)
Section titled “3. 环境与配置加强(阻止代码执行和限制执行权限)”- 内容安全策略(CSP, Content-Security-Policy): 这是最有效的纵深防御手段。通过 HTTP 响应头告诉浏览器哪些外部资源(脚本、样式、图片等)可以加载和执行,以及是否允许内联脚本和动态代码执行。可以从根本上限制恶意代码的来源和行为。
- HttpOnly Cookie: 尽管不能阻止 XSS 漏洞本身,但可以降低 XSS 攻击窃取用户身份认证信息的风险。设置了
HttpOnly属性的 Cookie 无法通过客户端 JavaScript(如document.cookie)访问,从而有效防止攻击者通过 XSS 脚本窃取会话 Cookie。 - 输入校验与验证: 在服务端和客户端对输入进行严格的校验,例如只允许数字、字母、特定符号,采用白名单机制。虽然不能完全杜绝 XSS,但能大幅提高攻击难度。
什么是 CSRF
Section titled “什么是 CSRF”CSRF(Cross-Site Request Forgery,跨站请求伪造) 是另一种常见的 Web 安全漏洞,其本质是攻击者诱导用户(在已登录目标网站的情况下)的浏览器发送一个伪造的、非自愿的 HTTP 请求到目标网站。由于请求是由受害者的浏览器发出的,目标网站会认为这是一个合法的用户操作,从而执行攻击者预期的动作(如修改密码、转账、发送邮件等)。
核心危害在于:利用用户在目标网站的认证状态(如 Cookie),以用户的名义执行非预愿的操作。
CSRF 攻击的原理与关键点
Section titled “CSRF 攻击的原理与关键点”- 用户已登录: 用户在目标网站 A(如银行网站)进行了登录,浏览器中保留了目标网站的身份认证凭证(如 Cookie)。
- 诱导访问: 用户在不知情的情况下访问了攻击者构造的恶意网站 B,或者点击了恶意链接。
- 伪造请求: 恶意网站 B 嵌入了指向目标网站 A 的伪造请求(例如一个
<img src="...">或一个隐藏的表单)。 - 自动携带凭证: 浏览器向目标网站 A 发送请求时,根据同源策略的规则,会自动附带上目标网站 A 的 Cookie 等身份凭证。
- 目标网站执行操作: 目标网站 A 验证了 Cookie 是有效的,认为该请求是用户主动发出的合法操作,并执行了相应的指令。
CSRF 攻击的类型
Section titled “CSRF 攻击的类型”CSRF 攻击的分类通常根据攻击者利用的请求方式或载体来划分:
1. GET 请求 CSRF
Section titled “1. GET 请求 CSRF”利用 HTML 标签(如 <img>、<script>、<link>、<iframe> 等)可以加载外部资源的特性,构造一个 GET 请求作为其 src 或 href 属性。
- 例子: 银行网站的转账操作是一个 GET 请求:
GET /transfer?to=attacker&amount=100。攻击者在恶意页面嵌入:<img src="http://bank.com/transfer?to=attacker&amount=100" width="0" height="0">。 - 特征: 隐蔽性高,只需要用户访问一次即可触发。
2. POST 请求 CSRF
Section titled “2. POST 请求 CSRF”利用自动提交的表单(Form Auto-Submit)来伪造 POST 请求。攻击者构造一个隐藏的 <form>,并通过 JavaScript 脚本或在页面加载完成后自动触发提交。
- 例子: 目标网站的修改密码操作是 POST 请求。攻击者构造一个隐藏表单,包含修改密码的字段和目标 URL,然后自动提交。
- 特征: 相对 GET 请求需要更精巧的构造,但能伪造包含更多参数的请求。
3. 链接型/一键式 CSRF
Section titled “3. 链接型/一键式 CSRF”诱骗用户点击一个链接,该链接可能是 GET 请求,或者链接的目标页面是一个包含自动提交表单的页面。
- 特征: 直接欺骗,如伪造的电子邮件或聊天消息。
CSRF 攻击的危害取决于目标网站受影响的业务功能,其核心目的都是以受害者的身份执行操作:
- 资金操作: 强制用户转账、购买商品、修改支付设置。
- 身份信息篡改: 修改用户密码、邮箱、收货地址等敏感信息。
- 会话劫持(非直接): 强制用户退出登录(Logout CSRF),或强制用户关联/绑定攻击者的账号(如社交媒体账号)。
- 数据泄露(间接): 强制用户发送请求到攻击者控制的网站(较少见)。
防御 CSRF 的关键在于 确保请求是用户“主动”和“自愿”发出的,而不是被“伪造”的。这通常通过在请求中引入只有合法的用户界面才能提供的 不可猜测的秘密凭证 来实现。
1. 核心防御:同步令牌(Synchronizer Token Pattern, STP)
Section titled “1. 核心防御:同步令牌(Synchronizer Token Pattern, STP)”关键点:在表单和请求中加入一个攻击者无法预测的、随机生成的 Token。
- 实现:
- 用户请求表单页面时,服务器生成一个唯一的、加密的 CSRF Token,并将其存入用户的 Session 中。
- Token 同时被嵌入到页面的表单中(作为隐藏域)。
- 用户提交请求时,请求参数中会携带这个 Token。
- 服务器接收请求后,比对请求中的 Token 与 Session 中的 Token 是否一致。只有一致才认为请求有效。
2. 核心防御:同源验证机制
Section titled “2. 核心防御:同源验证机制”关键点:检查请求来源是否为目标网站自身。
- 验证 Referer 和 Origin 字段:
- Referer 头部: 检查 HTTP 请求的
Referer头部,判断请求是否来自于目标网站的安全域名。但Referer有时会被用户禁用或被代理修改。 - Origin 头部: 现代浏览器在跨站 POST 请求或带跨站凭证的 GET 请求中会携带
Origin头部。应优先检查Origin头部以确认请求的真实来源。
- Referer 头部: 检查 HTTP 请求的
3. 设置 Samesite Cookie 属性
Section titled “3. 设置 Samesite Cookie 属性”关键点:限制浏览器在跨站请求中发送 Cookie。
SameSite=Strict: 最严格。浏览器在所有跨站请求中都不会发送 Cookie。这几乎可以完全防御 CSRF 攻击,但可能会影响用户体验(如点击邮件链接到目标网站,发现未登录)。SameSite=Lax: 推荐使用。浏览器只在少数例外情况下(如顶级导航的 GET 请求)发送 Cookie,防御了大部分 POST 型和 GET 型 CSRF。SameSite=None: 必须同时设置Secure属性,允许跨站发送 Cookie,相当于没有防御作用。
4. 对敏感操作进行二次验证
Section titled “4. 对敏感操作进行二次验证”对于涉及资金或敏感信息修改的操作,强制用户进行二次验证(如输入旧密码、图形验证码或短信验证码),即使攻击者成功伪造了请求,也无法通过二次验证。
什么是 CSP
Section titled “什么是 CSP”CSP(Content Security Policy,内容安全策略) 是一种由浏览器强制执行的安全机制,用于防止跨站脚本攻击(XSS)、数据注入攻击等。它通过指定哪些资源(如脚本、样式、图片等)可以被加载,来减少攻击面。
TODO:
什么是同源策略?
Section titled “什么是同源策略?”同源策略(Same-Origin Policy) 是浏览器的一种核心安全机制,核心目的是 防止恶意网站通过脚本窃取或篡改其他网站的敏感数据。它的核心思想是:只有同一“源”(协议+域名+端口)的网页或脚本才能互相访问资源。意义包括:
- 减小跨站脚本攻击(XSS)的影响面:如果恶意网站能随意读取其他网站的数据(如 Cookie、LocalStorage),用户的隐私和账户安全将受到更严重的威胁。同源策略起到了安全沙箱的作用,让 XSS 的影响面限定在了“被攻击的那一个”网站中。
- 阻止恶意行为:例如,防止恶意脚本在用户不知情的情况下,以用户身份向其他网站(如银行、邮箱)发起请求(如转账、删除邮件等)。
同源策略虽然安全,但也限制了合法的跨域请求。有时,开发者希望安全地允许跨域请求。CORS(跨源资源共享,Cross-Origin Resource Sharing) 就是浏览器提供的一种受控的跨域访问方案。
跨域问题是什么?有哪些解决方案?
Section titled “跨域问题是什么?有哪些解决方案?”跨域问题是由于浏览器的 同源策略 引发的安全限制,当请求的协议、域名、端口 任一与当前页面不同时,浏览器会拦截响应数据。解决这一问题的核心是通过合法手段绕过或放宽这一限制。
解决方案包括:
- CORS(跨域资源共享) 是最标准的方案,通过后端设置响应头(如
Access-Control-Allow-Origin)明确允许特定域的请求,支持所有 HTTP 方法,但需要前后端协作。 - 若前端可控,可通过代理服务器(如 Nginx 或开发环境的 Webpack 代理)转发请求,将跨域转化为同源请求。
- 对于老旧系统,JSONP 利用
<script>标签的特性实现跨域,但仅支持 GET 且安全性较低。 - WebSocket 协议天然不受同源策略限制,适合实时通信场景。此外,通过 PostMessage 结合
iframe可实现跨页面通信。 - 修改 document.domain 则适用于主域相同的子域间交互。
实际选择时,优先考虑CORS(需后端支持)或代理服务器(前端可控场景),遗留系统可尝试 JSONP,需注意安全性及适用场景限制。