在 Web 安全领域,XSS(跨站脚本攻击)和 SQL 注入长期占据 OWASP Top 10 的显著位置。尽管这两类漏洞的原理并不复杂,但在实际代码审计中,它们依然是最常被发现的缺陷。本文将从代码审计的视角出发,系统梳理这两类漏洞的识别方法与防御策略,并附带一份 Linux 服务器安全加固清单,帮助开发者和运维人员构建更稳固的防线。
一、XSS 的常见方式与前端防御
1.1 代码审计中常见的 XSS 形态
在审计前端代码时,XSS 通常出现在数据从“不可信来源”流向“危险汇聚点”的路径上。常见类型包括:
- 反射型 XSS:恶意脚本作为请求参数的一部分,被服务器直接“反射”回响应页面。审计时重点关注 URL 参数是否未经转义就插入 HTML。
- 存储型 XSS:恶意数据被持久化到数据库(如评论、用户昵称),在其他用户访问时执行。这是危害最大的一类,审计时需追踪所有写入数据库的字段。
- DOM 型 XSS:漏洞完全发生在客户端,JavaScript 从
location.hash、document.referrer等来源读取数据,并直接写入innerHTML、document.write或eval。
1.2 前端防御的核心原则
前端防御 XSS 的核心是 “永远不要信任用户输入,始终进行上下文相关的输出编码”。具体措施包括:
- 输出编码:根据数据插入的位置(HTML 正文、属性、URL、JavaScript 变量)采用不同的编码方式。例如,插入 HTML 正文时转义
<、>、&、"、';插入 URL 时使用encodeURIComponent。 - 避免危险 API:禁止使用
innerHTML、outerHTML、document.write直接插入不可信数据。优先使用textContent或createElement+appendChild。 - 使用 CSP:内容安全策略(Content-Security-Policy)可以限制脚本来源,即使存在 XSS 漏洞,也能大幅降低危害。建议设置
script-src 'self'并禁用unsafe-inline。 - 输入验证与白名单:对用户输入进行格式校验,例如邮箱、手机号等,但输入验证不能替代输出编码。
在代码审计中,可以搜索 innerHTML、dangerouslySetInnerHTML(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 应用账户不应有 DROP、FILE 等权限,这样即使发生注入,攻击者也无法执行危险操作。
在代码审计中,搜索 mysql_query、mysqli_query、query( 等关键字,检查其参数是否来自用户输入且未经过预处理。
三、Linux 服务器安全加固清单
即使应用层防御完善,服务器层面的加固也不可或缺。以下是一份可落地的检查清单:
3.1 账户与认证
- 禁用 root 远程登录:修改
/etc/ssh/sshd_config,设置PermitRootLogin no。 - 使用密钥认证,禁用密码登录:
PasswordAuthentication no。 - 为所有用户设置强密码策略,定期清理无用账户。
- 启用
sudo并记录日志,避免直接使用 root。
3.2 网络与防火墙
- 使用
iptables或firewalld仅开放必要端口(如 80、443、SSH 端口)。 - 修改 SSH 默认端口,减少自动化扫描。
- 部署 Fail2ban,自动封禁暴力破解 IP。
- 关闭不必要的服务(如 FTP、Telnet),使用
ss -tulnp检查监听端口。
3.3 系统与软件更新
- 定期执行
apt update && apt upgrade或yum 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记录关键系统调用。 - 集中收集日志到远程服务器,防止本地日志被清除。
- 使用
logwatch或ossec进行异常行为告警。
3.6 Web 服务器专项
- 隐藏版本号:Nginx 中设置
server_tokens off。 - 限制请求方法:仅允许 GET、POST、HEAD。
- 配置 WAF(如 ModSecurity)作为纵深防御。
结语
XSS 与 SQL 注入的防御并非一劳永逸,而是贯穿于代码编写、审计、部署和运维的每一个环节。从代码审计角度出发,核心思路是:追踪不可信数据的流动路径,在输出和查询时采用上下文相关的安全处理。同时,配合服务器加固清单,形成多层防御体系,才能有效降低安全风险。希望本文的梳理能为你的日常开发与审计工作提供一份实用的参考。
未经允许不得转载:任鹏个人博客 » 从代码审计角度识别 XSS 与 SQL 注入:一份面向开发者的防御指南


朋友圈点赞图在线生成源码