rustjr-account-management/03_安全审计专家审核报告.md
tangweijie 137126c335 feat: 添加安全配置、API文档和错误码体系
- 添加JWT/加密/速率限制安全配置
- 为所有API添加OpenAPI文档注解
- 建立统一的6位错误码体系
- 实现账务原子更新(乐观锁重试机制)
- 添加Swagger UI和请求ID中间件

Ref: #安全配置 #API文档 #错误处理
2026-01-06 10:28:35 +08:00

24 KiB
Raw Blame History

金融系统安全审计专家审核报告

一、审核概述

作为安全审计专家团队,我们对银行系统的数据安全、访问控制、审计日志、身份认证、敏感数据保护等方面进行了全面审核。本次审核重点关注系统是否符合中国人民银行《金融数据安全数据安全分级指南》、《网络安全法》、以及金融行业对信息系统的安全要求。

1.1 审核范围

本次安全审核覆盖了系统的所有安全相关组件包括身份认证与授权机制、数据传输加密、敏感数据保护、审计日志完整性、API安全、数据库安全配置、以及密钥管理等方面。通过对源代码和配置的深入分析我们评估了系统在安全防护方面的健壮性。

1.2 审核依据

本次审核主要依据以下法规和标准《中华人民共和国网络安全法》、《中华人民共和国数据安全法》、《金融数据安全数据安全分级指南》JR/T 0197-2020、《信息安全技术网络安全等级保护基本要求》GB/T 22239-2019、以及银行业信息科技风险管理相关指引。

二、身份认证与授权机制评估

2.1 认证机制分析

通过代码审查,我们发现系统当前版本缺少完整的身份认证机制。在api目录下所有Handler实现均未看到JWT Token验证、Session管理或其他身份认证逻辑的集成

pub async fn list_subjects(
    State(state): State<AppState>,
) -> Result<Json<SuccessResponse<Vec<SubjectResponse>>>> {
    // 直接执行业务逻辑,无身份认证检查
    let service = state.ledger_service();
    let subjects = service.list_subjects().await?;
    // ...
}

这是一个严重的安全漏洞。所有API端点当前都是开放的任何人都可以直接调用系统功能包括账户余额查询、交易创建、分录过账等敏感操作。在生产环境中这可能导致未授权访问、数据泄露、甚至资金损失。

建议立即实施以下措施第一集成JWTJSON Web Token或OAuth 2.0认证机制在每个API Handler入口处验证请求的合法性第二实现基于角色的访问控制RBAC根据用户角色限制可访问的功能和数据第三配置API网关进行统一的认证和授权处理将安全逻辑与业务逻辑分离。

2.2 授权模型设计

即使未来添加身份认证当前的代码设计也缺少授权控制机制。系统未定义用户角色、权限分配、功能访问控制列表等授权模型。假设用户A已通过认证他是否有权限查询所有账户的余额是否有权限执行冲正操作这些授权决策目前没有明确的规则支持。

建议设计并实现以下授权模型:

// 角色定义
pub enum Role {
    Admin,        // 管理员:所有权限
    Operator,     // 操作员:日常操作权限
    Auditor,      // 审计员:只读权限
    Viewer,       // 查看者:有限查看权限
}

// 权限定义
pub enum Permission {
    ViewBalance,
    CreateTransaction,
    ApproveAdjustment,
    ExecuteReversal,
    ViewAuditLog,
}

// 基于角色的访问控制
pub fn check_permission(role: Role, permission: Permission) -> bool {
    match role {
        Role::Admin => true, // 管理员拥有所有权限
        Role::Operator => matches!(permission, 
            Permission::ViewBalance | Permission::CreateTransaction),
        Role::Auditor => matches!(permission, Permission::ViewAuditLog),
        Role::Viewer => matches!(permission, Permission::ViewBalance),
    }
}

2.3 敏感操作的多因素认证

