OWASP Top 10 深度解析

深度解析 OWASP Top 10 2021 安全风险:注入、失效访问控制、加密失败、不安全设计、安全配置错误、易受攻击组件、身份识别与认证失败、软件和数据完整性失败、安全日志与监控失败、服务端请求伪造(SSRF)的原理、攻击方式和防御方案。

OWASP(Open Web Application Security Project)Top 10 是全球最具影响力的 Web 应用安全风险清单,每 3-4 年更新一次。2021 版本反映了现代云原生、微服务、DevOps 时代的新威胁。本文逐项深度解析每个风险的原理与防御方案。


1. A01:2021 失效的访问控制(Broken Access Control)

1.1 风险描述

访问控制确保用户只能执行其权限范围内的操作。当访问控制失效时,攻击者可以访问未授权的功能或数据。

1.2 常见漏洞

水平越权:
GET /api/orders/12345  → 正常访问自己的订单
GET /api/orders/12346  → 未验证是否属于自己,看到他人订单!

垂直越权:
普通用户访问管理员接口:
POST /admin/delete-user  → 未验证角色,普通用户也能调用!

不安全的直接对象引用(IDOR):
GET /documents?id=1001 → 通过遍历 id 获取他人文件

1.3 防御方案

@RestController
public class OrderController {
    @GetMapping("/api/orders/{orderId}")
    public Order getOrder(@PathVariable Long orderId, 
                          @AuthenticationPrincipal User user) {
        Order order = orderService.findById(orderId);
        // ✅ 必须验证资源归属
        if (!order.getUserId().equals(user.getId())) {
            throw new AccessDeniedException();
        }
        return order;
    }
}

// 全局方案:
// 1. 默认拒绝(Deny by Default)
// 2. 最小权限原则
// 3. 服务端验证权限(不信任客户端)
// 4. 使用成熟的 RBAC/ABAC 框架

2. A02:2021 加密机制失效(Cryptographic Failures)

2.1 风险描述

敏感数据(密码、信用卡、PII)因加密不当而被泄露。

2.2 常见漏洞

❌ 明文存储密码
❌ 使用 MD5/SHA1 哈希密码(可被彩虹表破解)
❌ 硬编码密钥在代码中
❌ 使用弱加密算法(DES/RC4)
❌ 不验证 TLS 证书
❌ 在 URL 中传输敏感数据

2.3 防御方案

// ✅ 密码哈希:BCrypt / Argon2 / PBKDF2
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(12); // strength=12
String hashed = encoder.encode("user_password");
boolean matches = encoder.matches("user_password", hashed);

// ✅ 敏感数据加密(AES-256-GCM)
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey, gcmParameterSpec);

// ✅ HTTPS 强制
server:
  ssl:
    enabled: true
    protocol: TLS
    enabled-protocols: TLSv1.2,TLSv1.3

3. A03:2021 注入(Injection)

3.1 SQL 注入

// ❌ 字符串拼接(危险!)
String sql = "SELECT * FROM users WHERE name = '" + username + "'";
// username = "' OR '1'='1" → 绕过认证

// ✅ 预处理语句
String sql = "SELECT * FROM users WHERE name = ?";
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setString(1, username);

3.2 其他注入类型

类型示例防御
NoSQL 注入db.users.find({name: {$gt: ''}})参数化查询、输入验证
OS 命令注入Runtime.exec("ping " + ip)禁止拼接命令、使用 API
LDAP 注入恶意过滤条件参数化 LDAP 查询
XPath 注入操纵 XML 查询参数化 XPath
Expression 注入SPEL/OGNL 注入禁用表达式、沙箱

4. A04:2021 不安全设计(Insecure Design)

4.1 风险描述

安全设计缺陷无法通过完美实现来修复,必须在架构阶段考虑安全。

4.2 反例与正例

❌ 不安全设计:
- 业务逻辑中假设用户总是按正常流程操作
- 无业务流校验(跳过步骤、重复提交)
- 缺少安全的需求分析

✅ 安全设计原则:
- 威胁建模(Threat Modeling)
- 安全需求作为功能需求的一部分
- 关键业务步骤状态机校验
- 业务逻辑边界检查

