E16. 服务器安全
6.1. 用户输入和前端校验是不可靠的
前端校验是用户体验的盾,不是服务器的安全锁!
6.1.1. 危险的前端信任示例
typescript
// 错误示例:仅依赖前端校验
// 前端表单验证代码
function validateForm(input: string) {
if (input.length < 8) {
alert("密码长度需≥8位!");
return false;
}
return true; // 信任前端校验直接提交
}
// 后端未验证导致漏洞
// Node.js示例(伪代码)
app.post('/login', (req, res) => {
const { password } = req.body;
if (password === 'admin') { // 未验证直接逻辑判断
res.send('Admin Access!');
}
});
6.1.2. 正确防御方案
typescript
// 前端校验仅做用户体验优化
function validateForm(input: string) {
// 同上,但明确标注仅为客户端提示
}
// 后端严格二次验证
app.post('/login', (req, res) => {
const { password } = req.body;
if (typeof password !== 'string' || password.length < 8) {
return res.status(400).send("密码格式错误");
}
// 继续执行安全逻辑
});
DANGER
致命误区:
- 前端校验可绕过(如通过Postman直接请求)
- 后端必须对所有输入进行类型检查和格式验证
- 避免将敏感逻辑(如权限判断)放在前端
6.2. 网页开发谨防 XSS 攻击
用户的输入可能是毒药,必须经过严格消毒!
6.2.1. XSS 攻击示例
typescript
// 错误示例:直接拼接用户输入
// Vue.js组件
@Component
export default class Comment extends Vue {
@Prop() content!: string;
render() {
return <div dangerouslySetInnerHTML={{ __html: this.content }} />;
}
}
// 攻击者输入:
// <script>alert('XSS')</script>
6.2.2. 安全编码规范
typescript
// 正确方案:使用框架内置的HTML转义
import { escape } from 'he'; // 安全HTML转义库
@Component
export default class Comment extends Vue {
@Prop() content!: string;
render() {
return <div>{escape(this.content)}</div>; // 自动转义特殊字符
}
}
攻击类型 | 危害示例 | 防御方法 |
---|---|---|
存储型XSS | 用户提交恶意脚本到数据库 | 输入时转义特殊字符 |
反射型XSS | URL参数携带恶意代码 | 输出时使用框架安全方法(如React的dangerouslySetInnerHTML慎用) |
DOM型XSS | 动态修改DOM节点 | 严格限制innerHTML 的使用场景 |
6.3. 数据库开发谨防 SQL 注入攻击
SQL注入就像毒蛇,参数化查询是唯一解药!
6.3.1. SQL注入漏洞示例
typescript
// 错误示例:拼接SQL语句
// Node.js + MySQL示例
const query = `SELECT * FROM users WHERE username = '${username}'`;
// 攻击输入:
// username = ' OR ''=' --
// 最终查询:SELECT * FROM users WHERE username = '' OR ']=' (注释掉后续条件)
6.3.2. 安全查询方案
typescript
// 正确方案:使用参数化查询
import { createPool } from 'mysql2/promise';
const pool = createPool({ /* 配置信息 */ });
async function getUser(username: string) {
const [rows] = await pool.query(
'SELECT * FROM users WHERE username = ?', // 参数占位符
[username] // 参数数组自动转义
);
return rows[0];
}
TIP
防御三原则:
- 永远使用参数化查询
- 禁止拼接用户输入到SQL语句
- 限制数据库账号权限(如仅授予SELECT/INSERT权限)
6.4. DDoS 攻击及平台应对
DDoS攻击是洪水猛兽,需多层防御体系!
6.4.1. 典型攻击场景
bash
# 攻击者发起UDP Flood攻击
for i in {1..10000}; do
curl -X POST "http://target.com/api/call-expensive-operation"
done
6.4.2. 多层防御策略
mermaid
graph LR
A[CDN层] -->|流量清洗| B[Web应用防火墙(WAF)]
B --> C[服务器防火墙]
C --> D[速率限制]
D --> E[熔断机制]
具体实现示例
typescript
// 速率限制中间件(Express示例)
import rateLimit from 'express-rate-limit';
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15分钟
max: 100, // 每IP最多100次请求
message: "Too many requests from this IP, please try later"
});
app.use(limiter);
6.5. 使用高安全性框架有助于避免损失
框架选择决定安全基线,老旧技术债是定时炸弹!
6.5.1. 旧框架的脆弱性示例
typescript
// Express 3.x时代代码(存在原型污染漏洞)
app.use(cookieParser()); // 未配置安全选项
// 攻击者构造Cookie:__proto__[admin]=true
// 导致所有用户获得管理员权限
6.5.2. 现代框架的防护机制
typescript
// NestJS框架示例(内置安全配置)
@Module({
imports: [
CookieParserModule.register({
verify: (cookie) => !cookie.startsWith('__proto__') // 自定义验证
})
]
})
export class AppModule {}
框架类型 | 安全特性对比 | 推荐版本 |
---|---|---|
老旧框架 | 无默认XSS防护/SQL注入防御 | Express 3.x、ASP.NET MVC 4 |
现代框架 | 内置CSRF防护/参数化查询 | Next.js、NestJS、Django 4+ |
WARNING
技术债务警示:
- 2024年仍有企业使用Express 2.x导致原型污染漏洞
- 老旧框架需持续投入人力维护补丁,成本远高于迁移新框架
- 新项目必须选择2020年后活跃开发的框架
知识回顾
- 输入校验:前端校验仅为用户体验,后端必须二次验证。
- XSS防御:HTML转义、框架安全方法、CSP策略。
- SQL注入:参数化查询彻底杜绝拼接风险。
- DDoS应对:CDN+防火墙+速率限制+熔断机制。
- 框架选择:现代框架内置安全机制,避免使用2015年前的框架。
课后练习
(单选)以下哪种方式能彻底防止SQL注入?
- A. 在输入前添加
'
转义 - B. 使用参数化查询
- C. 限制输入长度
- D. 以上都不对
- A. 在输入前添加
(操作)将以下代码改造为XSS安全版本:
typescript
@Component
export default class Comment extends Vue {
@Prop() content!: string;
render() {
return <div dangerouslySetInnerHTML={{ __html: this.content }} />;
}
}
- (分析)为什么说
eval()
函数是服务器安全的定时炸弹?
参考答案
- B
- typescript
import { escape } from 'he'; @Component export default class Comment extends Vue { @Prop() content!: string; render() { return <div>{escape(this.content)}</div>; } }
eval()
会直接执行任意代码,攻击者可通过构造恶意字符串远程执行命令,导致服务器被完全控制。