跨站请求伪造 (CSRF)
跨站请求伪造(CSRF,Cross-Site Request Forgery) 是一种网络攻击方式,攻击者通过精心构造的恶意请求,诱导受害者在不知情的情况下向目标网站发送请求。这些请求会携带受害者的认证信息(如Cookies),从而执行攻击者想要的操作。
CSRF攻击原理
- 用户登录受信任网站:用户登录一个可信网站(如银行网站),获得一个认证会话(通常通过Cookie存储会话ID)。
- 攻击者诱导用户访问恶意网站:攻击者利用社交工程(如钓鱼邮件或恶意链接)诱导用户访问包含恶意代码的网站或点击某个链接。
- 发送恶意请求:恶意网站或链接会向目标网站发送伪造的请求(例如转账请求)。由于浏览器会自动附带用户在目标网站的Cookies,这些请求看起来像是用户合法发出的。
- 目标网站执行请求:目标网站无法区分请求是用户主动发起还是被伪造的,因此会执行请求,导致攻击成功。
示例(隐藏的恶意请求) :
arduino
<img src="http://bank.com/transfer?amount=1000&to=attacker_account" width="0" height="0">
防御措施
1. 使用CSRF令牌(推荐)
CSRF令牌(CSRF Token) 是一种防御CSRF攻击的安全机制。其核心是通过为每个用户会话生成一个唯一且不可预测的随机字符串(Token),并要求客户端在发送状态更改请求(如POST、PUT、DELETE)时附带该Token。服务器通过验证Token的有效性来确认请求是否来自合法用户。
工作原理
-
生成令牌:服务器为每个用户会话生成一个唯一的CSRF令牌,通常与用户的会话ID相关联。
-
分发令牌:服务器将令牌发送给客户端,通常嵌入到HTML表单的隐藏字段中,或通过响应头、API等方式提供给前端。
-
客户端提交令牌:客户端在发送状态更改请求时,必须将令牌包含在请求中(例如表单字段或请求头)。
-
服务器验证令牌:服务器检查请求中的令牌是否与用户会话中的令牌匹配,且令牌是否有效(未过期、未被篡改)。
-
处理结果:
- 令牌有效:请求被视为合法,服务器继续处理。
- 令牌缺失或无效:服务器拒绝请求,通常返回403 Forbidden错误。
使用方式
CSRF令牌通常放在表单字段或请求头中,不能存储在Cookies或LocalStorage中。
表单示例:
ini
<form method="POST" action="/transfer">
<input type="hidden" name="csrf_token" value="abc123randomtoken">
<input type="submit" value="提交">
</form>
API请求示例:
css
fetch('/transfer', {
method: 'POST',
headers: {
'X-CSRF-Token': 'abc123randomtoken' // 从meta标签或API获取
},
body: JSON.stringify({ amount: 1000 })
});
2. 检查Referer和Origin头
原理
服务器检查HTTP请求的Referer或Origin头,验证请求是否来自可信的域名。如果请求来自不可信的域名(如攻击者的网站),则拒绝处理。
实现方式
- 配置服务器检查Referer或Origin是否与应用的域名匹配。
- 对于敏感操作,优先使用Origin头,因为它更可靠(仅包含域名,不包含具体路径)。
局限性
- 某些浏览器可能不发送Referer(例如隐私模式)。
- 攻击者可能通过某些方式伪造Referer。
3. 使用SameSite Cookie属性
原理
通过设置Cookie的SameSite属性,限制跨站请求中Cookie的发送。
- SameSite=Strict:Cookie仅在同站请求中发送,跨站请求(如CSRF)不会携带Cookie。
- SameSite=Lax:允许部分安全的跨站GET请求携带Cookie,但限制POST等请求。
跨站脚本攻击 (XSS)
跨站脚本攻击(XSS,Cross-Site Scripting) 是一种常见的网络安全漏洞。攻击者通过在网页中注入恶意脚本(通常是JavaScript),当用户访问受感染的页面时,恶意脚本会在用户浏览器中执行,可能窃取用户数据(如Cookie、会话令牌)、篡改页面内容或执行其他恶意操作。
类型
- 反射型:非持久性XSS,攻击者诱骗用户点击包含恶意代码的短链接。服务器解析后返回的响应中隐藏了攻击者的XSS代码,从而攻击用户。
- 持久型:也称存储型XSS,攻击者将恶意数据提交到服务器。当其他用户访问时,服务器从数据库查询数据并发送给用户,导致攻击。
- DOM型 :通过HTML结构执行事件脚本,例如
<img src="xx" onerror="..."/>
,可能导致界面操作被劫持。
防御措施
1. 输入验证与过滤
- 白名单验证:仅允许符合预期格式的输入(如数字、字母等),拒绝不符合规则的输入。
- 黑名单过滤不可靠 :攻击者可能绕过黑名单(例如使用变种
<sCrIpT>
)。 - 过滤危险字符 :对
<
、>
、'
、"
、&
等特殊字符进行严格检查或移除。 - 示例:限制用户评论内容仅包含字母、数字和特定标点。
2. 输出编码
-
根据输出上下文对用户输入进行适当编码,防止脚本被解析为可执行代码。
- HTML上下文 :将
<
编码为<
,>
编码为>
。 - JavaScript上下文 :对变量进行JSON编码或使用安全的API(如
textContent
而非innerHTML
)。 - URL上下文 :使用
encodeURIComponent()
编码URL参数。
- HTML上下文 :将
-
工具/库:使用成熟的编码库,如OWASP ESAPI,或框架内置的编码功能(React的JSX、Vue的模板等会自动编码)。
3. 使用安全的API
-
避免直接使用
innerHTML
或eval()
,改用安全的API:- 使用
textContent
或createElement
动态添加内容。 - 避免
document.write
或setTimeout
直接执行用户输入。
- 使用
-
示例 :
element.textContent = userInput;
比element.innerHTML = userInput;
更安全。
4. 内容安全策略 (CSP)
-
通过HTTP头或
<meta>
标签配置内容安全策略(CSP),限制页面加载和执行的资源。 -
示例 :
Content-Security-Policy: default-src 'self'; script-src 'self' trusted.com
-
作用:
- 禁止内联脚本(
<script>
或on*
事件),强制使用外部脚本。 - 限制脚本来源,仅允许受信任域名。
- 降低XSS脚本执行的可能性。
- 禁止内联脚本(
-
注意:CSP需谨慎配置,避免过于宽松。
5. HTTP安全头
-
HttpOnly Cookie :设置HttpOnly属性,防止JavaScript通过
document.cookie
访问Cookie。- 示例 :
Set-Cookie: sessionid=abc123; HttpOnly
- 示例 :
-
Secure Cookie:确保Cookie仅通过HTTPS传输。
-
SameSite Cookie :设置
SameSite=Strict
或SameSite=Lax
,防止跨站请求携带Cookie。
内容安全策略 (CSP)
内容安全策略(CSP,Content-Security-Policy) 是一种安全机制,用于防止跨站脚本攻击(XSS)、点击劫持等威胁,通过限制网页加载资源的来源(如脚本、样式、图片等)来提升安全性。
核心作用
- 指定允许加载的资源来源(如域名、协议)。
- 限制内联脚本、样式和不安全的代码执行。
- 报告违反策略的行为。
前端配置方法
CSP通常通过以下方式在前端配置:
-
HTTP响应头
在服务器端设置
Content-Security-Policy
头。例如:cssContent-Security-Policy: default-src 'self'; script-src 'self' https://trusted.com; style-src 'self'; report-uri /csp-report
default-src 'self'
:默认只允许同源资源。script-src
:限制脚本来源。report-uri
:报告违规的端点。
-
HTML Meta标签
在HTML文件的
<head>
中添加<meta>
标签(功能有限,无法设置报告功能):css<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' https://trusted.com;">
-
常用指令
default-src
:默认资源来源。script-src
:脚本来源。style-src
:样式来源。img-src
:图片来源。connect-src
:API请求来源。font-src
:字体来源。frame-src
:框架来源。'self'
:仅允许同源。'none'
:禁止所有。'unsafe-inline'
:允许内联脚本/样式(不推荐)。'nonce-abc'
:允许带有指定nonce的脚本/样式。
-
前端注意事项
-
避免内联脚本/样式 :使用外部文件,或通过
nonce
(随机数)或hash
校验内联内容。xml<script nonce="randomNonce">/* 代码 */</script>
需在CSP中设置:
script-src 'nonce-randomNonce'
. -
测试与调试 :使用
Content-Security-Policy-Report-Only
头,仅报告而不阻止,便于调试。 -
动态内容:确保动态加载的资源(如通过JavaScript加载的图片)符合CSP规则。
-
示例
限制只加载同源脚本和来自https://trusted.com
的脚本:
css
Content-Security-Policy: script-src 'self' https://trusted.com; default-src 'self'
总结
内容安全策略通过HTTP头或<meta>
标签配置,推荐在服务器端设置响应头以获得完整功能。前端需确保代码符合CSP规则,避免内联脚本/样式,并通过测试逐步优化策略。