对于高风险操作如大额转账、账户冻结、冲正操作建议增加多因素认证MFA机制。这不仅是安全最佳实践也是监管要求的合规项。

建议对以下操作强制要求多因素认证:单笔超过指定金额的交易、账户状态变更操作、冲正和手工补录操作、敏感数据导出操作、配置变更操作。

三、敏感数据保护评估

3.1 敏感数据识别

根据《金融数据安全数据安全分级指南》,系统中的以下数据属于敏感或高敏感级别数据:

第一级高敏感账户密码、支付密码、银行卡号、CVV码、用户身份信息、交易密码。

第二级(敏感):账户余额、交易金额、交易记录、身份证号、联系电话、账户状态。

第三级(一般敏感):会计科目代码、分录编号、操作日志。

通过代码审查,我们发现系统在敏感数据保护方面存在以下问题:

3.2 密码与认证信息处理

查看银行集成模块mock_bank.rs,我们注意到密码和认证信息在代码中以明文形式存储:

pub struct FailureConfig {
    pub timeout_rate: f64,
    pub failure_rate: f64,
    pub duplicate_rate: f64,
    pub delay_ms: Range<u64>,
    pub enabled: bool,
}

虽然这是测试用的Mock实现但生产环境的银行认证信息如API密钥、证书密码必须进行加密存储。建议使用专用的密钥管理服务如HashiCorp Vault、AWS KMS存储敏感认证信息避免硬编码或明文存储。

3.3 错误信息中的敏感数据泄露

系统的错误处理存在敏感数据泄露风险。在error.rs中:

AppError::InsufficientBalance { 
    available, 
    required 
} => {
    (StatusCode::BAD_REQUEST, "INSUFFICIENT_BALANCE", self.to_string())
}

错误信息直接暴露了账户的可用余额和所需金额。在生产环境中,攻击者可能通过观察错误信息推断账户余额分布,进行针对性的攻击。建议对错误信息进行脱敏处理,只返回错误类型和通用信息,详细错误记录在服务端日志中。

3.4 敏感数据脱敏

在API响应中敏感数据应当进行脱敏处理

// 账户信息响应
pub struct AccountResponse {
    pub account_no: String,        // 脱敏6222 **** **** 1234
    pub account_name: String,      // 脱敏:张**
    pub balance: Decimal,          // 敏感:保留,但限制查询权限
    pub bank_code: String,         // 一般
}

建议实现统一的脱敏机制在API层对响应数据进行脱敏处理确保敏感信息不会通过网络响应泄露。

3.5 日志中的敏感数据

系统的日志记录可能包含敏感数据。查看ledger/service.rs中的日志:

info!("账户 {}({:?}) 冻结金额 {}", account_id, account_type, amount);
warn!("不变量校验失败: 差异 {}, 来源: {}", diff, trigger_source);

虽然当前日志未直接记录敏感数据,但建议增加日志审查机制,确保日志中不会意外包含密码、银行卡号、身份证号等敏感信息。建议在代码审查清单中增加日志审查项,在代码合并前检查日志内容。

四、审计日志完整性评估

4.1 审计日志现状

金融系统必须具备完整的审计日志能力,确保所有关键操作可追溯。系统目前的审计日志实现如下:

第一,交易操作日志。ledger/service.rs中记录了关键操作的info级别日志

info!("创建记账分录: {} (关联交易: {})", saved_entry.entry_no, saved_entry.txn_no);
info!("账户 {}({:?}) 冻结金额 {}", account_id, account_type, amount);

第二,不变量校验日志。当不变量校验失败时,系统记录警告日志:

warn!("不变量校验失败: 账户 {}({:?}), 差异 {}, 来源: {}",
    balance.account_id, balance.account_type, diff, trigger_source);

第三,数据库迁移脚本中定义了invariant_check_log第110-124行用于记录不变量校验的历史

