Web 安全入门:从 SQL 注入到 XSS、CSRF 的完整攻防图谱

Web 安全是每个后端开发者和运维人员都无法绕开的必修课。一个看似不起眼的输入框,可能成为攻击者撬动整个数据库的支点。本文围绕 Web 安全中最经典的三类漏洞——SQL 注入、XSS 和 CSRF,梳理它们的攻击原理、常见变体以及对应的防御策略,帮助你建立一套完整的攻防认知框架。

一、SQL 注入:当用户输入变成数据库指令

SQL 注入(SQL Injection)是 Web 安全领域最古老、也最具破坏力的漏洞之一。它的核心问题在于:应用程序将用户输入直接拼接进 SQL 语句,导致攻击者可以篡改查询逻辑。

攻击原理

假设登录接口的查询语句是这样拼接的:

SELECT * FROM users WHERE username = '$username' AND password = '$password';

如果攻击者在用户名输入 ' OR '1'='1' --,语句就变成:

SELECT * FROM users WHERE username = '' OR '1'='1' --' AND password = '...';

OR '1'='1' 使条件恒真,-- 注释掉后续内容,攻击者无需密码即可登录。更进一步,攻击者可以通过 UNION SELECT 读取其他表的数据,甚至利用数据库函数执行系统命令。

常见变体

  • 联合查询注入:利用 UNION SELECT 将额外数据拼接到正常结果集中。
  • 盲注:页面不回显数据时,通过布尔条件或时间延迟逐字符推断信息。
  • 堆叠注入:利用分号执行多条语句,直接修改或删除数据。

防御策略

参数化查询是根本解法。 使用预编译语句将 SQL 结构与数据分离,让数据库引擎明确区分“代码”和“值”:

cursor.execute("SELECT * FROM users WHERE username = %s AND password = %s", (username, password))

此外,还应做到:最小权限原则(Web 应用连接数据库的账号不应有 DROP、FILE 等权限)、对输入进行类型校验和长度限制、关闭生产环境的详细错误回显。

二、XSS:在别人的浏览器里执行我的代码

跨站脚本攻击(Cross-Site Scripting,XSS)的本质是:攻击者将恶意脚本注入到网页中,当其他用户浏览该页面时,脚本在其浏览器中执行,从而窃取 Cookie、会话令牌或进行钓鱼操作。

三种类型

存储型 XSS 是最危险的一种。恶意脚本被永久存储在服务器上(如评论区、用户昵称),所有访问该页面的用户都会中招。

反射型 XSS 中,恶意脚本作为请求参数发送给服务器,服务器将其原样“反射”回响应页面。攻击者通常通过钓鱼链接诱导用户点击。

DOM 型 XSS 不经过服务器,完全由前端 JavaScript 处理不当引起。例如:

document.getElementById('output').innerHTML = location.hash.slice(1);

攻击者在 URL 的 hash 中构造 <img src=x onerror=alert(document.cookie)>,脚本便会在受害者浏览器中执行。

防御策略

输出编码是第一道防线。 根据输出位置(HTML 正文、属性、JavaScript、URL)使用对应的编码方式,将 <>"' 等字符转义。

内容安全策略(CSP)是纵深防御的关键。 通过 HTTP 响应头限制脚本来源:

Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted.cdn.com

这能有效阻止内联脚本和未授权外部脚本的执行。此外,对 Cookie 设置 HttpOnly 标志,可以防止 JavaScript 读取会话 Cookie。

三、CSRF:借用户之手完成恶意操作

跨站请求伪造(Cross-Site Request Forgery,CSRF)与 XSS 不同,它不需要注入脚本,而是利用浏览器自动携带 Cookie 的机制,诱导已登录用户在不知情的情况下发出请求。

攻击场景

假设银行转账接口为 POST /transfer,参数为 toamount。攻击者构造一个自动提交的隐藏表单,放在自己的页面上:

<form action="https://bank.com/transfer" method="POST">
  <input type="hidden" name="to" value="attacker">
  <input type="hidden" name="amount" value="10000">
</form>
<script>document.forms[0].submit();</script>

当已登录银行账户的用户访问该页面时,浏览器会自动带上银行的会话 Cookie 发出请求,服务器误以为是用户本人操作。

防御策略

CSRF Token 是最常用的防御手段。 服务器在表单中嵌入一个随机生成的、与用户会话绑定的令牌,提交时验证令牌是否匹配。攻击者无法预测该令牌,因此伪造的请求会被拒绝。

SameSite Cookie 属性是现代浏览器的另一道屏障。将会话 Cookie 设置为 SameSite=LaxSameSite=Strict,可以限制跨站请求携带 Cookie:

Set-Cookie: sessionid=abc123; SameSite=Lax; Secure; HttpOnly

此外,对于敏感操作,应验证 OriginReferer 请求头,并避免使用 GET 请求执行状态变更操作。

四、安全加固清单

将以上防御措施整合为一份可落地的检查清单:

  1. 所有数据库查询使用参数化语句,禁止字符串拼接 SQL。
  2. 所有用户可控输出进行上下文相关的编码,配合 CSP 头限制脚本执行。
  3. 所有状态变更请求携带 CSRF Token,Cookie 设置 SameSiteHttpOnlySecure
  4. 输入验证采用白名单策略,只允许预期格式的数据通过。
  5. 错误信息不暴露堆栈和数据库细节,统一返回友好提示。
  6. 依赖库定期更新,关注 CVE 漏洞公告。
  7. 部署 WAF 作为辅助,但不能替代代码层面的修复。

结语

SQL 注入、XSS 和 CSRF 之所以长期占据 OWASP Top 10,不是因为防御手段有多复杂,而是因为开发者往往在功能实现后才想起安全。将参数化查询、输出编码、CSRF Token 和 SameSite Cookie 作为编码习惯而非事后补丁,才能真正把这三类漏洞挡在门外。安全不是一次性的审计,而是贯穿开发全流程的思维方式。

未经允许不得转载:任鹏个人博客 » Web 安全入门:从 SQL 注入到 XSS、CSRF 的完整攻防图谱

赞 (0) 打赏

评论 0

取消
  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