在 Web 安全领域,跨站脚本攻击(XSS)和 SQL 注入(SQLi)长期占据 OWASP Top 10 的显著位置。尽管开发框架和防护手段不断演进,这两类漏洞依然是渗透测试和代码审计中最常被发现的“常客”。本文将从安全测试的视角出发,梳理如何主动发现 XSS 与 SQL 注入问题,并给出前端防御、MySQL 安全写法以及 Linux 服务器加固的实用清单。
一、XSS 的常见方式与前端防御
XSS 的本质是攻击者将恶意脚本注入到网页中,当其他用户浏览该页面时,脚本在用户浏览器中执行。根据注入方式的不同,XSS 主要分为三类:
- 反射型 XSS:恶意脚本作为请求参数发送给服务器,服务器未经过滤直接“反射”回响应页面。常见于搜索框、错误提示、跳转链接等场景。测试时可以在参数中插入
<script>alert(1)</script>或"><img src=x onerror=alert(1)>,观察是否被原样输出并执行。 - 存储型 XSS:恶意脚本被持久化存储在服务器端(如数据库、评论、用户资料),所有访问该页面的用户都会触发。这类漏洞危害最大,常见于留言板、论坛、个人签名等。测试时需要提交含脚本的内容,然后重新访问页面查看是否执行。
- DOM 型 XSS:漏洞完全发生在客户端 JavaScript 中,服务器响应本身不包含恶意脚本。例如代码中使用
document.write(location.hash)或innerHTML直接处理不可信数据。测试时可通过修改 URL 的 hash 或参数,观察 DOM 操作是否导致脚本执行。
前端如何防御 XSS?
前端防御的核心原则是“永远不要信任用户输入,对输出进行上下文感知的编码”。具体措施包括:
- 输出编码:根据输出位置(HTML 标签内、属性内、JavaScript 内、CSS 内、URL 内)采用不同的编码方式。例如 HTML 实体编码将
<转为<,>转为>。 - 使用安全的 API:优先使用
textContent而非innerHTML,使用setAttribute而非直接拼接属性字符串。现代框架如 React、Vue 默认对插值进行转义,但dangerouslySetInnerHTML和v-html仍需谨慎使用。 - 内容安全策略(CSP):通过 HTTP 响应头
Content-Security-Policy限制脚本来源,禁止内联脚本执行,可有效缓解 XSS 的影响。 - 输入验证与白名单:对用户输入进行格式校验,例如邮箱、URL、数字等,只允许符合预期的字符通过。
- HttpOnly Cookie:为敏感 Cookie 设置
HttpOnly属性,防止 JavaScript 通过document.cookie读取,降低会话劫持风险。
二、MySQL 防止 SQL 注入的几种写法
SQL 注入产生的根源是应用程序将用户输入直接拼接到 SQL 语句中,导致攻击者可以改变语句语义。在 MySQL 环境下,防止 SQL 注入的写法有以下几种,按推荐程度从高到低排列:
1. 参数化查询(预处理语句)—— 最推荐
使用 Prepared Statement 将 SQL 语句与数据分离,数据库先编译语句结构,再绑定参数。无论参数内容如何,都不会被解释为 SQL 代码。
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = :email AND status = :status');
$stmt->execute(['email' => $email, 'status' => $status]);
Java 中的 PreparedStatement、Python 中的 cursor.execute(sql, params)、Node.js 中的 connection.execute(sql, values) 均属此类。这是防御 SQL 注入最有效、最根本的方法。
2. 使用 ORM 框架
ORM(如 Hibernate、MyBatis、Sequelize、Django ORM)通常内置参数化机制,只要不拼接原生 SQL,就能避免注入。但需注意:MyBatis 中 #{} 是参数化,${} 是字符串拼接,后者存在注入风险。
3. 输入验证与类型转换
对用户输入进行严格校验,例如 id 参数强制转换为整数:
$id = (int)$_GET['id'];
$sql = "SELECT * FROM articles WHERE id = $id";
这种方式仅适用于简单场景,不能替代参数化查询。
4. 转义特殊字符
使用 mysqli_real_escape_string() 或 PDO::quote() 对输入进行转义。但这种方式容易遗漏,且与字符集设置相关,不推荐作为主要防御手段。
5. 最小权限原则
为数据库连接账户分配最小必要权限,例如只读账户禁止 DROP、UPDATE,即使发生注入也能限制危害范围。
安全测试提示:测试 SQL 注入时,可以尝试在参数中插入 '、"、1' OR '1'='1、1 AND SLEEP(5) 等 payload,观察是否出现数据库报错、页面异常或响应延迟。使用 SQLMap 等工具可自动化检测,但需在授权范围内进行。
三、Linux 服务器安全加固清单
Web 应用的安全不仅取决于代码,服务器环境同样关键。以下是一份实用的 Linux 服务器安全加固清单:
账户与认证
- 禁用 root 远程 SSH 登录,使用普通用户 +
sudo提权。 - 配置 SSH 密钥认证,禁用密码登录(
PasswordAuthentication no)。 - 修改 SSH 默认端口,减少自动化扫描。
- 使用
fail2ban自动封禁多次登录失败的 IP。 - 定期审计用户账户,删除无用账户和过期密钥。
系统更新与补丁
- 启用自动安全更新(如
unattended-upgrades)。 - 定期执行
apt update && apt upgrade或yum update。 - 订阅安全公告,及时修复内核和关键组件漏洞。
网络与防火墙
- 使用
iptables、nftables或ufw配置最小开放端口策略。 - 仅暴露必要的服务端口(如 80、443),数据库端口(3306)禁止公网访问。
- 使用 WAF(如 ModSecurity)过滤恶意请求。
服务与权限
- 以最小权限运行 Web 服务(如
www-data用户),禁止使用 root 运行 Nginx/Apache。 - 关闭不必要的服务(如 FTP、Telnet),卸载无用软件包。
- 配置文件权限:敏感文件设为
600,目录设为750,避免全局可写。
日志与监控
- 启用并集中管理日志(
/var/log/auth.log、/var/log/nginx/access.log)。 - 使用
auditd监控关键文件变更。 - 部署入侵检测系统(如 OSSEC、Wazuh)和文件完整性监控。
MySQL 服务器加固
- 删除匿名用户和测试数据库。
- 禁止
LOAD DATA LOCAL INFILE。 - 为每个应用分配独立数据库账户,遵循最小权限。
- 启用慢查询日志和错误日志,定期审查异常 SQL。
结语
发现 XSS 与 SQL 注入问题,既需要掌握测试方法,也需要理解防御原理。安全测试的价值在于主动暴露风险,而防御的价值在于从源头消除漏洞。前端做好输出编码与 CSP,后端坚持参数化查询与最小权限,服务器层面持续加固与监控,三者结合才能构建起纵深防御体系。安全不是一次性的任务,而是贯穿开发、测试、运维全生命周期的持续过程。
未经允许不得转载:任鹏个人博客 » 如何用安全测试发现 XSS 与 SQL 注入问题


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