从代码审计角度识别 XSS 与 SQL 注入:一份面向开发者的防御指南

在 Web 安全领域,XSS(跨站脚本攻击)和 SQL 注入长期占据 OWASP Top 10 的显著位置。尽管这两类漏洞的原理并不复杂,但在实际代码审计中,它们依然是最常被发现的缺陷。本文将从代码审计的视角出发,系统梳理这两类漏洞的识别方法与防御策略,并附带一份 Linux 服务器安全加固清单,帮助开发者和运维人员构建更稳固的防线。

一、XSS 的常见方式与前端防御

1.1 代码审计中常见的 XSS 形态

在审计前端代码时,XSS 通常出现在数据从“不可信来源”流向“危险汇聚点”的路径上。常见类型包括:

  • 反射型 XSS:恶意脚本作为请求参数的一部分,被服务器直接“反射”回响应页面。审计时重点关注 URL 参数是否未经转义就插入 HTML。
  • 存储型 XSS:恶意数据被持久化到数据库(如评论、用户昵称),在其他用户访问时执行。这是危害最大的一类,审计时需追踪所有写入数据库的字段。
  • DOM 型 XSS:漏洞完全发生在客户端,JavaScript 从 location.hashdocument.referrer 等来源读取数据,并直接写入 innerHTMLdocument.writeeval

1.2 前端防御的核心原则

前端防御 XSS 的核心是 “永远不要信任用户输入,始终进行上下文相关的输出编码”。具体措施包括:

  • 输出编码:根据数据插入的位置(HTML 正文、属性、URL、JavaScript 变量)采用不同的编码方式。例如,插入 HTML 正文时转义 <>&"';插入 URL 时使用 encodeURIComponent
  • 避免危险 API:禁止使用 innerHTMLouterHTMLdocument.write 直接插入不可信数据。优先使用 textContentcreateElement + appendChild
  • 使用 CSP:内容安全策略(Content-Security-Policy)可以限制脚本来源,即使存在 XSS 漏洞,也能大幅降低危害。建议设置 script-src 'self' 并禁用 unsafe-inline
  • 输入验证与白名单:对用户输入进行格式校验,例如邮箱、手机号等,但输入验证不能替代输出编码。

在代码审计中,可以搜索 innerHTMLdangerouslySetInnerHTML(React)、v-html(Vue)等关键字,快速定位潜在风险点。

二、MySQL 防止 SQL 注入的几种写法

SQL 注入的本质是用户输入被当作 SQL 代码执行。在审计后端代码时,重点检查所有拼接 SQL 语句的地方。以下是几种安全的写法,按推荐程度排序:

2.1 参数化查询(预处理语句)—— 首选方案

参数化查询将 SQL 语句与数据分离,数据库会先编译语句结构,再绑定参数值,从根本上杜绝注入。

// PHP PDO 示例
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = :email');
$stmt->execute(['email' => $email]);
# Python MySQLdb 示例
cursor.execute("SELECT * FROM users WHERE email = %s", (email,))

注意:表名、列名、排序方向(ASC/DESC)不能作为参数绑定,必须使用白名单校验。

2.2 使用 ORM 框架

现代 ORM(如 Hibernate、SQLAlchemy、Eloquent)默认使用参数化查询。但需警惕 ORM 中的“原生 SQL”方法,例如 Django 的 raw()extra(),若拼接了用户输入,依然会引入注入。

2.3 输入验证与转义(辅助手段)

  • 类型转换:对于数字型参数,强制使用 intval()(int) 转换。
  • 白名单:对于 ORDER BY 字段,只允许预定义的列名。
  • 转义函数:如 PHP 的 mysqli_real_escape_string,但需注意字符集问题,且不能用于所有场景。转义不能替代参数化查询

2.4 最小权限原则

数据库账户应仅授予必要的权限。例如,Web 应用账户不应有 DROPFILE 等权限,这样即使发生注入,攻击者也无法执行危险操作。

在代码审计中,搜索 mysql_querymysqli_queryquery( 等关键字,检查其参数是否来自用户输入且未经过预处理。

三、Linux 服务器安全加固清单

即使应用层防御完善,服务器层面的加固也不可或缺。以下是一份可落地的检查清单:

3.1 账户与认证

  • 禁用 root 远程登录:修改 /etc/ssh/sshd_config,设置 PermitRootLogin no
  • 使用密钥认证,禁用密码登录:PasswordAuthentication no
  • 为所有用户设置强密码策略,定期清理无用账户。
  • 启用 sudo 并记录日志,避免直接使用 root。

3.2 网络与防火墙

  • 使用 iptablesfirewalld 仅开放必要端口(如 80、443、SSH 端口)。
  • 修改 SSH 默认端口,减少自动化扫描。
  • 部署 Fail2ban,自动封禁暴力破解 IP。
  • 关闭不必要的服务(如 FTP、Telnet),使用 ss -tulnp 检查监听端口。

3.3 系统与软件更新

  • 定期执行 apt update && apt upgradeyum update
  • 启用自动安全更新(如 unattended-upgrades)。
  • 订阅 CVE 公告,及时修补内核与关键组件。

3.4 文件系统与权限

  • 设置关键目录权限:/etc 为 644,/root 为 700。
  • 使用 chattr +i 锁定关键文件(如 /etc/passwd/etc/shadow)。
  • 禁用 SUID/SGID 不必要的二进制文件:find / -perm -4000 -type f 排查。

3.5 日志与监控

  • 启用 auditd 记录关键系统调用。
  • 集中收集日志到远程服务器,防止本地日志被清除。
  • 使用 logwatchossec 进行异常行为告警。

3.6 Web 服务器专项

  • 隐藏版本号:Nginx 中设置 server_tokens off
  • 限制请求方法:仅允许 GET、POST、HEAD。
  • 配置 WAF(如 ModSecurity)作为纵深防御。

结语

XSS 与 SQL 注入的防御并非一劳永逸,而是贯穿于代码编写、审计、部署和运维的每一个环节。从代码审计角度出发,核心思路是:追踪不可信数据的流动路径,在输出和查询时采用上下文相关的安全处理。同时,配合服务器加固清单,形成多层防御体系,才能有效降低安全风险。希望本文的梳理能为你的日常开发与审计工作提供一份实用的参考。

未经允许不得转载:任鹏个人博客 » 从代码审计角度识别 XSS 与 SQL 注入:一份面向开发者的防御指南

赞 (0) 打赏

评论 0

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

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

支付宝扫一扫打赏

微信扫一扫打赏