4.3 威胁建模 STRIDE

威胁描述示例
Spoofing身份伪装伪造 JWT Token
Tampering数据篡改修改请求参数
Repudiation否认操作无审计日志
Information Disclosure信息泄露返回敏感错误信息
Denial of Service拒绝服务慢查询攻击
Elevation of Privilege权限提升普通用户变管理员

5. A05:2021 安全配置错误(Security Misconfiguration)

5.1 常见错误

❌ 默认密码未修改(admin/admin)
❌ 调试模式在生产环境开启
❌ 不必要的功能/端口/服务暴露
❌ 错误信息泄露敏感信息(堆栈跟踪、SQL语句)
❌ 缺少安全响应头
❌ CORS 配置过于宽松:Access-Control-Allow-Origin: *

5.2 安全基线配置

# Spring Boot 安全配置
server:
  error:
    whitelabel:
      enabled: false  # 禁用默认错误页
    include-stacktrace: never
    include-message: never

management:
  endpoints:
    web:
      exposure:
        include: health,info  # 不暴露 sensitive endpoints
      base-path: /admin/actuator  # 隐藏路径
      
security:
  headers:
    content-security-policy: "default-src 'self'"
    x-content-type-options: nosniff
    x-frame-options: DENY
    strict-transport-security: max-age=31536000; includeSubDomains

6. A06:2021 易受攻击和过时的组件(Vulnerable and Outdated Components)

6.1 供应链风险

依赖树风险:
Your App
├── dependency A v1.0 (有 CVE-2024-1234)
│   └── dependency B v2.1 (有 CVE-2024-5678)
└── dependency C v3.0 (安全)

 Log4j2 事件(2021):流行的日志框架存在 RCE 漏洞
 影响范围:几乎所有 Java 应用

6.2 防御方案

# 使用依赖扫描工具
# Maven
mvn org.owasp:dependency-check-maven:check

# npm
npm audit
yarn audit

# Gradle
./gradlew dependencyCheckAnalyze

# Snyk 持续监控
snyk monitor
snyk test

# GitHub Dependabot
# 自动创建 PR 升级有漏洞的依赖

7. A07:2021 身份识别与认证失败(Identification and Authentication Failures)

7.1 常见漏洞

❌ 允许弱密码(123456)
❌ 无多因素认证(MFA)
❌ 会话管理不当(无超时、固定会话 ID)
❌ 凭证恢复/密码重置流程不安全
❌ 使用明文传输凭证
❌ 登录爆破无防护(无验证码、无速率限制)

7.2 安全认证实现

// 登录速率限制(Bucket4j)
Bucket bucket = Bucket.builder()
    .addLimit(Bandwidth.classic(5, Refill.intervally(5, Duration.ofMinutes(1))))
    .build();

if (!bucket.tryConsume(1)) {
    throw new TooManyRequestsException("登录尝试过多,请稍后再试");
}

// JWT 安全配置
@Bean
public JwtDecoder jwtDecoder() {
    NimbusJwtDecoder decoder = NimbusJwtDecoder.withJwkSetUri(jwkUri).build();
    decoder.setJwtValidator(JwtValidators.createDefaultWithIssuer(issuer));
    return decoder;
}
// - 使用 RS256(非对称加密)
// - 设置合理的 exp(15分钟)
// - 包含 jti 用于撤销
// - HTTPS only

8. A08:2021 软件和数据完整性失败(Software and Data Integrity Failures)

8.1 风险描述

应用基于不可信来源的假设做出关键决策,如:

  • 不安全的反序列化
  • 无验证的依赖拉取
  • CI/CD 管道被篡改

8.2 不安全的反序列化

// ❌ Java 原生反序列化(危险!)
ObjectInputStream ois = new ObjectInputStream(input);
Object obj = ois.readObject(); // 可执行任意代码!

// ✅ 使用 JSON 替代(Jackson + 类型白名单)
ObjectMapper mapper = new ObjectMapper();
mapper.activateDefaultTyping(
    BasicPolymorphicTypeValidator.builder()
        .allowIfBaseType(Object.class)
        .build(),
    ObjectMapper.DefaultTyping.NON_FINAL
);

