第6章:日志与审计(Logging and Auditing)
一、导读
1.1 本章学习目标
第6章讲解安全日志和审计追踪——安全事件的记录和分析。
本章的核心学习目标包括:
- 理解安全日志的重要性
- 掌握日志中应该记录什么
- 学会设计审计追踪系统
- 理解日志安全的风险
1.2 为什么本章如此重要
没有日志,你就无法发现安全事件、无法调查攻击、无法满足合规要求。但日志本身也可能成为安全风险——泄露敏感信息、被攻击者篡改。
1.3 核心问题引导
安全日志应该记录什么?不应该记录什么?
审计追踪和普通日志有什么区别?
如何防止日志成为攻击向量?
日志保留策略如何设计?
二、核心概念详解
2.1 安全日志
java
// 安全事件日志
public class SecurityLogger {
public void logLoginAttempt(String username, boolean success, String ipAddress) {
logger.info("Login attempt: user={}, success={}, ip={}, time={}",
username, success, ipAddress, Instant.now());
}
public void logAccessDenied(String userId, String resource, String action) {
logger.warn("Access denied: user={}, resource={}, action={}, time={}",
userId, resource, action, Instant.now());
}
public void logSensitiveOperation(String userId, String operation, String details) {
logger.info("Sensitive operation: user={}, op={}, details={}, time={}",
userId, operation, details, Instant.now());
}
}
// 危险!日志中记录敏感信息
logger.info("User login: username={}, password={}", username, password); // 不要记录密码!2.2 审计追踪
java
public class AuditTrail {
public void record(AuditEvent event) {
// 不可变的审计记录
AuditRecord record = new AuditRecord(
UUID.randomUUID(),
event.getUserId(),
event.getAction(),
event.getResource(),
event.getTimestamp(),
event.getIpAddress(),
event.getUserAgent(),
computeHash(event) // 完整性校验
);
// 写入审计日志(只追加,不可修改)
auditRepository.append(record);
}
private String computeHash(AuditEvent event) {
// 计算哈希确保记录不被篡改
return DigestUtils.sha256Hex(event.toString() + secretKey);
}
}2.3 日志安全
日志安全风险:
1. 日志注入:攻击者在输入中注入换行符伪造日志
→ 对策:转义日志输入
2. 敏感信息泄露:日志中记录密码、信用卡号等
→ 对策:过滤敏感字段
3. 日志篡改:攻击者修改日志掩盖痕迹
→ 对策:只追加存储、哈希校验
4. 日志洪泛:大量假日志淹没真实事件
→ 对策:限流、异常检测三、实战案例
3.1 案例一:安全日志框架
java
public class SecureLogger {
private static final Set<String> SENSITIVE_FIELDS = Set.of(
"password", "ssn", "creditCard", "token", "secret"
);
public void log(String template, Object... args) {
Object[] safeArgs = Arrays.stream(args)
.map(this::sanitize)
.toArray();
logger.info(template, safeArgs);
}
private Object sanitize(Object arg) {
if (arg instanceof Map) {
Map<?, ?> map = (Map<?, ?>) arg;
Map<Object, Object> sanitized = new HashMap<>();
for (Map.Entry<?, ?> entry : map.entrySet()) {
String key = String.valueOf(entry.getKey());
if (SENSITIVE_FIELDS.contains(key.toLowerCase())) {
sanitized.put(entry.getKey(), "***REDACTED***");
} else {
sanitized.put(entry.getKey(), entry.getValue());
}
}
return sanitized;
}
return arg;
}
}四、本章小结
安全日志:记录认证、授权、敏感操作等安全事件。
审计追踪:不可变的、可验证的操作记录。
日志安全:防止日志注入、敏感信息泄露、日志篡改。
保留策略:根据合规要求确定日志保留时间。
五、思考与练习
设计一个安全日志方案来检测暴力破解攻击。
如何实现不可篡改的审计日志?
分析一个你熟悉的系统,找出日志中可能泄露的敏感信息。