网络安全
问题
网络传输过程中有哪些安全威胁?HTTPS 如何保证安全?
答案
网络安全涉及数据在传输过程中的机密性、完整性和身份认证。
安全威胁概览
中间人攻击(MITM)
攻击原理
常见形式
| 类型 | 说明 | 场景 |
|---|---|---|
| ARP 欺骗 | 伪造 MAC 地址 | 局域网 |
| DNS 劫持 | 篡改 DNS 解析 | 公共 Wi-Fi |
| SSL 剥离 | 降级 HTTPS 到 HTTP | 不安全网络 |
| 证书伪造 | 使用假证书 | 安装了恶意根证书 |
HTTPS 安全机制
三大保障
| 保障 | 实现方式 | 防御威胁 |
|---|---|---|
| 机密性 | 对称加密(AES) | 窃听 |
| 完整性 | MAC/数字签名 | 篡改 |
| 身份认证 | 数字证书 | 冒充 |
TLS 握手过程
密钥交换
// 为什么不直接用非对称加密?
// 非对称加密(RSA)慢,对称加密(AES)快
// 解决方案:用非对称加密交换对称密钥
// 密钥协商过程(简化)
const clientRandom = generateRandom(); // 客户端随机数
const serverRandom = generateRandom(); // 服务器随机数
const preMasterSecret = generateSecret(); // 预主密钥
// 主密钥 = PRF(预主密钥, "master secret", 客户端随机数 + 服务器随机数)
const masterSecret = deriveKey(preMasterSecret, clientRandom, serverRandom);
// 会话密钥派生
const sessionKey = deriveSessionKey(masterSecret);
数字证书
证书内容
interface Certificate {
// 证书版本
version: number;
// 序列号
serialNumber: string;
// 签名算法
signatureAlgorithm: string;
// 颁发者
issuer: {
commonName: string;
organization: string;
};
// 有效期
validity: {
notBefore: Date;
notAfter: Date;
};
// 主体
subject: {
commonName: string; // 域名
};
// 公钥
publicKey: string;
// 扩展(SAN)
subjectAltName: string[];
// 颁发者签名
signature: string;
}
证书链验证
// 验证过程
function verifyCertificate(cert: Certificate, chain: Certificate[]): boolean {
// 1. 检查证书是否过期
const now = new Date();
if (now < cert.validity.notBefore || now > cert.validity.notAfter) {
return false;
}
// 2. 检查域名是否匹配
if (!matchDomain(cert.subject.commonName, requestHost)) {
return false;
}
// 3. 验证签名链
for (let i = 0; i < chain.length - 1; i++) {
const current = chain[i];
const issuer = chain[i + 1];
if (!verifySignature(current, issuer.publicKey)) {
return false;
}
}
// 4. 检查根证书是否在信任列表
const rootCert = chain[chain.length - 1];
return isTrustedRoot(rootCert);
}
证书类型
| 类型 | 验证级别 | 显示 | 价格 |
|---|---|---|---|
| DV (Domain) | 域名所有权 | 🔒 | 免费/低 |
| OV (Organization) | 域名 + 组织 | 🔒 + 公司名 | 中 |
| EV (Extended) | 严格验证 | 🔒 + 绿色公司名 | 高 |
前向安全(PFS)
为什么需要前向安全?
// 没有 PFS 的情况
// 1. 攻击者记录所有加密流量
// 2. 未来某天私钥泄露
// 3. 攻击者可以解密所有历史流量
// 有 PFS 的情况
// 每次连接使用临时密钥(DH/ECDHE)
// 会话密钥不依赖长期私钥
// 私钥泄露不影响历史会话
ECDHE 密钥交换
HSTS
HTTP 严格传输安全
// 响应头
// Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
// 作用:
// 1. 浏览器自动将 HTTP 升级为 HTTPS
// 2. 阻止用户绕过证书警告
// 3. 防止 SSL 剥离攻击
HSTS 预加载
// 首次访问前就强制 HTTPS
// 提交到 HSTS Preload List
// https://hstspreload.org/
// 要求:
// 1. 有效的 HTTPS 证书
// 2. 所有子域名都支持 HTTPS
// 3. HSTS 头包含 preload 指令
常见安全头
// 安全响应头配置
const securityHeaders = {
// HTTPS 强制
'Strict-Transport-Security': 'max-age=31536000; includeSubDomains',
// 防止 XSS
'X-Content-Type-Options': 'nosniff',
'X-XSS-Protection': '1; mode=block',
// 防止点击劫持
'X-Frame-Options': 'DENY',
// CSP 内容安全策略
'Content-Security-Policy': "default-src 'self'",
// 防止 MIME 类型嗅探
'X-Content-Type-Options': 'nosniff',
// Referrer 策略
'Referrer-Policy': 'strict-origin-when-cross-origin'
};
常见面试问题
Q1: HTTPS 是如何保证安全的?
答案:
HTTPS = HTTP + TLS,提供三重保护:
| 保护 | 机制 | 说明 |
|---|---|---|
| 机密性 | 对称加密(AES) | 数据加密传输 |
| 完整性 | HMAC | 防止数据被篡改 |
| 身份认证 | 数字证书 | 验证服务器身份 |
Q2: 中间人攻击是什么?如何防御?
答案:
中间人攻击:攻击者在客户端和服务器之间拦截、篡改通信。
防御措施:
| 措施 | 说明 |
|---|---|
| HTTPS | 加密传输 + 证书验证 |
| HSTS | 强制 HTTPS |
| 证书固定 | 绑定证书指纹 |
| 公钥固定 | 绑定公钥(已弃用) |
// 证书固定(移动端常用)
const pinnedCerts = ['sha256/ABC...', 'sha256/DEF...'];
function verifyPinning(serverCert: string): boolean {
const certHash = sha256(serverCert);
return pinnedCerts.includes(certHash);
}
Q3: 什么是前向安全?
答案:
前向安全(Forward Secrecy):即使长期私钥泄露,也无法解密历史通信。
实现方式:
- 使用临时密钥(ECDHE、DHE)
- 每次会话密钥独立
- 会话密钥用后销毁
// ❌ 无前向安全(RSA 密钥交换)
// 私钥泄露 → 解密所有历史流量
// ✅ 有前向安全(ECDHE)
// 私钥泄露 → 只能解密未来流量,历史安全
Q4: HTTPS 首次访问为什么还可能被攻击?
答案:
SSL 剥离攻击:
- 用户输入
example.com(HTTP) - 中间人拦截,返回 HTTP 页面
- 中间人与服务器建立 HTTPS
- 用户全程使用 HTTP,攻击者可窃听
防御:
- HSTS:告知浏览器只用 HTTPS
- HSTS Preload:首次访问前就强制 HTTPS
- 用户习惯:主动输入
https://
Q5: 如何验证网站的 HTTPS 是否安全?
答案:
# 1. 检查证书信息
openssl s_client -connect example.com:443
# 2. 检查 TLS 版本和加密套件
nmap --script ssl-enum-ciphers -p 443 example.com
# 3. 在线检测工具
# https://www.ssllabs.com/ssltest/
检查点:
- ✅ 证书有效且未过期
- ✅ 证书链完整
- ✅ 支持 TLS 1.2/1.3
- ✅ 使用强加密套件
- ✅ 支持前向安全
- ✅ 启用 HSTS