4. Web安全面试题
OWASP Top 10 并不是一份“漏洞排行榜”,而是对 Web 应用最常见、危害最大的十类安全风险的归纳。面试中,面试官通常不会只问“Top 10 有哪些”,而是会挑其中一两类,追问原理、利用链、代码层成因和修复方案。因此,本章不按条目平铺直叙,而是围绕“输入不可信”这一主线,把注入、失效的访问控制、加密失败、SSRF 等高频考点串起来讲清楚。
一、注入类漏洞:从 SQL 注入看“数据变代码”
注入的本质,是应用把用户可控的数据当成了代码或指令的一部分执行。以 SQL 注入为例,假设登录接口的查询语句是字符串拼接:
SELECT id, username FROM users
WHERE username = '${username}' AND password = '${password}';
当攻击者提交 username=admin'--、password=任意值 时,实际执行的语句变为:
SELECT id, username FROM users
WHERE username = 'admin'--' AND password = '任意值';
-- 在多数数据库中是行注释符,密码条件被注释掉,攻击者无需正确密码即可登录。若接口返回数据库报错,还可通过联合查询 UNION SELECT 逐列探测表名、字段名,再读取 users 表中的口令哈希。盲注场景下,攻击者则通过 AND SUBSTRING(...)='a' 这类布尔条件或时间函数 SLEEP(3) 推断数据。
防御的核心不是过滤关键字,而是让数据永远不进入代码通道。正确做法是使用参数化查询:
SELECT id, username FROM users
WHERE username = ? AND password = ?;
参数值由数据库驱动单独绑定,即使输入包含引号或注释符,也只被当作普通字符串。工程上还应做到:数据库账号最小权限,Web 账号不授予 FILE、DROP 等权限;关闭详细报错,统一返回自定义错误页;对输入做类型和长度校验作为纵深防御,但不能替代参数化。命令注入、LDAP 注入、模板注入(SSTI)同理,分别对应 Runtime.exec、目录查询和模板引擎的表达式求值,修复思路都是“不拼接、用安全 API、白名单校验”。
二、失效的访问控制与身份认证缺陷
失效的访问控制长期位居 Top 10 前列,典型表现是水平越权和垂直越权。水平越权指用户 A 能访问用户 B 的资源,例如订单查询接口 GET /api/order?orderId=1002,服务端只校验了“已登录”,没有校验“该订单属于当前用户”。攻击者把 orderId 改成 1003 即可读取他人订单。垂直越权则是普通用户访问管理员接口,如直接请求 POST /admin/deleteUser。
修复要点是“服务端强制、默认拒绝”。每个敏感操作都应在服务端确认当前会话主体与目标资源的归属关系,例如在查询时把 user_id 作为条件:
SELECT * FROM orders WHERE id = ? AND user_id = ?;
仅靠前端隐藏按钮或菜单不构成防护。身份认证方面,常见缺陷包括:允许弱口令、登录无失败次数限制、会话 ID 未在登录后重新生成(导致会话固定)、JWT 未校验签名或允许 alg=none。面试中若被问到 JWT,应说明:签名密钥必须足够强且服务端保管,校验时固定算法,exp、iss、aud 都要验证,敏感操作仍需二次校验,不能把 JWT 当作万能凭证。
三、加密失败与敏感数据暴露
加密失败涵盖传输层和存储层。传输层应全站 HTTPS,并启用 HSTS,避免降级到 HTTP。存储层最常见的问题是口令明文或弱哈希保存。MD5、SHA-1 已不适合口令存储,应使用 bcrypt、scrypt 或 Argon2 这类带盐、可调工作因子的算法。示例参数:bcrypt 工作因子取 12,单次哈希耗时约数百毫秒,可在安全与体验间取得平衡(该数值为常见工程建议,实际需按服务器性能压测确定)。
另一个高频点是硬编码密钥。若代码仓库中出现数据库口令、API Key、JWT 密钥,一旦仓库泄露即全盘失守。应改用环境变量或密钥管理服务,并定期轮换。面试时可补充:加密不等于编码,Base64 只是编码,可逆且不提供机密性。
四、SSRF:让服务器替你发请求
SSRF 常出现在图片抓取、Webhook、URL 预览等功能。若接口 POST /fetch 接收 url 参数并由服务端请求,攻击者可提交 http://169.254.169.254/latest/meta-data/ 读取云主机元数据,进而获取临时凭证;也可探测内网 http://10.0.0.5:6379 等未授权服务。
防御应遵循:只允许白名单域名和协议(仅 http/https),解析目标 IP 后拒绝内网网段(如 10.0.0.0/8、172.16.0.0/12、192.168.0.0/16、127.0.0.0/8、169.254.0.0/16),禁止跟随跳转,或对跳转后地址再次校验。注意 DNS 重绑定攻击:校验时解析为公网 IP,实际请求时又解析到内网,因此应在连接层固定已校验的 IP。
五、实战案例:一次越权读取的排查闭环
假设某电商系统收到报告:普通用户可通过修改 orderId 读取他人订单。排查步骤如下。第一,复现:用账号 A 登录,获取自己的订单 ID 1001,再请求 1002,观察是否返回他人收货地址。第二,定位:查看订单查询的控制器代码,确认是否只做了登录校验。第三,修复:在查询条件中加入当前用户 ID,并补充单元测试。第四,验证:用账号 A 请求 1002,应返回 404 或 403,而非数据;同时确认账号 A 请求自己的 1001 仍正常。第五,回归:检查其他类似接口(地址、发票、物流)是否存在同样问题。
这个闭环体现了面试答题的加分点:不仅说“加权限校验”,还能说清复现条件、修复位置、验证判据和横向排查范围。
六、可直接使用的面试速查表
| 风险类别 | 典型入口 | 核心防御 | 验证判据 |
|---|---|---|---|
| SQL 注入 | 登录、搜索、排序参数 | 参数化查询、最小权限 | 输入 ' OR '1'='1 不再改变语义 |
| 失效访问控制 | 订单、用户、文件 ID | 服务端校验资源归属 | 越权请求返回 403/404 |
| 加密失败 | 口令存储、传输 | bcrypt、全站 HTTPS | 数据库中无明文口令 |
| SSRF | URL 抓取、Webhook | 白名单、禁内网、禁跳转 | 请求元数据地址被拒绝 |
回答 Top 10 类问题时,建议采用“原理一句话 + 利用条件 + 修复动作 + 验证方式”的结构。原理讲清数据与代码的边界,利用讲清前置条件(如是否回显、是否有权限),修复落到具体 API 或配置,验证给出可观察的判据。这样既体现知识深度,也体现工程落地能力。