»» 引言:为什么Web安全是每个开发者的必修课
在Web应用开发中,安全漏洞往往是黑客入侵的突破口。OWASP(开放Web应用安全项目)每年都会发布十大Web应用安全风险(OWASP Top 10),其中XSS(跨站脚本攻击)、CSRF(跨站请求伪造)、SQL注入常年位居前列。这些攻击手段看似老生常谈,却在实际生产中频频造成严重的数据泄露和业务损失。
本文将系统讲解这三种最经典的Web攻击手法及其防御策略,并引入Content Security Policy(CSP)作为纵深防御手段,帮助开发者构建更安全的Web应用。
»» 一、XSS(跨站脚本攻击):当用户输入变成了代码
1.1 XSS攻击原理
XSS(Cross-Site Scripting)的核心原理是:应用程序未经过滤或转义,直接将用户输入的内容作为HTML或JavaScript代码输出到页面中,导致攻击者可以注入并执行恶意脚本。
一个典型的反射型XSS场景:搜索页面URL参数直接输出到页面,攻击者构造包含恶意脚本的链接,当用户点击时脚本在当前域名下执行,可以窃取Cookie、Session Token,甚至代表用户发起任意请求。
1.2 XSS的三种类型
- 反射型XSS(Reflected XSS):恶意脚本作为请求的一部分发送给服务器,服务器未过滤直接返回给浏览器执行。常见于搜索框、错误提示页面等。
- 存储型XSS(Stored XSS):恶意脚本被持久化存储到服务器(如评论、留言板、用户昵称),任何访问受影响页面的用户都会中招。危害最大。
- DOM型XSS(DOM-based XSS):完全在客户端发生,恶意脚本通过修改DOM树触发执行,服务器端无法检测。常见于前端模板渲染场景。
1.3 XSS防御策略
策略一:输出编码(Output Encoding)
// Go语言使用html/template自动转义
// 所有{{.UserInput}}会被自动HTML转义
// 包含HTML特殊字符的内容会安全地变为实体编码
策略二:输入验证与白名单
// 使用regexp验证输入格式
// 用户名只允许字母数字和下划线
// 拒绝包含HTML特殊字符的输入
// 日期字段严格匹配YYYY-MM-DD格式
策略三:设置HttpOnly Cookie
// Go语言设置HttpOnly Cookie
http.SetCookie(w, &http.Cookie{
Name: "session_id",
Value: sessionToken,
HttpOnly: true, // 禁止JavaScript读取
Secure: true, // 仅HTTPS传输
SameSite: http.SameSiteStrictMode,
})
策略四:CSP(Content Security Policy)
// 设置响应头限制脚本执行
w.Header().Set("Content-Security-Policy",
"default-src 'self'; script-src 'self' https:; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; object-src 'none'")
»» 二、CSRF(跨站请求伪造):借刀杀人的攻击
2.1 CSRF攻击原理
CSRF(Cross-Site Request Forgery)利用的是:浏览器在发起请求时,会自动携带该站点的Cookie。攻击者诱导用户访问恶意页面,该页面自动向目标网站发起请求,由于携带了合法Cookie,服务器会认为是用户的正常操作。
典型场景:恶意页面包含隐藏表单自动提交到银行转账接口,由于用户已登录且浏览器自动携带了Session Cookie,服务器会执行转账操作。
2.2 CSRF防御策略
策略一:CSRF Token(最常用)
// Go语言使用gorilla/csrf中间件
import "github.com/gorilla/csrf"
protect := csrf.Protect(
[]byte("32-byte-long-auth-key"),
csrf.Secure(false), // 生产环境设为true
)
http.Handle("/form", protect(http.HandlerFunc(showForm)))
策略二:SameSite Cookie属性
http.SetCookie(w, &http.Cookie{
Name: "session_id",
Value: token,
SameSite: http.SameSiteStrictMode,
Secure: true,
HttpOnly: true,
})
策略三:验证Origin/Referer头
// 检查请求来源
func checkOrigin(r *http.Request) bool {
origin := r.Header.Get("Origin")
return origin == "https://yourdomain.com"
}
»» 三、SQL注入(SQL Injection):数据库大门的定时炸弹
3.1 SQL注入原理
SQL注入发生在应用程序将用户输入直接拼接到SQL查询语句中时,攻击者通过构造特殊的输入内容,改变原SQL语句的语义,实现越权查询、数据篡改甚至删库。
例如代码:query := fmt.Sprintf("SELECT * FROM users WHERE name='%s' AND password='%s'", username, password),当username输入 admin' OR '1'='1 时,SQL语义被改变,'1'='1'始终为真,绕过了密码验证。
3.2 SQL注入防御策略
策略一:参数化查询(Prepared Statements)—— 最重要!
// 安全的参数化查询
query := "SELECT * FROM users WHERE name = ? AND password = ?"
err := db.QueryRow(query, username, password).Scan(&id, &name)
策略二:ORM框架自动转义
// 使用GORM等ORM框架自动防止注入
db.Where("name = ? AND password = ?", username, password).First(&user)
策略三:最小权限原则
-- 为应用创建专用数据库用户,只授予必要权限
GRANT SELECT, INSERT, UPDATE ON app_db.* TO 'app_user'@'localhost';
-- 禁止DROP、DELETE等危险操作
REVOKE DROP, DELETE ON app_db.* FROM 'app_user'@'localhost';
策略四:输入白名单验证
// 对严格限定格式的字段做白名单验证
allowedSorts := map[string]bool{"created_at": true, "name": true}
if !allowedSorts[orderBy] {
return errors.New("invalid sort field")
}
»» 四、CSP(内容安全策略):纵深防御的最后一道防线
CSP通过响应头告诉浏览器:哪些资源可以加载和执行,即使攻击者成功注入了恶意脚本,CSP也能阻止其执行。关键配置包括:default-src限制默认资源来源、script-src限制脚本来源、style-src限制样式来源、img-src限制图片来源、object-src设为none禁止插件、frame-ancestors限制iframe嵌入、upgrade-insecure-requests自动升级HTTP到HTTPS。
»» 五、综合防御清单
- ✅ 所有用户输入必须经过输出编码或转义
- ✅ 敏感Cookie设置HttpOnly + Secure + SameSite=Strict
- ✅ 所有状态变更请求(POST/PUT/DELETE)验证CSRF Token
- ✅ 数据库操作强制使用参数化查询
- ✅ 数据库用户遵循最小权限原则
- ✅ 设置严格的CSP响应头
- ✅ 对用户上传文件做类型校验和病毒扫描
- ✅ 敏感操作增加二次确认(如短信验证码)
- ✅ 定期进行安全审计和渗透测试
Web安全是一个持续攻防的过程,永远不要信任用户输入是安全开发的第一原则。通过纵深防御策略,即使一层防御被突破,其他层次仍然能保护你的应用和数据安全。

发表评论 取消回复