Web 安全面试扫盲
这份文档是给你补 Web 安全基础的,不追求讲到漏洞利用专家级别。目标是:面试官提到常见漏洞时,你能知道它在说什么、代码里大概看哪里、修复方向是什么,并且不要把话说太满。
1. SQL 注入
SQL 注入就是用户输入改变了 SQL 语句本来的语义。最典型的情况是把用户名、搜索词、排序字段直接拼进 SQL 字符串里。
典型代码味道:
代码审查时重点看三件事:输入是否来自 HTTP 参数、表单或 JSON;它最后是否进入数据库查询;中间有没有参数化查询、ORM 安全 API 或白名单校验。特别要注意 ORDER BY、表名、列名这类地方,因为它们有时不能直接参数化,需要白名单。
修复方向通常是参数化查询、prepared statement、ORM 的安全查询接口,以及对排序字段这类动态结构做 allowlist。
面试可以这么说:SQLi 的核心不是“输入里有引号”,而是攻击者能不能改变 SQL AST 或查询语义。只做字符串 replace 很脆,真正稳的是参数化和白名单。
常见 CWE:CWE-89。
2. XSS
XSS 是攻击者控制的内容被浏览器当成 HTML 或 JavaScript 执行。它常见分三类:stored XSS 存在数据库里,reflected XSS 从请求参数反射出来,DOM XSS 主要发生在前端脚本处理 URL、hash、localStorage 等数据时。
典型场景包括评论、帖子内容、用户昵称、搜索结果、富文本、Markdown 渲染、错误提示。React 里要特别小心 dangerouslySetInnerHTML;后端模板里要看有没有关闭默认 escaping。
代码审查时要看:数据从哪里来,最后进入 HTML、属性、URL、CSS 还是 JS 字符串上下文。不同上下文需要不同编码,不能简单说“escape 一下”。
修复方向包括输出编码、使用模板/框架默认 escaping、富文本 sanitize、限制允许标签和属性、避免直接插入 HTML。CSP 可以降低影响,但不能当成根本修复。
面试可以这么说:XSS 修复重点在输出上下文,不是把所有用户输入都禁掉。比如同一个字符串进入 HTML body、href、script 里,安全处理方式是不一样的。
常见 CWE:CWE-79。
3. SSRF
SSRF 可以先按这个故事理解:后端有时确实需要主动访问外部资源,比如拉取第三方头像、同步远程图片、调用用户配置的 webhook、从对象存储或外部服务导入文件。风险出在“后端要访问哪里”这件事被用户输入或外部配置控制了。正常情况下目标是公网资源;攻击者会把目标换成内网地址,比如 http://localhost:...、公司内网服务、云厂商 metadata 地址。
问题在于,请求不是从攻击者电脑发出去的,而是从服务器发出去的。服务器能访问的网络范围通常比外部用户更大,所以攻击者等于借服务器的身份和网络位置去探测内网。
典型场景是 URL preview、webhook test、图片抓取、从 URL 导入、PDF 截图服务、开放代理。云环境里尤其要注意 metadata 地址,比如 169.254.169.254。
代码审查时要看:用户能不能控制服务端要访问的 URL;有没有允许 http://localhost、127.0.0.1、内网 IP、link-local 地址;有没有允许奇怪协议;是否跟随重定向;DNS 解析后有没有重新校验真实 IP。
修复方向是 allowlist 优先,限制协议为 http/https,禁止 private IP、localhost、link-local,限制重定向并在每次跳转后重新校验,必要时通过安全代理出网。
面试可以这么说:SSRF 的关键不是“服务器发了一个请求”,而是攻击者控制了服务器要请求哪里。服务器可能访问得到内网和云 metadata,所以必须限制目标地址。只校验字符串里的 host 不够,因为 DNS、重定向、IPv6、编码都可能绕过。
常见 CWE:CWE-918。
4. IDOR / 越权访问
IDOR 是用户通过改对象 ID 访问或操作不属于自己的对象。比如用户 A 把 /api/posts/123/delete 改成 /api/posts/124/delete,如果后端只检查登录、不检查所有权,就会越权。
典型场景包括订单详情、帖子删除、文件下载、用户资料、发票、组织成员管理、后台对象编辑。
代码审查时要看:路由里拿到对象 ID 后,数据库查询有没有加 owner / tenant / organization 条件;权限判断是在服务端做还是只在前端隐藏按钮;管理员和普通用户路径有没有混在一起;对象是否属于当前用户或当前租户。
修复方向是在服务端做 authorization check。不要靠隐藏 ID、前端按钮、随机 UUID 或“用户一般猜不到”来防。更稳的方式是查询时绑定当前用户或租户,比如 WHERE id = ? AND owner_id = current_user.id。
面试可以这么说:认证只回答“你是谁”,授权回答“你能不能操作这个对象”。IDOR 通常就是认证有了,但对象级授权没做。
常见 CWE:CWE-639、CWE-862、CWE-863。
5. 路径穿越
路径穿越是用户控制文件名或路径,通过 ../、编码、绝对路径、符号链接等方式读写到允许目录之外。
典型场景包括文件下载、头像上传、静态文件服务、日志查看、压缩包解压、模板加载。
代码审查时要看:用户输入是否参与路径拼接;有没有只做简单字符串替换;是否处理 URL decode、多轮 decode、Windows 路径分隔符、绝对路径、符号链接;最终路径是否真正落在允许目录下。
修复时优先用框架或语言提供的安全 API,不要自己手搓字符串规则。比如 Web 框架常有 send_from_directory、safe_join 这类工具;Node 里常见做法是 path.resolve(base, userPath) 后检查结果仍在 base 下;Python 可以用 Path.resolve() 后做目录边界判断。
如果没有现成安全 API,基本思路是:先把路径解析成 canonical absolute path,再检查它是否仍在允许目录内。文件上传时还要重命名文件,不信任原始文件名。压缩包解压要逐个 entry 检查目标路径。
面试可以这么说:路径穿越不能只靠删掉 ../,因为编码、绝对路径、Windows 分隔符、符号链接都可能绕过。更稳的是用框架安全 API;没有 API 时,resolve 成真实路径后做目录边界检查。
常见 CWE:CWE-22。
6. 反序列化
不安全反序列化是程序把不可信输入还原成对象时,触发了构造函数、魔术方法、类加载或其他危险逻辑。严重时会导致远程代码执行。
典型危险格式包括 Python pickle、Java native serialization、PHP object serialization、Ruby Marshal。JSON 本身通常不是同一类问题,但如果 JSON 里带类型名再动态实例化,也可能有类似风险。
代码审查时要看:反序列化数据是否来自 cookie、请求体、缓存、消息队列、上传文件;是否允许任意类;有没有签名校验;反序列化后是否立刻进入敏感操作。
修复方向是不要反序列化不可信数据,改用 JSON 等简单数据格式;必须用时要做签名、类型白名单、隔离执行和最小权限。
面试可以这么说:反序列化的危险点不只是“读了一个对象”,而是对象恢复过程中可能执行代码或构造出攻击者想要的对象图。
常见 CWE:CWE-502。
7. JWT
JWT 是一种带签名的 token。签名能证明 token 没被篡改,但不代表 token 里的权限设计一定正确。
常见问题包括弱 secret、硬编码 secret、接受 alg=none、算法混淆、不过期、不校验 issuer / audience、把敏感信息放进 payload、token 泄露后缺少撤销机制。
代码审查时要看:验证时是否固定允许算法;secret 是否足够强并来自安全配置;是否校验 exp、iss、aud;是否把 role、user_id 这类字段直接当最终权限依据;登出、改密、封禁后 token 是否仍长期有效。
修复方向是固定算法、强 secret 或非对称密钥、校验标准 claims、缩短过期时间、必要时引入 refresh token 和服务端撤销列表。权限仍然要在服务端根据当前用户和资源重新判断。
面试可以这么说:JWT 最大的误区是“签了名就安全”。签名只保证 token 没被改,权限是否合理、secret 是否安全、token 是否应该继续有效,是另外的问题。
8. CSRF
CSRF 的问题描述可以这样拆:用户已经登录了目标网站,目标网站用 cookie 识别登录态;用户又打开了一个恶意网页;恶意网页让浏览器向目标网站发起一个状态变更请求,比如改邮箱、删帖子、退出登录;浏览器发请求时会自动带上目标网站的 cookie。服务器如果只看 cookie,就会以为这是用户自己在目标网站里点的操作。
所以 CSRF 的关键不是攻击者偷到了 cookie,也不是攻击者能读响应。关键是:攻击者能借用户的浏览器发出一个带登录态的请求,而服务器分不清这个请求是用户在本站页面主动发的,还是第三方恶意页面诱导发的。
CSRF 一般需要这些条件同时成立:
- 目标站点主要靠 cookie 做身份认证。
- 某个敏感接口会改变状态,比如改资料、下单、删除资源。
- 这个接口没有额外校验请求来源或 CSRF token。
- 第三方页面能构造出这个请求,比如普通表单、图片请求、自动提交表单等。
典型场景包括修改邮箱、修改密码、转账、下单、删除资源、退出登录。只要认证依赖 cookie,并且接口缺少额外校验,就要考虑 CSRF。
代码审查时要看:敏感操作是否只靠 cookie 认证;接口是否接受普通表单就能提交;有没有 CSRF token;是否检查 Origin / Referer;cookie 的 SameSite 设置是什么。还要注意 GET 请求不应该做状态变更。
HTTP 请求里确实有一些能辅助判断来源的字段,比如 Origin、Referer,现代浏览器还会带 Sec-Fetch-Site 这类 Fetch Metadata 头。问题是服务端必须主动检查这些字段,否则它们只是请求头里的信息,不会自动阻止 CSRF。实际防护里常见做法是:对状态变更接口校验 Origin / Referer 是否来自本站;同时配合 CSRF token 和 SameSite cookie。不要只依赖一个头,因为某些请求或隐私策略下 Referer 可能缺失。
修复方向包括 CSRF token、SameSite cookie、Origin / Referer 校验、对敏感操作要求非简单请求或二次确认。CSRF token 的作用是让第三方页面猜不到一个随请求提交的随机值;SameSite cookie 则是让浏览器在跨站请求时少带或不带 cookie。
面试可以这么说:CSRF 是“借用户浏览器发请求”。攻击者不一定能读响应,关键是浏览器会自动带 cookie。防护重点是让服务器能区分“用户真实页面发起的请求”和“第三方页面诱导发起的请求”。
常见 CWE:CWE-352。
9. 权限绕过
权限绕过比 IDOR 更宽,指攻击者绕过认证、角色、租户、状态机或业务规则,执行本不该执行的操作。
典型场景包括普通用户改 role、未审核用户访问审核后功能、跨租户读数据、只在前端隐藏管理入口、后台路由漏挂鉴权中间件、对象状态不允许修改但接口没检查。
代码审查时要看:路由是否挂了正确中间件;权限判断是否在服务端;角色字段是否能被用户更新;多租户查询是否绑定 tenant;业务状态是否被检查;前端权限和后端权限是否一致。
修复方向是把权限判断放在服务端统一入口或关键业务函数里;对象级权限和租户边界要进入查询条件;敏感字段要做 allowlist 更新;不要信任前端传来的 role、owner、tenant。
面试可以这么说:权限问题最麻烦的是它通常不是某一行危险 API,而是路由、用户态、数据模型和业务规则组合起来才成立。所以它比普通 sink 型漏洞更需要跨文件理解。
常见 CWE:CWE-862、CWE-863、CWE-284。
10. 敏感信息暴露
敏感信息暴露是系统把不该给攻击者看的信息返回、记录或提交到了不安全位置。常见包括 password hash、token、secret、debug stack trace、内部路径、配置、云密钥、用户隐私字段。
典型场景包括 API 返回整个 user 对象、日志打印登录失败密码、debug endpoint 暴露环境变量、前端 bundle 里出现 secret、错误页带堆栈。
代码审查时要看:响应序列化是否使用安全 DTO;日志有没有脱敏;debug 功能是否在生产环境关闭;secret 是否硬编码;错误处理是否暴露内部信息。
修复方向是响应字段白名单、日志脱敏、关闭生产 debug、secret 从环境或 secret manager 读取、错误响应统一化。
面试可以这么说:password hash 泄露也算敏感信息暴露,因为 hash 不是明文密码,但一旦泄露就可以离线爆破,而且用户复用密码时影响会扩大。
常见 CWE:CWE-200、CWE-209、CWE-359、CWE-798。
11. CWE 怎么讲
CWE 是漏洞类型分类,不是漏洞存在的证据。比如 SQL 注入常见对应 CWE-89,路径穿越对应 CWE-22,CSRF 对应 CWE-352。
面试里可以说:CWE 的价值是让报告标准化,方便沟通“这是哪类弱点”。但判断漏洞必须先看代码、数据流、权限边界和可达性,不能因为描述里写了某个 CWE 就认为漏洞已经成立。
12. CVSS 怎么讲
CVSS 是严重性评分标准,不负责判断漏洞真假。它回答的是:如果这个漏洞成立,它的技术严重性大概如何。
CVSS 会考虑攻击复杂度、是否需要权限、是否需要用户交互、影响范围、机密性/完整性/可用性影响等因素。它适合做排序和报告,但不能替代业务风险判断。
面试可以这么说:CWE 是“这是什么类型的问题”,CVSS 是“这个问题有多严重”。两者都不是漏洞证明,漏洞证明还是要靠代码和攻击路径。
13. 不确定时的回答模板
如果被问到某个漏洞细节你不确定,可以用这个框架:
我会先看攻击者能控制什么输入,这个输入最后进入了什么危险操作,期间有没有足够的防护。然后再看它是否真实可达,以及权限边界、业务状态和部署环境会不会影响利用条件。
这套说法比较稳,因为大多数 Web 漏洞都离不开 input、dangerous operation、guard、reachability 这几件事。