Skip to content

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用户提交恶意脚本到数据库输入时转义特殊字符
反射型XSSURL参数携带恶意代码输出时使用框架安全方法(如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

防御三原则

  1. 永远使用参数化查询
  2. 禁止拼接用户输入到SQL语句
  3. 限制数据库账号权限(如仅授予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年后活跃开发的框架

知识回顾

  1. 输入校验:前端校验仅为用户体验,后端必须二次验证。
  2. XSS防御:HTML转义、框架安全方法、CSP策略。
  3. SQL注入:参数化查询彻底杜绝拼接风险。
  4. DDoS应对:CDN+防火墙+速率限制+熔断机制。
  5. 框架选择:现代框架内置安全机制,避免使用2015年前的框架。

课后练习

  1. (单选)以下哪种方式能彻底防止SQL注入?

    • A. 在输入前添加'转义
    • B. 使用参数化查询
    • C. 限制输入长度
    • D. 以上都不对
  2. (操作)将以下代码改造为XSS安全版本:

typescript
@Component
export default class Comment extends Vue {
    @Prop() content!: string;

    render() {
        return <div dangerouslySetInnerHTML={{ __html: this.content }} />;
    }
}
  1. (分析)为什么说eval()函数是服务器安全的定时炸弹?
参考答案
  1. B
  2. typescript
    import { escape } from 'he';
    
    @Component
    export default class Comment extends Vue {
        @Prop() content!: string;
    
        render() {
            return <div>{escape(this.content)}</div>;
        }
    }
  3. eval()会直接执行任意代码,攻击者可通过构造恶意字符串远程执行命令,导致服务器被完全控制。

扩展阅读

Built by Vitepress | Apache 2.0 Licensed