ClamAV日志转JSON:多Linux系统扫描结果对接SIEM技术求助
嘿,别担心!作为Python新手完全能搞定这个需求,我来一步步带你实现,让ClamAV的输出顺利对接SIEM。
先搞清楚ClamAV的输出格式
首先,咱们得知道ClamAV默认输出长啥样。比如用clamscan命令扫描时,典型输出是这样的:
/home/user/test/file1.txt: OK
/home/user/test/file2.exe: Win.Test.Virus FOUND
/home/user/test/badfile: ERROR Can't open file or directory
----------- SCAN SUMMARY -----------
Known viruses: 8634567
Engine version: 0.103.8
Scanned directories: 12
Scanned files: 45
Infected files: 1
Data scanned: 23.45 MB
Data read: 18.21 MB (ratio 1.29:1)
Time: 12.345 sec (0 m 12 s)
咱们需要提取每一个文件的扫描结果,以及最后的扫描汇总信息。
步骤1:用Python调用ClamAV并捕获输出
Python的subprocess模块可以帮我们运行系统命令并获取输出,这是基础操作。下面是示例代码:
import subprocess import json def run_clamav_scan(scan_path): # 运行clamscan命令,--stdout确保输出到标准输出,避免终端颜色干扰 try: result = subprocess.run( ["clamscan", "--stdout", scan_path], capture_output=True, text=True, check=True # 如果命令执行失败(比如权限问题),会抛出异常 ) return result.stdout except subprocess.CalledProcessError as e: # 注意:clamscan如果扫描到病毒,退出码是1,这属于正常情况,不是错误 if e.returncode == 1: return e.stdout else: # 真正的错误,比如命令不存在、权限不足等 print(f"ClamAV扫描出错: {e.stderr}") return None
这里要注意:ClamAV的退出码规则是0=无病毒,1=发现病毒,2=扫描错误。所以我们要特殊处理returncode=1的情况,不要当成错误丢弃输出。
步骤2:解析ClamAV输出并转换成字典
接下来要把纯文本输出拆成结构化的数据。我们可以逐行处理输出,提取每个文件的信息,最后再处理汇总信息:
def parse_clamav_output(output): scan_results = { "files": [], "summary": {} } if not output: return scan_results lines = output.strip().split('\n') summary_started = False for line in lines: line = line.strip() if not line: continue # 检测是否进入汇总部分 if line.startswith("----------- SCAN SUMMARY -----------"): summary_started = True continue if summary_started: # 解析汇总行,比如"Known viruses: 8634567" if ":" in line: key, value = line.split(":", 1) scan_results["summary"][key.strip()] = value.strip() else: # 解析单个文件的结果 if ":" in line: file_path, status_part = line.split(":", 1) file_path = file_path.strip() status_details = status_part.strip().split(" ", 1) file_result = { "file_path": file_path, "status": status_details[0] } # 如果是发现病毒,提取病毒名 if len(status_details) > 1: file_result["virus_name"] = status_details[1] scan_results["files"].append(file_result) return scan_results
这个函数会把输出转换成一个包含files列表(每个文件的详细结果)和summary字典(扫描汇总信息)的结构,非常适合转成JSON。
步骤3:转换成JSON并输出/发送到SIEM
最后一步就是把结构化的数据转成JSON格式,你可以选择保存到文件,或者直接发送到SIEM的API:
def main(): # 替换成你要扫描的路径,比如"/"扫描整个系统(需要root权限) scan_path = "/home/user/test" # 运行扫描 scan_output = run_clamav_scan(scan_path) if not scan_output: print("扫描失败,无法获取输出") return # 解析输出 structured_data = parse_clamav_output(scan_output) # 转换成JSON字符串 json_output = json.dumps(structured_data, indent=4) # 选项1:打印到控制台,方便测试 print(json_output) # 选项2:保存到文件,供SIEM读取 with open("clamav_scan_results.json", "w") as f: f.write(json_output) # 选项3:发送到SIEM API(示例,根据你的SIEM调整) # import requests # siem_api_url = "https://your-siem-api-endpoint.com/logs" # requests.post(siem_api_url, json=structured_data) if __name__ == "__main__": main()
针对CentOS 7和Ubuntu 16.04的注意事项
- 安装依赖:确保已经安装了ClamAV(CentOS用
yum install clamav clamav-scanner,Ubuntu用apt-get install clamav clamav-daemon),并且更新了病毒库(freshclam命令)。 - 权限问题:扫描系统目录需要root权限,所以运行Python脚本时可能需要
sudo。 - ClamAV版本差异:两个系统的ClamAV版本可能略有不同,但核心输出格式是一致的,上面的代码应该都能兼容。
测试和调试
建议先在小目录上测试脚本,比如/tmp,看看输出的JSON是否符合预期。如果遇到解析错误,可以打印原始的ClamAV输出,调整解析逻辑。
内容的提问来源于stack exchange,提问作者Kevin Homan