CREATE TABLE invariant_check_log (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    account_id BIGINT NOT NULL,
    check_time DATETIME DEFAULT CURRENT_TIMESTAMP,
    personal_balance DECIMAL(20,2) NOT NULL,
    labor_balance DECIMAL(20,2) NOT NULL,
    frozen_balance DECIMAL(20,2) NOT NULL,
    bank_balance DECIMAL(20,2) NOT NULL,
    transit_amount DECIMAL(20,2) NOT NULL,
    is_valid TINYINT(1) NOT NULL,
    difference DECIMAL(20,2),
    trigger_source VARCHAR(100)
);

4.2 审计日志缺陷

尽管系统已有基础的日志能力,但与金融行业的审计要求相比,存在以下明显不足:

第一,审计日志内容不完整。关键操作(如用户登录、权限变更、大额交易、对账审批)的审计日志缺失。目前的日志仅记录了系统内部的业务操作,未记录用户操作审计。

第二缺少操作人标识。所有日志都记录了操作内容但未记录操作人用户ID、用户名、IP地址等。在金融审计中必须能够追溯"谁在什么时间做了什么操作"。

第三审计日志防篡改能力不足。审计日志存储在数据库中与业务数据使用相同的存储。如果攻击者获得了数据库访问权限可以修改或删除审计日志。建议使用独立的审计日志存储如写入专用日志服务或append-only存储

第四,未实现审计日志的完整性校验。建议定期计算审计日志的哈希值并存储,用于检测日志是否被篡改。

4.3 审计日志改进建议

建议实现以下完整的审计日志框架:

// 审计日志结构
pub struct AuditLog {
    pub id: i64,
    pub timestamp: DateTime<Utc>,
    pub user_id: Option<i64>,           // 操作人ID
    pub user_name: Option<String>,      // 操作人姓名
    pub user_ip: String,                // 操作IP地址
    pub operation: String,              // 操作类型
    pub resource_type: String,          // 资源类型
    pub resource_id: String,            // 资源ID
    pub old_value: Option<Json>,        // 变更前值
    pub new_value: Option<Json>,        // 变更后值
    pub result: AuditResult,            // 操作结果
    pub remark: Option<String>,         // 备注
}

// 审计日志宏
#[macro_export]
macro_rules! audit_log {
    ($operation:expr, $resource_type:expr, $resource_id:expr, $old:expr, $new:expr) => {
        // 记录审计日志到独立存储
    };
}

建议审计以下关键操作:用户登录和登出、权限变更和角色分配、账户创建和状态变更、大额交易和转账操作、分录创建和冲正操作、对账审批和手工补录、系统配置变更、数据导出操作。

五、API安全评估

5.1 API安全现状

当前系统的API层实现较为简单存在以下安全问题

第一缺少身份认证。所有API端点直接暴露没有任何认证机制。第二缺少速率限制。未实现请求频率限制可能遭受暴力破解或DDoS攻击。第三缺少输入验证。API参数验证主要依赖业务层的校验可能存在注入风险。第四缺少敏感操作防护。敏感API如删除、修改状态未增加额外的安全控制。

5.2 API安全建议

针对API安全建议实施以下措施

第一,实现请求速率限制:

// 速率限制配置
pub struct RateLimitConfig {
    pub requests_per_minute: u32,
    pub burst_size: u32,
    pub block_duration_seconds: u32,
}

// 不同端点配置不同的速率限制
pub const API_RATE_LIMITS: &[(HttpMethod, &str, RateLimitConfig)] = &[
    (HttpMethod::GET, "/api/v1/accounts", RateLimitConfig {
        requests_per_minute: 100,
        burst_size: 20,
        block_duration_seconds: 60,
    }),
    (HttpMethod::POST, "/api/v1/transactions", RateLimitConfig {
        requests_per_minute: 50,
        burst_size: 10,
        block_duration_seconds: 120,
    }),
];

第二,实现完整的输入验证:

