上周末,笔者为研究KNIME的爬虫工作流,从某网站上下载了一个开源工作流作为学习对象。不幸,系统因此感染Malware.Gen系列木马病毒。虽然最终得以解决,但不得不重视网络安全必要性。相比较普通用户,价值较高的企业被木马程序攻击的风险,以及被植入后造成的损失都要更大。因此防范病毒也是网络安全中的重要课题之一。普通木马程序已能被大多数杀毒软件及时发现,并向用户提示,但高级木马程序已能实现删除关键日志记录或篡改、伪造日志条目,来实现掩盖入侵痕迹和伪装行为的操作。那么如何去验证日志记录是否被删除或篡改呢?20世纪80年代末到90年代初,在互联网的快速发展下,人们亟需一种能在信息传输过程中确保数据的完整性和真实性,同时能支持基于公钥密码学的数学签名机制。Ronald Rivest设计的MD系列哈希算法应运而生,它将任意长度的输入数据(如文件、消息),通过特定的算法生成固定长度的输出值,且具有敏感性(输入数据的微小变化会导致哈希值完全不同)、唯一性(不同的输入数据尽可能生成不同的哈希值,因此理论上具有唯一性)、压缩性(输入数据的长度是任意的,但是哈希值的长度是固定的)、不可逆性(无法通过哈希值反推原始数据)。MD系列算法随后也衍生出SHA、BLAKE等系列的现代哈希算法,满足日渐提高的安全需求,并广泛应用于数据完整性验证、数字签名、密码学等应用领域。 | | |
| | |
| | |
| | |
| | |
| | |
| | 不安全,2005 年起被发现存在碰撞攻击,现已废弃 |
| 安全性高,支持多种输出长度(SHA-224、SHA-256、SHA-384、SHA-512) | 在大数据和并行处理场景中速度略逊于 BLAKE 系列 |
| 基于海绵函数设计,抗碰撞能力强,适合高安全需求场景 | 速度较慢,硬件加速支持不足,兼容性不如 SHA-2 |
| | |
| 基于 ChaCha 核心设计,安全性高,速度比 SHA 系列更快 | |
| 比 SHA-2 快 2-3 倍,安全性等同于 SHA-3,支持嵌入式和硬件优化 | 在传统应用场景中兼容性不如 SHA 系列(不符合 NIST 标准) |
| 极高的速度和并行性能,适合多核计算和大数据场景;内置抗量子计算能力潜力 | |
由于BLAKE系列算法还处于推广阶段,未被广泛采用,则被美国国家标准与技术研究院(NIST)采纳为全球密码学标准的算法即是SHA系列算法。因此利用哈希值的特性,将其利用在日志文件内容变更监控上,是个不错的选择。“hello world”和“hello world?”之间的哈希值会有什么差异呢?笔者利用SHA-2中的SHA-256(256位长度)进行计算,并采用汉明距离(Hamming Distance)来计算哈希值之间的大小差异,即当汉明距离越大,哈希值的差异越大,文件内容在字节或位的层面上差异就越明显。import hashlib
def hamming_distance(hash1, hash2):
# 将哈希值转换为二进制
bin1 = bin(int(hash1, 16))[2:].zfill(256)
bin2 = bin(int(hash2, 16))[2:].zfill(256)
# 计算汉明距离(不同的位数)
return sum(c1 != c2 for c1, c2 in zip(bin1, bin2))
# 输入字符串
data1 = "hello world"
data2 = "hello world?"
# 转换为字节格式data_bytes1 = data1.encode('utf-8')
data_bytes2 = data2.encode('utf-8')
# 利用SHA-256 计算字符串哈希值
hash1 = hashlib.sha256(data_bytes1).hexdigest()
hash2 = hashlib.sha256(data_bytes2).hexdigest()
# 打印哈希值
print(f"哈希值 '{data1}': {hash1}")
print(f"哈希值 '{data2}': {hash2}")
# 计算汉明距离
distance = hamming_distance(hash1, hash2)
print(f"汉明距离: {distance}")
# 输出结果
# 哈希值 'hello world': b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9
# 哈希值 'hello world?': af17ed267525a09e28e477a1af30a74ca49c74bc3078cd5bb28d89976714142d
# 汉明距离: 130
在256位SHA算法下,得出两者的汉明距离为130,即代表有130位不同,判断出两个字符串之间差异明显。但当我将字符串替换为“hello world”与“hellp lorld”之后,其哈希值反而变小,为123。其原因是哈希算法具有雪崩效应,但每个输入字符的修改或者添加所带来的变化又不总是均匀的,很无奈。但好在能够告诉我两个字符串发生了显著变化。import hashlib
def calculate_file_hash(file_path):
# 创建 SHA-256 哈希对象
sha256_hash = hashlib.sha256()
# 打开文件并以二进制模式读取内容
with open(file_path, "rb") as file:
# 分块读取文件,避免文件太大导致内存问题
for byte_block in iter(lambda: file.read(4096), b""):
sha256_hash.update(byte_block)
# 返回文件的哈希值(十六进制格式)
return sha256_hash.hexdigest()
def hamming_distance(hash1, hash2):
# 将哈希值从十六进制转换为二进制
bin_hash1 = bin(int(hash1, 16))[2:].zfill(256) # SHA-256 产生 256 位的二进制
bin_hash2 = bin(int(hash2, 16))[2:].zfill(256)
# 计算不相同的比特位数量
return sum(c1 != c2 for c1, c2 in zip(bin_hash1, bin_hash2))
# 输入文件路径
file1 = r"C:\Users\Desktop\file1.txt"
file2 = r"C:\Users\Desktop\file2.txt"
# 计算文件的哈希值
hash1 = calculate_file_hash(file1)
hash2 = calculate_file_hash(file2)
print(f"File 1 Hash: {hash1}")
print(f"File 2 Hash: {hash2}")
# 计算汉明距离
distance = hamming_distance(hash1, hash2)
print(f"Hamming Distance: {distance}")
以上就是哈希值的计算,以及判断哈希值之间差异大小的方法。回归正题,前文说到高级木马程序可能会删除或篡改日志条目等,如何去验证日志记录是否被删除或篡改?即可通过文件的实时监控,发现踪迹,即对系统重关键文件(如操作系统文件、应用程序文件、注册表信息文件等)计算哈希值,当文件被创建、修改或访问时,计算该文件的哈希值并进行比对,即可发现木马程序的踪迹;又可通过深度分析木马病毒的文件特征,提取哈希值,并将其添加到木马数据中;定期扫描系统文件,将系统中每个文件的哈希值与木马病毒库中的哈希值进行对比,若对比一致,即该文件可能是已知的木马病毒。此种方法不需要逐一检查文件内容,也可快速验证任何文件的完整性以及一致性,不失为一种可靠的方法。(1)审计、诉讼证据的固定。在裁判文书网上有着大量采用哈希值固定诉讼证据的案例,感兴趣的朋友可以搜一搜,同时审计证据对于审计报告以及人员定责上至关重要,为防止别有用心之人,也可利用哈希值来固定审计证据;(2)审计档案的固定。哈希值可确保归档的数据在长期储存中未被篡改,为后续审计提供可靠依据;(3)数据溯源。若数据分发时,每份数据都附有唯一的哈希值,就可以帮助确认数据的原始来源或分发链条。总结下来哈希值能够验证数据是否被篡改能够快速进行大规模的数据比较和校验,以及发现潜在的安全风险。(1)攻击者利用碰撞,构造一个与原始文件哈希值相同但内容不同的恶意文件,从而绕过安全验证机制;(2)哈希值只能告诉你输入的数据发生了变化,但无法提供具体变化的细节,例如哪个位置的内容被修改或增加了什么数据;(3)在实时监控场景中,文件内容可能自然增长或动态变化,若仅依据哈希值变化,可能会被误判为篡改;(4)哈希值的不可逆性,使得无法直接利用哈希值追溯数据的来源或重构原始数据;(5)哈希算法是将输入数据映射到固定长度,由于输入的数据可能是无限的,而哈希值的长度是有限的,所以可能会产生哈希碰撞是不可避免的,即哈希值在理论上是唯一的。最后,笔者仍有不足之处,欢迎大家与笔者交流或补充~