第一层 security(Web 安全)面试题
本面试题按难度分为 基础、进阶、高级 三个层级,共 22 道,每道题均附参考答案与评分要点。
一、基础题(共 8 道)
参考答案:
XSS(Cross-Site Scripting,跨站脚本攻击)是指攻击者向网页注入恶意脚本,当其他用户浏览该页面时,浏览器会执行这些脚本,从而达到窃取 Cookie、会话劫持、钓鱼、挖矿等目的。
常见类型:
- 反射型 XSS:恶意脚本通过 URL 参数传入,服务器立即返回并在页面中执行,通常需要诱骗用户点击恶意链接。
- 存储型 XSS:恶意脚本被持久化到服务器(数据库、文件、缓存),所有访问该资源的用户都会触发。
- DOM 型 XSS:恶意脚本不经过服务器,而是通过前端 JavaScript 对 URL、Hash、localStorage 等数据的不安全处理被写入 DOM。
评分维度:
- 能说明 XSS 本质是恶意脚本注入(20%)
- 能区分三种类型并举例(50%)
- 提到反射型依赖 URL、存储型持久化、DOM 型在前端触发(30%)
参考答案:
- 输出编码:根据输出上下文进行 HTML、JavaScript、URL、CSS 编码。
- 输入校验:限制输入格式、长度、类型,但仅作为辅助,不能替代输出编码。
- 使用前端框架:React、Vue、Angular 等框架默认对插值进行转义。
- CSP(内容安全策略):限制可执行脚本来源,禁止内联脚本。
- HttpOnly Cookie:防止 JavaScript 读取 Cookie,降低 XSS 危害。
- 避免危险 API:不使用
innerHTML、document.write、eval()、new Function()处理不可信数据。 - 富文本白名单过滤:使用 DOMPurify 等工具对富文本进行过滤。
评分维度:
- 提到输出编码是核心防御(25%)
- 提到 CSP、HttpOnly Cookie(25%)
- 提到前端框架转义(15%)
- 提到避免危险 API 和富文本过滤(20%)
- 表达清晰、有条理(15%)
参考答案:
CSRF(Cross-Site Request Forgery,跨站请求伪造)是指攻击者诱导已登录用户访问恶意网站,恶意网站自动向目标网站发起请求。由于浏览器会自动附带目标网站的 Cookie,服务器会误以为是用户的合法操作。
区别:
| 对比项 | XSS | CSRF |
|---|---|---|
| 核心 | 注入并执行恶意脚本 | 伪造用户请求 |
| 是否需要执行脚本 | 是 | 否 |
| 是否能读取 Cookie | 能(除非 HttpOnly) | 不能直接读取 |
| 防御重点 | 输入输出编码、CSP | CSRF Token、SameSite Cookie |
评分维度:
- 能准确描述 CSRF 攻击流程(30%)
- 能从至少三个维度区分 XSS 和 CSRF(50%)
- 提到浏览器自动携带 Cookie 是 CSRF 的关键(20%)
参考答案:
- CSRF Token:服务器生成随机 Token,嵌入表单或请求头中,后端校验。
- SameSite Cookie:设置
SameSite=Lax或Strict,限制跨站请求携带 Cookie。 - 双重 Cookie 验证:前端读取 Cookie 中的随机值,放入请求头,后端比较一致性。
- 校验 Referer/Origin:检查请求来源是否合法,仅作为辅助手段。
- 二次确认:对敏感操作要求用户再次输入密码、短信验证码等。
评分维度:
- 能说出 CSRF Token 和 SameSite Cookie(40%)
- 能解释双重 Cookie 验证原理(25%)
- 提到 Referer/Origin 校验和二次确认(20%)
- 说明各手段的适用场景(15%)
参考答案:
CSP(Content Security Policy,内容安全策略)是一种安全机制,通过 HTTP 响应头告诉浏览器哪些来源的资源可以加载、哪些脚本可以执行。
防御 XSS 的方式:
- 限制
script-src只允许特定来源,禁止内联脚本和eval()。 - 使用
nonce或hash允许特定的内联脚本。 - 通过
report-uri或report-to收集违规报告。
示例:
Content-Security-Policy: default-src 'self'; script-src 'self'; frame-ancestors 'none'
评分维度:
- 能解释 CSP 基本概念(25%)
- 能说明 CSP 通过限制脚本来源防御 XSS(35%)
- 提到 nonce/hash、report-uri 等进阶用法(25%)
- 能给出配置示例(15%)
参考答案:
点击劫持(Clickjacking)是指攻击者通过 iframe 将目标网站透明覆盖在诱导页面上,诱使用户点击目标网站的敏感按钮。
防御手段:
- X-Frame-Options:
DENY:禁止任何页面嵌入。SAMEORIGIN:仅允许同源嵌入。
- CSP frame-ancestors:
Content-Security-Policy: frame-ancestors 'none' - UI 冗余校验:对敏感操作增加二次确认或验证码。
评分维度:
- 能描述点击劫持原理(30%)
- 能说出 X-Frame-Options 两个取值(25%)
- 能说出 CSP frame-ancestors 用法(25%)
- 提到 UI 冗余校验(20%)
参考答案:
HTTPS = HTTP + TLS/SSL,主要优势:
- 加密通信:防止数据被窃听。
- 完整性校验:通过 MAC 检测数据是否被篡改。
- 身份认证:通过数字证书验证服务器身份,防止钓鱼和 MITM。
评分维度:
- 能说出加密、完整性、身份认证三点(各 30%)
- 提到 TLS 是 HTTP 的安全层(10%)
参考答案:
- Secure:Cookie 只在 HTTPS 连接中传输,防止明文传输被窃听。
- HttpOnly:禁止 JavaScript 通过
document.cookie读取 Cookie,降低 XSS 窃取 Cookie 的风险。 - SameSite:控制 Cookie 在跨站请求中的发送行为,
Strict完全禁止跨站携带,Lax允许部分安全导航,None允许跨站但需配合 Secure。
评分维度:
- 三个属性解释正确(各 30%)
- 能说明 SameSite 三个取值的区别(10%)
二、进阶题(共 8 道)
参考答案:
- 用户在前端点击"第三方登录"按钮。
- 前端将用户重定向到授权服务器:
https://auth-server.com/authorize? response_type=code &client_id=xxx &redirect_uri=yyy &scope=user &state=随机值 - 用户在授权服务器登录并同意授权。
- 授权服务器重定向回
redirect_uri,并附带授权码code和state:https://app.com/callback?code=abc&state=随机值 - 前端校验
state是否与会话一致,防止 CSRF。 - 前端把
code发送给己方后端。 - 后端用
client_id+client_secret+code向授权服务器换取 Access Token。 - 后端用 Access Token 请求用户信息,完成登录态建立。
评分维度:
- 能按顺序描述完整流程(40%)
- 提到
state的作用和校验(20%) - 说明
client_secret应由后端保管(15%) - 提到 Access Token 的换取和使用(15%)
- 表达逻辑清晰(10%)
参考答案:
PKCE(Proof Key for Code Exchange)是 OAuth 2.0 的扩展,主要用于公共客户端(如移动 App、SPA)。
解决的问题:
- 在授权码模式中,如果授权码被恶意应用截获,攻击者可以冒充客户端换取 Access Token。
- 公共客户端无法安全保存
client_secret,且重定向 URI 可能被其他应用监听或拦截。
PKCE 流程:
- 客户端生成一个随机字符串
code_verifier。 - 用哈希算法生成
code_challenge。 - 授权请求时携带
code_challenge。 - 换取 Token 时携带原始
code_verifier,授权服务器验证其哈希是否与code_challenge一致。
这样即使授权码被截获,没有 code_verifier 也无法换取 Token。
评分维度:
- 能说明 PKCE 用于公共客户端(20%)
- 能解释授权码截获问题(25%)
- 能描述 code_verifier 和 code_challenge 的生成与验证(40%)
- 说明为什么 SPA/移动端需要 PKCE(15%)
参考答案:
MITM(Man-in-the-Middle,中间人攻击)是指攻击者拦截客户端与服务器之间的通信,进行窃听、篡改或冒充。
HTTPS 防御 MITM 的方式:
- 加密:TLS 使用非对称加密交换密钥,对称加密传输数据,攻击者即使截获也无法解密。
- 完整性校验:TLS 记录层使用 MAC(消息认证码),篡改数据会被检测出来。
- 身份认证:服务器提供由 CA 签发的数字证书,客户端验证证书链和域名,防止攻击者冒充服务器。
评分维度:
- 能解释 MITM 攻击(20%)
- 从加密、完整性、身份认证三方面说明 HTTPS 防御(60%)
- 提到证书链验证(20%)
参考答案:
HSTS(HTTP Strict Transport Security)是一种安全机制,服务器通过响应头告诉浏览器在一段时间内必须始终使用 HTTPS 访问站点。
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
max-age:HSTS 生效时间(秒)。includeSubDomains:对子域名也生效。preload:加入浏览器的预加载列表。
SSL 剥离攻击是指 MITM 把 HTTPS 连接降级为 HTTP。HSTS 一旦生效,浏览器会自动把 HTTP 请求升级为 HTTPS,即使攻击者拦截首次 HTTP 请求,已访问过该站点的浏览器也不会再发送明文 HTTP 请求。
评分维度:
- 能解释 HSTS 作用(25%)
- 能解释 SSL 剥离攻击(25%)
- 说明 HSTS 如何防止首次访问后的降级(30%)
- 提到 preload 列表的作用(20%)
参考答案:
dangerouslySetInnerHTML 是 React 中直接设置原始 HTML 的 API,它会绕过 React 的默认转义机制。如果传入的内容包含用户输入,就会导致 XSS。
安全使用方式:
- 尽量避免使用:能用
textContent或普通 JSX 表达就用普通方式。 - 必须使用时先做白名单过滤:例如使用 DOMPurify 清洗 HTML。
import DOMPurify from 'dompurify'; const safeHtml = DOMPurify.sanitize(rawHtml); return <div dangerouslySetInnerHTML={{ __html: safeHtml }} />; - 配合 CSP:限制可执行脚本的来源。
评分维度:
- 能说明 bypass React 转义(25%)
- 能给出 DOMPurify 示例(35%)
- 提到尽量避免使用(20%)
- 提到 CSP 配合(20%)
参考答案:
| 存储方式 | 优点 | 缺点 | 安全建议 |
|---|---|---|---|
| localStorage | 容量大、简单易用 | 易被 XSS 读取,不会随请求自动携带 | 避免存储敏感 Token |
| sessionStorage | 页面关闭后清除 | 同样易被 XSS 读取 | 仅存储非敏感临时数据 |
| Cookie | 可设 HttpOnly、Secure、SameSite | 容量小,每次请求都会携带 | 敏感 Token 使用 httpOnly + Secure + SameSite |
建议:
- Access Token 可以短期保存在内存中,减少持久化风险。
- Refresh Token 应放在 httpOnly Cookie 中。
- 尽量避免把 JWT 长期存在 localStorage 中。
评分维度:
- 能对比三种存储方式的优劣(50%)
- 提到 XSS 对 localStorage 的威胁(20%)
- 给出合理的安全存储建议(30%)
参考答案:
CSP 默认禁止内联脚本,但很多业务需要内联脚本。nonce 和 hash 允许在禁止内联脚本的前提下,执行特定的合法脚本。
-
Nonce:服务器每次响应生成一个随机字符串,合法的
<script>标签带上这个 nonce,CSP 头中声明该 nonce。Content-Security-Policy: script-src 'nonce-abc123'<script nonce="abc123">console.log('ok');</script> -
Hash:计算合法内联脚本的哈希值,CSP 头中声明允许该哈希对应的脚本执行。
Content-Security-Policy: script-src 'sha256-xxxxxxxx'
解决的问题:在需要少量内联脚本的业务中,既保持 CSP 的防护能力,又不完全禁止内联脚本。
评分维度:
- 能解释 nonce 原理和示例(35%)
- 能解释 hash 原理(25%)
- 说明它们用于允许特定内联脚本(25%)
- 提到 nonce 需要每次随机生成(15%)
参考答案:
简单请求:满足特定条件(如 GET/POST/HEAD、特定 Content-Type、无自定义头)的跨域请求,浏览器直接发送,并在请求头中附带 Origin。
预检请求:对于非简单请求,浏览器先发送 OPTIONS 预检请求,询问服务器是否允许该跨域请求,服务器返回允许的源、方法、头信息后,浏览器才发送真正的请求。
前端配置 CORS 的安全注意事项:
- 服务端
Access-Control-Allow-Origin不要滥用*,尤其是当请求携带凭证时。 - 携带凭证时,必须明确指定允许的 Origin,并设置
Access-Control-Allow-Credentials: true。 - 不要在前端代码中暴露敏感的服务端密钥。
- 对允许跨域的 Origin 做白名单校验。
评分维度:
- 能区分简单请求和预检请求(35%)
- 说明预检请求使用 OPTIONS 方法(15%)
- 提到 CORS 与凭证的安全配置(35%)
- 提到 Origin 白名单(15%)
三、高级题(共 6 道)
参考答案:
常见绕过手段:
- 大小写绕过:
<ScRiPt>,过滤不严谨时可能绕过。 - 编码绕过:HTML 实体编码、URL 编码、Unicode 编码、JS 编码等。
- 事件处理器绕过:不使用
<script>,而用<img src=x onerror=...>、<svg onload=...>、<iframe onload=...>等。 - 属性引号绕过:
onmouseover=alert(1)不加引号。 - 协议绕过:
javascript:、data:text/html等伪协议。 - 模板注入绕过:在 Vue、Angular 等模板中利用表达式注入,如
{{constructor.constructor('alert(1)')()}}。 - CSP 绕过:利用内联事件、JSONP、
unsafe-eval、base64 图片等白名单配置缺陷。
应对策略:
- 不要依赖黑名单过滤,优先使用白名单。
- 在输出点做严格编码,不要仅在输入点过滤。
- 使用 DOMPurify 等成熟库处理富文本。
- 配置严格的 CSP,避免
'unsafe-inline'和'unsafe-eval'。 - 对模板表达式做沙箱化处理。
- 启用 HttpOnly Cookie 降低危害。
评分维度:
- 能列举至少 4 种绕过手段(40%)
- 提到黑名单不可靠、白名单优先(20%)
- 提到输出编码和 CSP 的重要性(25%)
- 能给出具体防御建议(15%)
参考答案:
设计要点:
-
登录流程:
- 使用 httpsOnly Cookie 保存会话标识。
- 登录表单加入 CSRF Token,或设置
SameSite=Lax/Strict。 - 对登录接口做限流和验证码,防止暴力破解。
-
会话管理:
- 设置合理的 Cookie 过期时间。
- 使用双 Token 机制:Access Token 短期有效,Refresh Token 长期保存在 httpOnly Cookie 中。
- 关键操作前校验用户身份(二次认证)。
-
转账等敏感操作:
- 强制使用 POST 请求。
- 每个敏感操作表单都带 CSRF Token。
- 设置
SameSite=Strict。 - 要求用户输入支付密码或短信验证码。
- 校验 Referer/Origin 作为辅助。
-
监控与告警:
- 对异常 IP、设备、地理位置的敏感操作进行风控拦截。
评分维度:
- 登录和转账都有 CSRF 防御措施(30%)
- 提到双 Token 和 httpOnly Cookie(20%)
- 提到二次认证和风控(25%)
- 兼顾用户体验,避免过度打扰(15%)
- 方案完整、逻辑清晰(10%)
参考答案:
CSP 常见绕过风险:
- 白名单域名存在 JSONP 端点:攻击者可以利用该域名返回任意脚本。
unsafe-inline或unsafe-eval:允许内联脚本或动态代码执行,大幅降低防护。data:协议滥用:data:text/javascript,...可执行脚本。- 通配符
*:允许任意来源,等于没有 CSP。 script-src包含不受信任的 CDN:CDN 被攻陷后,页面也会加载恶意脚本。- base-uri 未限制:攻击者可以通过
<base>标签改变相对路径脚本加载地址。
有效 CSP 配置建议:
Content-Security-Policy:
default-src 'none';
script-src 'self' https://trusted-cdn.com;
style-src 'self';
img-src 'self' data:;
connect-src 'self' https://api.example.com;
font-src 'self';
frame-ancestors 'none';
base-uri 'self';
form-action 'self';
report-uri /csp-report
- 尽量使用
'self'和明确白名单。 - 限制
base-uri和form-action。 - 使用
report-uri或report-to持续监控。
评分维度:
- 能列举至少 3 种 CSP 绕过风险(35%)
- 能给出严格 CSP 配置示例(30%)
- 提到 base-uri、form-action、report-uri(20%)
- 说明持续监控的重要性(15%)
参考答案:
评估与降低风险的措施:
-
来源评估:
- 优先选择知名、可信的第三方服务商。
- 检查其安全记录、隐私政策和数据处理方式。
-
加载方式:
- 使用子资源完整性(SRI)校验脚本文件是否被篡改:
<script src="https://third.com/analytics.js" integrity="sha384-xxx" crossorigin="anonymous"></script> - 不使用动态注入脚本的方式加载第三方代码。
- 使用子资源完整性(SRI)校验脚本文件是否被篡改:
-
CSP 限制:
- 将第三方域名加入
script-src白名单。 - 限制其只能连接特定的上报域名(
connect-src)。 - 禁止其嵌入 iframe 或操作表单。
- 将第三方域名加入
-
数据隔离:
- 不在第三方脚本可访问的页面中暴露敏感数据。
- 对第三方脚本使用独立的子域或沙箱 iframe。
-
监控审计:
- 定期审查第三方脚本的网络行为。
- 使用 CSP 报告收集违规信息。
评分维度:
- 提到 SRI 和来源评估(30%)
- 提到 CSP 限制和域名白名单(25%)
- 提到数据隔离和沙箱(20%)
- 提到监控审计(15%)
- 方案可行、考虑周全(10%)
参考答案:
TLS 握手简化流程(以 TLS 1.2 为例):
- 客户端发送 ClientHello,包含支持的 TLS 版本、加密套件列表、客户端随机数。
- 服务器返回 ServerHello,包含选定的加密套件、服务器随机数、服务器证书。
- 客户端验证证书,生成预主密钥(Pre-Master Secret),用服务器公钥加密后发送。
- 服务器用私钥解密得到预主密钥。
- 双方根据预主密钥和两个随机数生成会话密钥。
- 后续通信使用会话密钥对称加密。
TLS 1.3 简化了握手,减少了往返次数,并废弃了一些不安全的算法。
前向保密(Forward Secrecy):
前向保密要求即使服务器私钥在未来被泄露,也无法解密之前的通信记录。实现方式是每次握手生成临时的密钥交换参数(如 ECDHE),而不是使用固定的 RSA 密钥加密预主密钥。
重要性:
- 防止"先记录、后解密"的攻击。
- 降低私钥泄露带来的历史数据风险。
评分维度:
- 能描述 TLS 握手主要步骤(35%)
- 能解释前向保密概念(25%)
- 说明为什么 ECDHE 能实现前向保密(25%)
- 提到 TLS 1.3 的改进(15%)
参考答案:
一、输入输出规范
- 所有用户输入(URL、表单、Cookie、Storage、postMessage)均视为不可信。
- 输出时根据上下文编码:HTML 用
escapeHtml,JS 用JSON.stringify,URL 用encodeURIComponent。 - 富文本内容必须使用 DOMPurify 等白名单过滤。
二、DOM 操作规范
- 禁止使用
innerHTML、document.write插入不可信数据,优先使用textContent。 - 禁止
eval()、new Function()、setTimeout(string)。 - 对第三方 DOM 操作进行审查。
三、Cookie 与存储规范
- 敏感 Cookie 必须设置
HttpOnly; Secure; SameSite=Lax/Strict。 - Token 不长期存储在 localStorage 中,敏感 Token 使用 httpOnly Cookie。
四、依赖与构建规范
- 使用
npm audit定期检查依赖漏洞。 - 锁定依赖版本,使用私有仓库或可信源。
- 对第三方脚本启用 SRI。
五、安全配置规范
- 部署 CSP、HSTS、X-Frame-Options、X-Content-Type-Options 等响应头。
- CORS 配置严格限制 Origin,不滥用
*。
六、认证授权规范
- 前端校验只用于体验提升,核心校验必须后端完成。
- 敏感操作需要二次确认或 MFA。
七、安全培训与审计
- 定期组织安全培训。
- 对新功能做安全评审,定期进行代码审计和渗透测试。
评分维度:
- 覆盖输入输出、DOM、Cookie、依赖、配置、认证授权(60%)
- 提到具体可落地的检查项(20%)
- 提到培训和审计机制(10%)
- 结构清晰、适合团队落地(10%)
难度分布与评分建议
结语
Web 安全是前端工程师的重要基本功。通过本面试题的练习,建议读者不仅记住概念,更要理解攻击原理、防御机制和实际落地方法。在面试中,能够结合项目经验给出具体案例,往往比背诵定义更有说服力。
领域编号:F05 Web 安全
最后更新:2026-06-24