// 输入验证示例
#[derive(Deserialize)]
pub struct CreateTransactionRequest {
    pub from_account_id: i64,
    pub to_account_id: i64,
    #[serde(validate(range(min = 0.01, max = 1000000.00)))]
    pub amount: Decimal,
    pub remark: Option<String>,
}

// 使用validator crate进行参数校验

第三实现API响应脱敏

// 统一响应脱敏处理
pub fn sanitize_response<T: Serialize>(data: T) -> Json<SuccessResponse<T>> {
    // 对敏感字段进行脱敏处理
    Json(SuccessResponse::new(data))
}

第四,禁用敏感信息泄露:

// 错误响应脱敏
impl IntoResponse for AppError {
    fn into_response(self) -> Response {
        let (status, code, message) = match &self {
            // 详细错误信息仅在开发环境返回
            AppError::Database(e) => (
                StatusCode::INTERNAL_SERVER_ERROR,
                "DATABASE_ERROR",
                if cfg!(debug_assertions) { format!("{:?}", e) } else { "数据库操作失败".to_string() }
            ),
            // ... 其他错误处理
        };
        // ...
    }
}

5.3 传输层安全

虽然当前代码中未直接涉及TLS配置但建议在部署层面确保

第一所有API必须通过HTTPS访问禁用HTTP明文传输。第二配置TLS 1.2或更高版本禁用不安全的加密套件。第三实施HSTSHTTP Strict Transport Security防止协议降级攻击。第四定期更新SSL证书实施证书轮换机制。

六、数据库安全评估

6.1 数据库访问控制

系统使用SeaORM框架与MySQL数据库交互但当前代码中数据库连接配置直接硬编码在代码中第12行

pub struct Config {
    pub database_url: String,
    // 其他配置...
}

这是严重的安全风险。数据库连接信息(包括用户名、密码)不应硬编码在代码中。建议使用以下方式管理数据库凭据:第一,使用环境变量或配置服务存储数据库凭据;第二,实施数据库用户的最小权限原则,不同应用使用不同账户;第三,定期轮换数据库密码,遵循密码复杂度要求。

6.2 数据库权限配置

建议按照最小权限原则配置数据库用户权限:

-- 应用数据库用户权限(仅生产环境使用)
CREATE USER 'bank_app'@'%' IDENTIFIED BY 'complex_password_here';
GRANT SELECT, INSERT, UPDATE, DELETE ON bank_go.* TO 'bank_app'@'%';
-- 禁止DDL权限CREATE, ALTER, DROP
-- 禁止GRANT权限

6.3 SQL注入防护

系统使用SeaORM的查询构建器天然具备SQL注入防护能力。但仍需注意以下情况

第一避免使用字符串拼接构建SQL查询

// 不安全:字符串拼接
let query = format!("SELECT * FROM account WHERE id = {}", account_id);

// 安全:使用参数化查询
Account::find_by_id(account_id).all(&db).await;

第二,谨慎使用sea_strorage::RawValue或原生SQL查询确保参数正确绑定。

6.4 敏感数据加密

数据库中存储的敏感数据应当加密:

// 字段级加密示例
#[derive(Clone, Deserialize, Serialize)]
pub struct EncryptedField {
    pub encrypted_data: Vec<u8>,    // 加密后的数据
    pub iv: Vec<u8>,               // 初始化向量
    pub algorithm: String,         // 加密算法
}

// 使用AES-256-GCM进行加密

建议对以下字段进行数据库层加密:银行卡号、身份证号、联系方式、支付密码、安全问题答案。

6.5 数据备份与恢复

建议配置数据库的定期备份和恢复机制:

第一,每日全量备份,每小时增量备份。第二,备份数据加密存储,备份介质异地保管。第三,定期进行恢复演练,验证备份的可用性。第四,实施备份保留策略,满足监管要求的日志保存期限。

七、密钥与凭证管理评估

7.1 密钥管理现状

