Python实战:构建信息安全风险评估模型,实现自动化风险量化
1. 项目概述从零构建一个实用的风险评估脚本在信息安全领域风险评估是几乎所有工作的起点。无论是做等保测评、安全运维还是规划安全预算你都得先搞清楚我们到底有哪些家当资产这些家当面临哪些威胁万一出事损失有多大最后哪些风险需要优先处理这些问题光靠拍脑袋是没用的需要一个结构化的方法来量化。很多朋友一听到“风险评估模型”就觉得是咨询公司或者大厂安全部门才玩得转的复杂东西需要专门的商业软件。其实不然其核心逻辑非常清晰识别资产 - 评估资产价值 - 识别威胁与脆弱性 - 计算风险值 - 给出处置建议。这个逻辑链条完全可以用我们最熟悉的Python来实现自动化变成一个轻量级、可定制、能反复使用的脚本工具。我这次要分享的就是如何用Python从零开始搭建一个简单的信息安全风险评估模型。这个模型的核心是计算两个关键指标资产价值和风险值。资产价值决定了“东西有多重要”风险值则量化了“出事的可能性与后果”。最终脚本会输出一份结构化的报告告诉你哪些风险是“高危”必须立刻处理哪些可以“观察”后续跟进。这个项目特别适合以下几类朋友信息安全工程师或运维人员需要定期对负责的系统进行风险评估但不想每次都手动填Excel表格。开发人员或项目负责人在项目上线前想快速评估一下应用的安全风险做到心中有数。对安全感兴趣的Python学习者想找一个有明确业务场景、能串联多个Python知识点的实战项目。备考相关认证如软考信息安全工程师的同学通过动手实现可以深刻理解风险评估的计算过程比死记硬背公式有效得多。整个实现过程我们会用到Python的基础数据结构、文件操作、简单的数学计算以及报告生成。不需要复杂的机器学习库重点在于逻辑的严谨性和脚本的实用性。下面我就带你一步步拆解思路并把代码实现、参数定义、常见坑点都讲清楚。2. 风险评估模型的核心逻辑拆解在动手写代码之前我们必须把模型的计算逻辑彻底搞明白。一个简易但完整的信息安全风险评估模型通常遵循以下流程这也是我们代码结构的蓝图信息收集 - 资产赋值 - 威胁分析 - 脆弱性分析 - 风险计算 - 结果输出。2.1 核心概念定义我们的模型围绕几个核心概念展开理解它们的定义和关系至关重要资产在信息安全语境下资产是指对组织具有价值的任何信息、软件、硬件、服务、人员等。例如客户数据库服务器、官网Web应用、源代码仓库、门禁系统。资产价值并非指资产的市场价格而是指其保密性、完整性、可用性三个安全属性遭到破坏时对组织造成的潜在影响或损失程度。通常用一个综合的数值来表示。威胁可能导致对系统或组织损害的不期望事件发生的潜在原因。例如黑客攻击、内部人员误操作、硬件故障、自然灾害。脆弱性资产自身存在的、可能被威胁所利用的弱点或缺陷。例如服务器存在未修复的高危漏洞、员工使用弱口令、机房没有备用电源。风险特定的威胁利用资产的一项或多项脆弱性导致安全事件发生从而对资产造成损害的可能性及其影响的组合。风险是我们要计算的最终目标。注意这里采用的是经典的“资产-威胁-脆弱性”风险模型。在实际操作中我们通常不会漫无边际地列举所有威胁和脆弱性而是针对具体的资产分析它可能面临的主要威胁和已存在的脆弱性。这能让评估更聚焦、更高效。2.2 风险值计算公式风险值如何量化最常用的一个简化公式是风险值 资产价值 × 威胁发生的可能性 × 脆弱性被利用的严重程度这个公式直观地体现了风险的三要素资产本身的价值影响、坏事发生的概率可能性、以及坏事能造成多大破坏严重性。资产价值我们需要先计算出来是一个1-5或1-10的等级值。威胁可能性威胁事件发生的频率或概率同样用1-5等级表示。例如1代表“几乎不可能”5代表“几乎肯定发生”。脆弱性严重程度该脆弱性如果被成功利用会导致多严重的后果用1-5等级表示。例如1代表“轻微影响”5代表“灾难性影响”。将这三个等级值相乘得到的就是一个量化的风险值。这个值越大代表风险越高。2.3 资产价值计算公式资产价值怎么算我们采用对保密性、完整性、可用性分别赋值再综合的方法资产价值 (保密性赋值 完整性赋值 可用性赋值) / 3或者采用加权平均如果某个属性对特定资产更重要的话。每个属性C/I/A也使用1-5的等级进行赋值5-非常高破坏会导致灾难性后果。4-高破坏会导致严重损失。3-中破坏会导致中度损失。2-低破坏会导致轻微损失。1-可忽略破坏后果可忽略。例如对于“客户数据库”保密性5数据泄露后果严重完整性4数据被篡改影响业务可用性3短暂中断可恢复资产价值 (543)/3 4.0有了这些理论基础我们就可以开始设计程序的数据结构和流程了。3. 模型设计与数据结构规划代码的骨架源于清晰的逻辑设计。我们需要规划好如何存储资产、威胁、脆弱性这些信息以及它们之间的关联关系。3.1 使用字典和列表构建核心数据Python的字典和列表非常适合用来表示这种结构化的评估数据。我建议按以下方式组织# 资产列表每个资产是一个字典 assets [ { “id”: “AST-001”, “name”: “官网Web服务器”, “description”: “承载公司官网和产品展示页面运行在Nginx上。”, “confidentiality”: 3, # 保密性赋值 “integrity”: 4, # 完整性赋值 “availability”: 5, # 可用性赋值 “value”: 0.0 # 待计算初始为0 }, { “id”: “AST-002”, “name”: “核心业务数据库”, “description”: “存储所有用户订单和交易数据MySQL主从架构。”, “confidentiality”: 5, “integrity”: 5, “availability”: 4, “value”: 0.0 } ] # 威胁库可以预定义一些常见威胁 threat_library [ {“id”: “T-01”, “name”: “DDoS攻击”, “description”: “通过海量流量耗尽目标带宽或资源。”}, {“id”: “T-02”, “name”: “SQL注入”, “description”: “攻击者利用Web应用漏洞执行恶意SQL语句。”}, {“id”: “T-03”, “name”: “内部人员误操作”, “description”: “授权员工无意中删除或修改关键数据。”}, {“id”: “T-04”, “name”: “硬件故障”, “description”: “服务器硬盘、内存等物理部件损坏。”} ] # 脆弱性库同样可以预定义 vulnerability_library [ {“id”: “V-01”, “name”: “未授权访问”, “description”: “系统存在无需认证即可访问的接口或页面。”}, {“id”: “V-02”, “name”: “弱口令”, “description”: “系统账户使用了简单、易猜测的密码。”}, {“id”: “V-03”, “name”: “未安装关键安全补丁”, “description”: “操作系统或应用存在已知高危漏洞且未修复。”}, {“id”: “V-04”, “name”: “备份缺失或失效”, “description”: “没有定期备份或备份数据无法成功恢复。”} ]3.2 风险评估记录表这是整个模型的核心表它把资产、威胁、脆弱性关联起来并记录评估的等级和计算结果。# 风险评估记录每个记录代表一个具体的“资产-威胁-脆弱性”组合 risk_assessments [ { “id”: “RA-001”, “asset_id”: “AST-001”, # 关联资产ID “threat_id”: “T-01”, # 关联威胁ID “vulnerability_id”: “V-03”, # 关联脆弱性ID “likelihood”: 4, # 威胁可能性 (1-5) “severity”: 4, # 脆弱性严重程度 (1-5) “risk_value”: 0.0 # 待计算的风险值 }, { “id”: “RA-002”, “asset_id”: “AST-002”, “threat_id”: “T-02”, “vulnerability_id”: “V-02”, “likelihood”: 3, “severity”: 5, “risk_value”: 0.0 } ]实操心得在项目初期强烈建议像上面这样用硬编码的方式在脚本里定义一些示例数据。这有两大好处第一可以立即开始编写和测试核心计算逻辑不用等待复杂的数据输入功能第二这些示例数据本身就是一份很好的文档能让你和后续的协作者快速理解数据结构。等核心逻辑跑通后再扩展为从文件读取或交互式输入。3.3 程序主流程设计我们的脚本将按照以下步骤运行初始化加载或定义资产、威胁、脆弱性数据以及风险评估记录。计算资产价值遍历资产列表根据C/I/A赋值计算每个资产的综合价值。计算风险值遍历风险评估记录根据公式资产价值 × 可能性 × 严重性计算每条记录的风险值。风险等级判定根据计算出的风险值将其划分为“高”、“中”、“低”等不同等级。生成报告将资产列表、风险清单按风险值排序等结果输出到控制台或文件。接下来我们就进入具体的代码实现环节。4. 分步代码实现与详解让我们把上面的设计变成可运行的代码。我会分函数讲解确保每一部分你都清楚其作用。4.1 数据准备与初始化首先我们把之前设计的数据结构放到代码里并写一个初始化函数。为了后续扩展我们会把数据定义和初始化分开。# risk_assessment_model.py def init_data(): “”“初始化示例数据。”“” assets [ {“id”: “AST-001”, “name”: “官网Web服务器”, “description”: “承载公司官网”, “confidentiality”: 3, “integrity”: 4, “availability”: 5, “value”: 0.0}, {“id”: “AST-002”, “name”: “核心业务数据库”, “description”: “存储用户订单数据”, “confidentiality”: 5, “integrity”: 5, “availability”: 4, “value”: 0.0}, {“id”: “AST-003”, “name”: “内部邮件系统”, “description”: “员工内部通信”, “confidentiality”: 4, “integrity”: 3, “availability”: 3, “value”: 0.0} ] threat_library [ {“id”: “T-01”, “name”: “DDoS攻击”, “description”: “耗尽目标资源。”}, {“id”: “T-02”, “name”: “SQL注入”, “description”: “利用漏洞执行恶意SQL。”}, {“id”: “T-03”, “name”: “内部人员误操作”, “description”: “员工无意删除数据。”}, {“id”: “T-04”, “name”: “硬件故障”, “description”: “物理部件损坏。”} ] vulnerability_library [ {“id”: “V-01”, “name”: “未授权访问”, “description”: “存在无需认证的接口。”}, {“id”: “V-02”, “name”: “弱口令”, “description”: “使用简单密码。”}, {“id”: “V-03”, “name”: “未安装关键补丁”, “description”: “存在已知高危漏洞。”}, {“id”: “V-04”, “name”: “备份缺失”, “description”: “无有效备份。”} ] risk_assessments [ {“id”: “RA-001”, “asset_id”: “AST-001”, “threat_id”: “T-01”, “vulnerability_id”: “V-03”, “likelihood”: 4, “severity”: 4, “risk_value”: 0.0}, {“id”: “RA-002”, “asset_id”: “AST-002”, “threat_id”: “T-02”, “vulnerability_id”: “V-02”, “likelihood”: 3, “severity”: 5, “risk_value”: 0.0}, {“id”: “RA-003”, “asset_id”: “AST-002”, “threat_id”: “T-04”, “vulnerability_id”: “V-04”, “likelihood”: 2, “severity”: 5, “risk_value”: 0.0}, {“id”: “RA-004”, “asset_id”: “AST-003”, “threat_id”: “T-03”, “vulnerability_id”: “V-01”, “likelihood”: 3, “severity”: 3, “risk_value”: 0.0} ] return assets, threat_library, vulnerability_library, risk_assessments4.2 核心计算函数实现接下来是实现两个核心计算函数calculate_asset_value和calculate_risk_value。def calculate_asset_value(asset): “”“计算单个资产的价值。 公式: 资产价值 (保密性 完整性 可用性) / 3 保留一位小数。 ”“” c asset.get(“confidentiality”, 1) i asset.get(“integrity”, 1) a asset.get(“availability”, 1) # 简单平均计算也可以根据业务需求改为加权平均 value round((c i a) / 3.0, 1) return value def calculate_all_asset_values(assets): “”“计算所有资产的价值并更新到资产字典中。”“” for asset in assets: asset[“value”] calculate_asset_value(asset) print(“[INFO] 所有资产价值计算完成。”) def calculate_risk_value(risk_assessment, asset_value): “”“计算单条风险评估记录的风险值。 公式: 风险值 资产价值 × 威胁可能性 × 脆弱性严重程度 ”“” likelihood risk_assessment.get(“likelihood”, 1) severity risk_assessment.get(“severity”, 1) risk_val asset_value * likelihood * severity return round(risk_val, 2) # 保留两位小数 def calculate_all_risk_values(assets, risk_assessments): “”“计算所有风险评估记录的风险值。 需要先根据 asset_id 找到对应的资产价值。 ”“” # 创建一个资产ID到资产价值的映射字典方便快速查找 asset_value_map {asset[“id”]: asset[“value”] for asset in assets} for ra in risk_assessments: asset_id ra[“asset_id”] asset_value asset_value_map.get(asset_id, 1.0) # 如果找不到默认给1.0 ra[“risk_value”] calculate_risk_value(ra, asset_value) print(“[INFO] 所有风险值计算完成。”)注意事项在calculate_all_risk_values函数中我创建了一个asset_value_map映射字典。这是一个非常实用的性能优化技巧。如果不这样做你就需要在双层循环中遍历资产列表来查找每个risk_assessment对应的资产当数据量稍大时比如几百条记录效率会非常低。用字典哈希表实现O(1)时间复杂度的查找是处理这类关联查询的常规操作。4.3 风险等级判定与报告生成计算出的风险值是一个数字我们需要将其转化为更直观的风险等级。def determine_risk_level(risk_value): “”“根据风险值确定风险等级。 划分阈值可以根据实际业务调整。这里是一个示例 高风险: risk_value 50 中风险: 20 risk_value 50 低风险: risk_value 20 ”“” if risk_value 50: return “高” elif risk_value 20: return “中” else: return “低” def generate_report(assets, threat_lib, vul_lib, risk_assessments): “”“生成并打印风险评估报告。”“” print(“\n” “”*60) print(“信息安全风险评估报告”) print(“”*60) # 1. 资产清单 print(“\n1. 资产清单与价值评估”) print(“-”*40) for asset in assets: level “高” if asset[“value”] 4.0 else (“中” if asset[“value”] 2.5 else “低”) print(f“ID: {asset[‘id’]:10} 名称: {asset[‘name’]:20} 价值: {asset[‘value’]:4} (等级: {level})”) # 2. 风险清单按风险值降序排序 print(“\n2. 风险清单按风险值降序排序”) print(“-”*80) # 排序前为每条记录补充详细信息并确定等级 detailed_risks [] for ra in risk_assessments: asset next((a for a in assets if a[“id”] ra[“asset_id”]), {“name”: “未知资产”}) threat next((t for t in threat_lib if t[“id”] ra[“threat_id”]), {“name”: “未知威胁”}) vul next((v for v in vul_lib if v[“id”] ra[“vulnerability_id”]), {“name”: “未知脆弱性”}) risk_level determine_risk_level(ra[“risk_value”]) detailed_risks.append({ “id”: ra[“id”], “asset_name”: asset[“name”], “threat_name”: threat[“name”], “vul_name”: vul[“name”], “likelihood”: ra[“likelihood”], “severity”: ra[“severity”], “risk_value”: ra[“risk_value”], “risk_level”: risk_level }) # 按风险值降序排序 detailed_risks.sort(keylambda x: x[“risk_value”], reverseTrue) for dr in detailed_risks: print(f“ID: {dr[‘id’]:8} | 资产: {dr[‘asset_name’]:15} | 威胁: {dr[‘threat_name’]:12} | 脆弱性: {dr[‘vul_name’]:10}”) print(f“ 可能性: {dr[‘likelihood’]} | 严重性: {dr[‘severity’]} | 风险值: {dr[‘risk_value’]:6} | 风险等级: 【{dr[‘risk_level’]}】”) print(“ ” “-”*70) # 3. 风险统计 print(“\n3. 风险等级统计”) print(“-”*40) level_count {“高”: 0, “中”: 0, “低”: 0} for dr in detailed_risks: level_count[dr[“risk_level”]] 1 for level, count in level_count.items(): print(f“{level}风险数量: {count}”) # 4. 最高风险项提示 if detailed_risks: top_risk detailed_risks[0] print(f“\n[!] 最高风险项: {top_risk[‘asset_name’]} 面临的 {top_risk[‘threat_name’]} 威胁 (风险值: {top_risk[‘risk_value’]}) 建议优先处置。”)4.4 主函数与执行最后我们把所有函数串联起来形成一个完整的脚本。def main(): “”“主函数执行风险评估全流程。”“” print(“开始执行信息安全风险评估模型...”) # 1. 初始化数据 assets, threat_lib, vul_lib, risk_assessments init_data() print(f“[INFO] 数据加载完成。资产数: {len(assets)} 威胁数: {len(threat_lib)} 脆弱性数: {len(vul_lib)} 评估记录数: {len(risk_assessments)}”) # 2. 计算所有资产价值 calculate_all_asset_values(assets) # 3. 计算所有风险值 calculate_all_risk_values(assets, risk_assessments) # 4. 生成并输出报告 generate_report(assets, threat_lib, vul_lib, risk_assessments) print(“\n风险评估报告生成完毕。”) if __name__ “__main__”: main()现在在命令行运行python risk_assessment_model.py你就能看到一份完整的风险评估报告输出在控制台了。5. 模型优化与功能扩展基础的模型跑通了但这只是个开始。一个真正实用的工具还需要考虑更多。下面分享几个关键的优化和扩展方向这也是体现你项目深度的部分。5.1 数据持久化从代码到文件硬编码数据只适用于演示。实际使用时我们需要从文件如CSV、JSON读取数据并将结果保存下来。使用JSON文件存储数据 创建一个data.json文件来存储所有数据。{ “assets”: [ {“id”: “AST-001”, “name”: “官网Web服务器”, “description”: “承载公司官网”, “confidentiality”: 3, “integrity”: 4, “availability”: 5} ], “threats”: [ {“id”: “T-01”, “name”: “DDoS攻击”, “description”: “耗尽目标资源。”} ], “vulnerabilities”: [ {“id”: “V-01”, “name”: “未授权访问”, “description”: “存在无需认证的接口。”} ], “assessments”: [ {“id”: “RA-001”, “asset_id”: “AST-001”, “threat_id”: “T-01”, “vulnerability_id”: “V-01”, “likelihood”: 4, “severity”: 4} ] }然后修改初始化函数从JSON文件加载import json def load_data_from_json(filepath): “”“从JSON文件加载数据。”“” try: with open(filepath, ‘r’, encoding‘utf-8’) as f: data json.load(f) return data.get(“assets”, []), data.get(“threats”, []), data.get(“vulnerabilities”, []), data.get(“assessments”, []) except FileNotFoundError: print(f“[ERROR] 数据文件 {filepath} 未找到将使用空数据。”) return [], [], [], [] except json.JSONDecodeError: print(f“[ERROR] 数据文件 {filepath} 格式错误。”) return [], [], [], []将报告输出到文件 同样我们可以轻松地将generate_report函数输出的内容写入到一个文本文件中。def generate_report_to_file(assets, threat_lib, vul_lib, risk_assessments, output_file“risk_report.txt”): “”“生成风险评估报告并保存到文件。”“” import sys original_stdout sys.stdout with open(output_file, ‘w’, encoding‘utf-8’) as f: sys.stdout f # 重定向标准输出到文件 generate_report(assets, threat_lib, vul_lib, risk_assessments) sys.stdout original_stdout # 恢复标准输出 print(f“[INFO] 风险评估报告已保存至: {output_file}”)5.2 交互式数据录入对于偶尔的、小规模的评估一个命令行交互界面比编辑JSON文件更友好。我们可以用input()函数实现。def interactive_input(): “”“通过命令行交互式输入一条风险评估记录。”“” print(“\n--- 开始交互式风险评估录入 ---”) asset_id input(“请输入资产ID (例如 AST-001): “).strip() threat_id input(“请输入威胁ID (例如 T-01): “).strip() vul_id input(“请输入脆弱性ID (例如 V-01): “).strip() try: likelihood int(input(“请输入威胁可能性 (1-5): “).strip()) severity int(input(“请输入脆弱性严重程度 (1-5): “).strip()) # 确保输入在有效范围 likelihood max(1, min(5, likelihood)) severity max(1, min(5, severity)) except ValueError: print(“[WARNING] 输入非数字将使用默认值1。”) likelihood severity 1 new_assessment { “id”: f“RA-{len(risk_assessments)1:03d}”, # 自动生成ID “asset_id”: asset_id, “threat_id”: threat_id, “vulnerability_id”: vul_id, “likelihood”: likelihood, “severity”: severity, “risk_value”: 0.0 } print(f“已创建评估记录: {new_assessment}”) return new_assessment在主函数中你可以添加一个选项让用户选择是加载文件还是交互输入。5.3 引入加权计算与矩阵法我们之前的资产价值计算是简单平均风险计算是直接相乘。在实际中可能需要更精细的模型。资产价值加权计算 对于不同的资产CIA三性的重要性可能不同。比如对于数据库保密性权重要高对于官网可用性权重要高。def calculate_asset_value_weighted(asset, weights{“confidentiality”: 0.4, “integrity”: 0.3, “availability”: 0.3}): “”“使用加权平均计算资产价值。”“” c asset.get(“confidentiality”, 1) * weights.get(“confidentiality”, 0.33) i asset.get(“integrity”, 1) * weights.get(“integrity”, 0.33) a asset.get(“availability”, 1) * weights.get(“availability”, 0.34) value round(c i a, 1) # 加权和 return value风险矩阵法 更专业的做法是使用风险矩阵。我们预先定义一个5x5的矩阵将可能性和严重性的等级组合映射到风险等级。# 定义一个风险矩阵 matrix[可能性][严重性] - 风险等级 RISK_MATRIX { 1: {1: “低”, 2: “低”, 3: “低”, 4: “中”, 5: “中”}, 2: {1: “低”, 2: “低”, 3: “中”, 4: “中”, 5: “高”}, 3: {1: “低”, 2: “中”, 3: “中”, 4: “高”, 5: “高”}, 4: {1: “中”, 2: “中”, 3: “高”, 4: “高”, 5: “高”}, 5: {1: “中”, 2: “高”, 3: “高”, 4: “高”, 5: “高”} } def determine_risk_level_by_matrix(likelihood, severity): “”“使用风险矩阵确定等级。”“” return RISK_MATRIX.get(likelihood, {}).get(severity, “未知”)然后在计算风险值时可以先通过矩阵得到等级再结合资产价值进行综合判断。例如高价值资产的“中”风险可能需要提升为“高”风险。5.4 可视化输出文字报告不够直观我们可以用matplotlib库生成图表。# 首先安装: pip install matplotlib import matplotlib.pyplot as plt def plot_risk_distribution(detailed_risks, output_image“risk_distribution.png”): “”“绘制风险分布柱状图。”“” if not detailed_risks: print(“[INFO] 无风险数据无法生成图表。”) return # 按风险等级分组计数 levels [“高”, “中”, “低”] counts [0, 0, 0] for dr in detailed_risks: if dr[“risk_level”] “高”: counts[0] 1 elif dr[“risk_level”] “中”: counts[1] 1 else: counts[2] 1 # 创建图表 plt.figure(figsize(8, 5)) bars plt.bar(levels, counts, color[‘#ff6b6b’, ‘#ffd93d’, ‘#6bcf7f’]) # 红黄绿 plt.title(‘信息安全风险等级分布’, fontsize14) plt.xlabel(‘风险等级’, fontsize12) plt.ylabel(‘数量’, fontsize12) # 在柱子上方显示数量 for bar, count in zip(bars, counts): height bar.get_height() plt.text(bar.get_x() bar.get_width()/2., height 0.1, f‘{count}’, ha‘center’, va‘bottom’) plt.tight_layout() plt.savefig(output_image, dpi300) print(f“[INFO] 风险分布图已保存至: {output_image}”) # plt.show() # 如果在桌面环境可以显示图表在主函数中调用plot_risk_distribution(detailed_risks)就能生成一张直观的风险分布图。6. 常见问题、排查技巧与避坑指南在实际编写和运行这个脚本的过程中你肯定会遇到一些问题。下面是我总结的一些常见坑点和解决思路。6.1 数据关联错误与查找失败问题在generate_report函数中使用next()查找资产、威胁、脆弱性信息时如果ID不匹配或数据缺失会返回None或导致StopIteration异常进而引发KeyError比如尝试访问asset[“name”]时asset是None。解决方案使用带默认值的next()如代码所示next((a for a in assets if a[“id”] ra[“asset_id”]), {“name”: “未知资产”})。这样即使找不到也会返回一个包含默认值的字典避免程序崩溃。增加数据完整性校验在计算风险值之前写一个校验函数检查所有risk_assessments中的asset_id、threat_id、vulnerability_id是否在对应的库中存在。def validate_data(assets, threats, vulns, assessments): asset_ids {a[“id”] for a in assets} threat_ids {t[“id”] for t in threats} vuln_ids {v[“id”] for v in vulns} errors [] for ra in assessments: if ra[“asset_id”] not in asset_ids: errors.append(f“评估记录 {ra[‘id’]} 引用了不存在的资产ID: {ra[‘asset_id’]}”) # 同理检查threat_id和vulnerability_id if errors: for err in errors: print(f“[ERROR] {err}”) return False return True6.2 数值范围与有效性检查问题用户在交互式输入或编辑JSON文件时可能输入超出1-5范围的值或者非数字导致计算结果异常比如风险值异常大或小。解决方案在输入环节限制如interactive_input函数中使用max(1, min(5, likelihood))进行钳制。在计算环节容错在calculate_asset_value和calculate_risk_value函数中使用.get(key, default_value)并提供合理的默认值如1。添加断言或日志在关键计算后可以加入断言或打印日志帮助调试。def calculate_risk_value(risk_assessment, asset_value): likelihood risk_assessment.get(“likelihood”, 1) severity risk_assessment.get(“severity”, 1) # 可选记录异常值 if not (1 likelihood 5) or not (1 severity 5): print(f“[WARNING] 记录 {risk_assessment.get(‘id’)} 的可能性或严重性值异常: L{likelihood}, S{severity}”) risk_val asset_value * likelihood * severity return round(risk_val, 2)6.3 性能问题与优化问题当资产、威胁、评估记录数量达到上千条时我们报告生成函数中的嵌套循环在detailed_risks的for循环里又用了next遍历查找可能会变得较慢。解决方案预构建映射字典这是最有效的优化。我们已经在calculate_all_risk_values里为资产价值做了。在generate_report里同样可以为威胁和脆弱性构建映射。threat_map {t[“id”]: t for t in threat_lib} vul_map {v[“id”]: v for v in vul_lib} asset_map {a[“id”]: a for a in assets} # 如果还没构建的话 for ra in risk_assessments: asset asset_map.get(ra[“asset_id”], {“name”: “未知”}) threat threat_map.get(ra[“threat_id”], {“name”: “未知”}) vul vul_map.get(ra[“vulnerability_id”], {“name”: “未知”}) # ... 后续处理这样就将O(n²)的查找复杂度降为了O(1)。考虑使用Pandas如果数据量非常大且需要复杂的分析和报表pandas库是更好的选择。它提供了高效的DataFrame操作但会引入额外的依赖。6.4 报告可读性与定制化问题控制台输出的报告格式可能不够美观或者领导需要特定格式如Word、PDF。解决方案美化控制台输出使用tabulate库可以轻松打印出漂亮的表格。# pip install tabulate from tabulate import tabulate table_data [[dr[‘id’], dr[‘asset_name’], dr[‘risk_value’], dr[‘risk_level’]] for dr in detailed_risks] headers [“ID”, “资产”, “风险值”, “风险等级”] print(tabulate(table_data, headersheaders, tablefmt“grid”))生成HTML/Word/PDF报告HTML可以用Jinja2模板引擎将数据填充到HTML模板中生成网页版报告。Word使用python-docx库可以编程创建和编辑Word文档。PDFreportlab库功能强大但稍复杂或者先生成HTML再用wkhtmltopdf转换。6.5 模型本身的局限性认知重要提醒我们这个Python实现的是一个简化版的定性/半定量风险评估模型。它非常适合用于快速筛查、内部讨论、风险排序和意识提升。但在正式的、需要审计的场合如等保测评通常需要遵循更严格的标准如ISO 27005、NIST SP 800-30使用更复杂的定量分析方法和专业的工具。我们这个脚本的价值在于快速原型帮助你在几分钟内对一个简单的系统环境完成风险初筛。理解过程通过代码彻底弄懂风险评估每个步骤在做什么。定制化基础你可以基于这个框架轻松地修改计算公式、添加新的属性如“合规性影响”、或者集成到其他自动化流程中。记住工具是辅助决策的而不是替代专业判断。最终的风险处置优先级还需要结合业务上下文、成本效益分析来综合决定。这个脚本输出的结果是你与业务、技术同事沟通时一份非常直观的“数据支撑”。