// 更好的方案:明确类型,不使用多态
User user = mapper.readValue(json, User.class);

8.3 CI/CD 安全

# 验证依赖签名
- name: Verify signatures
  run: |
    gpg --verify artifact.jar.asc artifact.jar
    
# SLSA 供应链层级
# Level 1: 构建过程脚本化
# Level 2: 使用版本控制和托管构建服务
# Level 3: 构建环境安全隔离 + 源码完整性
# Level 4: 双人员审查 + 可复现构建

9. A09:2021 安全日志与监控失败(Security Logging and Monitoring Failures)

9.1 为什么重要

“你无法保护你看不见的东西。” 攻击者在被检测前平均在系统中潜伏 280 天(IBM Security Report)。

9.2 应该记录什么

// 安全事件日志模板
@Aspect
@Component
public class SecurityAuditAspect {
    @AfterReturning("@annotation(auditable)")
    public void audit(JoinPoint jp, Auditable auditable) {
        SecurityEvent event = SecurityEvent.builder()
            .timestamp(Instant.now())
            .user(getCurrentUser())
            .action(auditable.action())
            .resource(auditable.resource())
            .ip(getClientIp())
            .userAgent(getUserAgent())
            .result("SUCCESS")
            .build();
        securityLogger.info(event);
    }
}

// 必须记录的事件:
// - 登录成功/失败
// - 权限变更
// - 敏感数据访问
// - 管理员操作
// - 配置变更
// - 安全异常(XSS/注入尝试)

10. A10:2021 服务端请求伪造(SSRF)

10.1 攻击原理

攻击者让服务器向攻击者指定的地址发送请求:

场景:图片下载功能
POST /download-image
{ "url": "http://attacker.com/malicious" }

危害:
- 访问内网服务(metadata API、内部管理接口)
- 攻击云厂商 metadata(获取 AK/SK)
- 端口扫描内网
- 读取本地文件(file:///etc/passwd)

10.2 防御方案

public class UrlValidator {
    private static final Set<String> ALLOWED_SCHEMES = Set.of("http", "https");
    private static final Set<String> BLOCKED_HOSTS = Set.of(
        "localhost", "127.0.0.1", "0.0.0.0",
        "169.254.169.254" // AWS/阿里云 metadata
    );
    
    public static boolean isSafe(String urlString) {
        try {
            URL url = new URL(urlString);
            
            // 1. 验证协议
            if (!ALLOWED_SCHEMES.contains(url.getProtocol())) {
                return false;
            }
            
            // 2. 解析 IP(防止 DNS 重绑定)
            InetAddress address = InetAddress.getByName(url.getHost());
            if (address.isLoopbackAddress() || address.isSiteLocalAddress()) {
                return false;
            }
            
            // 3. 黑名单检查
            if (BLOCKED_HOSTS.contains(url.getHost().toLowerCase())) {
                return false;
            }
            
            return true;
        } catch (Exception e) {
            return false;
        }
    }
}

11. 安全开发生命周期(SDLC)

需求阶段          设计阶段         开发阶段          测试阶段         部署阶段         运维阶段
   │                │               │               │              │              │
   ▼                ▼               ▼               ▼              ▼              ▼
威胁建模          安全设计        安全编码         SAST/DAST      容器扫描       漏洞管理
安全需求          安全架构        代码审计         渗透测试       配置基线       应急响应
                  数据流图        依赖检查         模糊测试       Secrets扫描    日志监控

12. 总结

OWASP Top 10 是安全入门与评估的基础框架,但真正的安全需要纵深防御:

分层防御模型:

  网络层 ──► WAF / CDN / DDoS 防护
      │
  主机层 ──► OS Hardening / 容器安全 / 运行时防护
      │
  应用层 ──► 输入验证 / 输出编码 / 访问控制 / 加密
      │
  数据层 ──► 数据库加密 / 备份 / 审计日志
      │
  人员层 ──► 安全意识培训 / 最小权限 / 安全编码规范

安全不是一次性任务,而是贯穿软件生命周期的持续活动。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「安全」更多文章

  1. Kubernetes安全体系:RBAC、PodSecurity与NetworkPolicy实战
  2. 安全合规与数据保护
  3. 渗透测试与红蓝对抗