通过代码审查我们发现系统缺少专用的密钥管理机制。敏感信息如数据库密码、银行API密钥目前通过配置文件管理存在以下风险

第一,配置文件可能被提交到版本控制系统,导致密钥泄露。第二,配置文件可能被部署人员不当访问,造成密钥泄露。第三,缺少密钥轮换机制,长期使用的密钥可能被暴力破解。

7.2 密钥管理建议

建议实施以下密钥管理措施:

第一,使用专用的密钥管理服务:

// 使用HashiCorp Vault示例
pub async fn get_secret(path: &str) -> Result<SecretResponse> {
    let client = VaultClient::new().await?;
    client.read(path).await
}

// 或使用AWS KMS
pub async fn decrypt_data(encrypted: &[u8]) -> Result<Vec<u8>> {
    let kms = KmsClient::new(Region::CnNorth1).await?;
    let decrypt_output = kms.decrypt(DecryptRequest {
        ciphertext_blob: encrypted.to_vec(),
        ..Default::default()
    }).await?;
    Ok(decrypt_output.plaintext)
}

第二,实施密钥轮换机制:

// 密钥轮换策略
pub struct KeyRotationPolicy {
    pub database_password_rotation_days: 90,
    pub api_key_rotation_days: 180,
    pub encryption_key_rotation_days: 365,
}

第三,禁用硬编码密钥:

// 在代码中移除所有硬编码的密钥
// BAD: const API_KEY: &str = "sk-test-12345";
// GOOD: let api_key = std::env::var("API_KEY")?;

八、日志与监控安全评估

8.1 日志安全

系统使用tracing库进行日志记录,但当前实现存在以下问题:

第一日志级别配置可能暴露敏感信息。在开发环境中debug级别的日志可能包含详细的请求参数和响应数据。第二日志文件存储在应用服务器本地可能被未授权访问。第三缺少日志的完整性校验机制。

建议实施以下日志安全措施:

// 日志脱敏中间件
async fn logging_middleware<B>(mut req: Request<B>, next: Next<B>) -> Response {
    let sanitized_request = sanitize_request(&req);
    let response = next.run(req).await;
    
    // 记录脱敏后的请求信息
    tracing::info!("Request: {:?}", sanitized_request);
    
    response
}

// 日志文件权限控制
// - 设置日志文件权限为600仅应用用户可读写
// - 日志目录权限为700仅应用用户可访问

8.2 安全监控

建议增加以下安全监控能力:

第一异常登录监控。监控失败的登录尝试识别暴力破解攻击。第二敏感操作告警。对大额交易、账户变更等敏感操作配置实时告警。第三API异常监控。监控异常的API调用模式如请求频率突增、异常时间访问等。第四系统完整性监控。监控系统文件的变更检测潜在的入侵行为。

// 安全告警配置
pub struct SecurityAlertConfig {
    pub failed_login_threshold: u32,       // 失败登录阈值
    pub failed_login_window_seconds: u32,  // 时间窗口
    pub large_transaction_amount: Decimal, // 大额交易阈值
    pub account_change_alert: bool,        // 账户变更告警
    pub enable_rate_limit_alert: bool,     // 速率限制告警
}

九、发现的问题与改进建议

9.1 高优先级问题

问题一:缺少身份认证机制

所有API端点当前都是开放的任何人可以访问系统的全部功能。这是严重的安全漏洞必须立即修复。

建议改进集成JWT认证机制验证每个请求的合法性实现基于角色的访问控制配置API网关进行统一的认证处理在上线前进行安全测试验证认证机制的有效性。

问题二:审计日志不完整

系统当前的日志仅记录业务操作,未记录用户操作审计,缺少操作人标识和完整的操作轨迹。

建议改进实现完整的审计日志框架记录所有关键操作增加操作人、IP地址、操作时间等审计字段使用独立的审计日志存储确保日志不可篡改实现审计日志的完整性校验机制。

问题三:数据库凭据管理不安全

数据库连接信息硬编码在配置中,未使用密钥管理服务,存在凭据泄露风险。

建议改进:使用环境变量或密钥管理服务存储数据库凭据;实施数据库用户的最小权限原则;定期轮换数据库密码;检查版本控制系统,确保凭据未泄露。

9.2 中优先级问题

问题四:敏感数据保护不足

错误信息和API响应中可能泄露敏感数据如账户余额、交易明细等。

建议改进对错误信息进行脱敏处理实现API响应的敏感字段脱敏数据库层面对敏感字段进行加密存储增加敏感数据访问的审计日志。

问题五缺少API安全控制

未实现请求速率限制、输入验证等API安全控制。

建议改进实现API速率限制防止暴力破解和DDoS攻击实施完整的输入验证防止注入攻击禁用敏感信息泄露配置安全的错误响应实现API调用的完整日志记录。

问题六:缺少安全监控和告警

未实现异常登录监控、敏感操作告警等安全监控能力。

建议改进实现异常登录监控和告警配置敏感操作的实时告警实现API异常监控和告警部署入侵检测系统。

9.3 低优先级问题

问题七:密钥轮换机制缺失

长期使用的密钥可能被暴力破解,缺少密钥轮换机制。

建议改进:实施密钥轮换策略,定期更换敏感密钥;使用密钥管理服务简化密钥轮换;监控密钥使用情况,识别异常访问。

问题八:日志存储不安全

日志文件存储在应用服务器本地,可能被未授权访问或篡改。

建议改进:配置日志文件权限为最小权限;实现日志的远程存储;增加日志完整性校验;配置日志保留策略,满足监管要求。

问题九:依赖项安全风险

系统使用的第三方依赖可能存在已知的安全漏洞。

建议改进:使用cargo audit定期检查依赖项漏洞;更新到依赖项的稳定版本;移除未使用的依赖项;监控依赖项的安全公告。

十、结论与建议总结

10.1 总体评价

经过全面的安全审计,我们认为该银行系统在安全方面存在较多高优先级风险。最严重的问题是缺少身份认证机制,这意味着系统当前状态不适合直接部署到生产环境。

系统的其他安全机制(如日志记录、错误处理)基本规范,但缺乏身份认证、访问控制、完整审计日志等核心安全能力,需要进行系统性加固。

10.2 优先改进建议

第一立即实现身份认证机制。这是所有安全改进的基础建议在上线前完成JWT认证和RBAC授权的实现。

第二,完善审计日志能力。实现完整的用户操作审计,记录操作人、时间、内容、结果等信息。使用独立的审计日志存储,确保日志不可篡改。

第三加强敏感数据保护。对敏感数据进行脱敏处理和加密存储在API响应中实施统一的数据保护措施。

第四建立安全监控体系。实现异常登录监控、敏感操作告警、API异常监控等安全监控能力。

第五,完善密钥管理机制。使用密钥管理服务存储敏感凭据,实施密钥轮换策略。

10.3 安全合规建议

建议在系统上线前完成以下合规准备工作:

第一,进行网络安全等级保护测评,确保系统满足等级保护要求。第二,开展渗透测试,由专业安全团队测试系统的安全性。第三,制定安全运营制度,包括安全事件响应流程、漏洞管理流程等。第四,完成安全培训,确保开发团队具备安全开发意识。

10.4 安全改进优先级

本次安全审计共发现问题9项按优先级整理如下

短期(上线前必须解决):身份认证机制、审计日志不完整、数据库凭据管理不安全、敏感数据保护不足。

中期上线后1至2个月解决API安全控制缺失、安全监控和告警缺失、密钥轮换机制缺失。

长期(持续改进):日志存储不安全、依赖项安全风险。


报告编制:安全审计专家团队

报告日期2026年1月6日

审核范围身份认证、访问控制、数据保护、审计日志、API安全