全文共计2946字,预计阅读15分钟
您是否曾花费很长时间寻找就在面前的钥匙?安全研究的感觉是一样的——你知道错误就在那里,隐藏在众目睽睽之下。
关于漏洞搜寻的问题是这样的:它很少是为了寻找新颖的零日漏洞。更常见的是,它是为了发现其他人错过的那些微妙的模式。挑战?足够快地测试数百个变化的样本,以找到一种突破一切的边缘情况。
长话短说
让我分享一下人工智能如何帮助发现文档 ID 系统中的漏洞,从而访问整个平台上的敏感文件。该错误本身并不是特别复杂,但使用人工智能使我们能够大规模分析模式——如果手动完成,这将非常耗时,而且可能会被忽视。
最初的发现
每个好的错误故事都是从“嗯,这有点怪”的那一刻开始的。我的开始是这样的一串:
672f7aacd9538fef01d44dd1721fe5767b5b1d3553672-181
只是来自上传系统的另一个文档 ID,对吧?但有些地方不对劲——它总是 49 个字符长,而不是您期望的 MD5 哈希值的 32 个字符长度,也不匹配 SHA1 或任何标准哈希算法。每次上传时,即使是相同的文件,它也会完全改变。
第一次尝试
ID 的模式看起来很有趣,因为该服务没有将用户授权 cookie 映射到文档 ID,因此如果它被破坏,我们可能会访问平台上的其他用户文档。
❝
🔍提示1:注意不符合通用标准的长度。他们经常暗示自定义实现,这可能是安全问题的金矿。
“它必须简单”阶段:
-
也许只是 Base64?不是。 -
一定是MD5吗?不是。 -
十六进制编码呢?不是。 -
sha256呢?不可能。
但这就是有趣的地方。相同的文件,相隔几秒上传,产生的 ID 不同......除了:
-
前几个字符看起来与某些模式相似 -
最后几位看似连续的数字
❝
🔍 提示2:测试文件上传时,始终快速连续尝试相同的文件。生成的 ID 中的差异(或相似之处)可以告诉您很多有关底层系统的信息。
利用人工智能进行模式分析
这就是人工智能LLMs改变游戏规则的地方。我没有手动分析模式,而是生成了 100 个 ID,并将它们提供给 Anthropic 的 Claude 3.5 进行分析。
我: "这里有 100 个文档 ID。你能发现任何模式吗,特别是在时间戳相关的?"
Claude: "前 8 个字符似乎是十六进制时间戳。看看这些连续的上传..."
事实上,几秒钟之内我们就取得了第一个突破:
pattern = {
'timestamp': id[:8], # Hex timestamp
'random': id[8:45], # Unknown portion
'sequence': id[46:] # Sequential number
}
❝
🔍提示3:人工智能不仅用于编码,还用于模式识别。它可以发现数据中的规律性,而这些规律性可能需要数小时才能手动注意到。
通过Burp Sequencer分析得出的新信息表明中间部分是足够随机的。挑战在于,除了时间戳和序列号之外,相同的输入数据会产生不同的输出。
破解加密算法
中间部分(37 个字符)很有趣,因为我们已经了解其他部分的作用。
然而,它是:
-
MD5 太长 -
对于 SHA1 来说太短 -
GUID 太奇怪了 -
过于随机,无法以客户端为基础
它也不能基于像我们的 IP 地址或服务器 MAC 地址这样的固定值,因为静态数据点不会在每个请求之间发生变化来解释输出的随机性。
我利用LLM为各种哈希组合生成测试用例,以排除任何明显可以解释填充或哈希输入的内容,并假设序列用于输入:
test_strings = [
# Basic combinations
timestamp_hex + sequence,
sequence + timestamp_hex,
# With datetime variations
timestamp_str + sequence,
unix_timestamp + sequence,
# With the trailing 5 digits
timestamp_hex + full_hash[-5:],
sequence + full_hash[-5:],
# Reversed combinations
sequence[::-1] + timestamp_hex,
timestamp_hex[::-1] + sequence,
# Mixed formats
hex(int(sequence))[2:] + timestamp_hex,
timestamp_hex + hex(int(sequence))[2:],
# With different separators
f"{timestamp_hex}-{sequence}",
f"{timestamp_hex}_{sequence}",
f"{timestamp_hex}:{sequence}"
]
运气不太好,对于可能的基本算法来说,这开始变得过于复杂。
突破:给朋友打了个电话
我几乎要放弃了,但有件事一直困扰着我。就在那时,我联系了一位好朋友兼猎人同伴卢平,他是一位真正的快速验证想法的大师。
这对于安全研究至关重要——知道何时需要第二双眼睛。有时你需要有人告诉你你正在追逐死胡同,或者推动你深入挖掘。
我逐字逐句告诉了卢平 该应用程序感觉有点不可靠,使用 PHP 并且最后的迭代让我认为它没有经过深思熟虑
所以必须对哈希算法有一个简单的解释。
❝
🔍提示4:遇到困难时,用语言表达你的假设。有时,只要向别人解释问题就能找到解决方案。
我们就代码的用途进行了集思广益
-
是否使用临时文件名来生成哈希值?
$hash = md5(__DIR__ . $filename . time()) . substr(uniqid(), 0, 5);
-
是否加盐?
$hash = md5($filename . time() . $salt) . generatePadding(5);
-
它是一个 Unix 时间戳来哈希 + 一些填充吗?
$hash = md5(time()) . random_bytes(5);
-
它是一个要哈希的字符串时间戳 + 一些填充吗?
$hash = md5(date('Y-m-d H:i:s')) . bin2hex(random_bytes(5));
手动测试哈希理论就像看着油漆变干——技术上是可行的,但生命太短暂了。让人工智能加速我们的发现其中的匹配特征。
我们没有仔细研究每种可能性,而是将我们的理论提供给LLM ,后者将它们转换为一些 Python 排列选项和有针对性的 hashcat 命令,以便可以轻松验证理论。
Hashcat是破解哈希的强大工具。它支持多种算法和攻击类型,包括暴力破解、字典和基于规则的攻击,您可以向它提供输入和掩码,以生成针对缺失部分的测试用例。
这里的想法是为散列的缺失部分生成一个掩码,并针对已知部分对其进行测试。
这样的LLM提供的输出非常完美。系统在< 1秒内破解了它:
hashcat -m 0 -a 3 fef01d44dd1721fe5767b5b1d3553672 '672f7aac?h?h?h?h?h'
让我们分解一下这个命令:
-m 0: "Hey hashcat, we're dealing with plain old MD5 here"
-a 3: "Use mask attack mode" (more on this in a second)
fef01d44dd1721fe5767b5b1d3553672: The mysterious middle section we're trying to crack
672f7aac?h?h?h?h?h: The magic mask pattern
最后一部分是有趣的地方。我们告诉 hashcat:
672f7aac: "We know these exact characters from the timestamp"
?h?h?h?h?h: "Then try every possible hex character for these 5 positions"
使这个特别优雅的是有限的搜索空间:
# Search space breakdown
characters = 16 # Hex characters (0-9, a-f)
positions = 5 # Padding length
combinations = 16^5 = 1,048,576
在现代 GPU 上,这只需不到一秒的时间。运行 hashcat 证实了我们的理论:
fef01d44dd1721fe5767b5b1d3553672:672f7aacd9539
Session..........: hashcat
Status...........: Cracked
Hash.Mode........: 0 (MD5)
Hash.Target......: fef01d44dd1721fe5767b5b1d3553672
Time.Started.....: Sun Nov 10 17:39:07 2024 (0 secs)
Time.Estimated...: Sun Nov 10 17:39:07 2024 (0 secs)
Kernel.Feature...: Pure Kernel
Guess.Mask.......: 672f7aac?h?h?h?h?h [13]
理解模式
该算法使用带有 5 个字符填充的时间戳来生成 MD5 哈希值。
最初,我们期望填充是完全随机的 - 毕竟,这通常是填充的重点。经过一番头脑风暴,我们考虑了一个有趣的可能性:如果在哈希算法中将时间戳用作种子两次会怎样?提交文档时一次,生成 ID 时再次。
双时间戳理论
我请Claude帮忙分析这个理论,它很快证实了一个模式:
我们在文档 ID 中看到的种子与我们破解生成 32 个字符哈希的种子仅相差几个值:
原始哈希值: 672f7aac d9538 fef01d44dd1721fe5767b5b1d3553672 -181
破解输入: timestamp + d95389 [incremented by 1 from d9538]
破解输出: fef01d44dd1721fe5767b5b1d3553672
final Hash: timestamp + fef01d44dd1721fe5767b5b1d3553672 + 181
这意味着输出始终比输入大 1-5 个值,这可能是由于这些操作之间的时间差所致:
Upload Time (t1) → Process Time (t2) → ID Generation (t3)
↓ ↓ ↓
First Hash ----→ MD5 + Padding ----→ Final ID
“随机”填充根本不是随机的 - 它看起来像是时间戳的哈希值,进一步消除了这里的复杂性。
影响
该漏洞可实现经典的三明治攻击:
-
上传文档并请求其 ID -
稍等一会儿 -
再次请求ID -
时间戳差异揭示了时间戳和序列号,以计算出种子并下载其他用户的文档。
结论:LLMs和 Bug 搜寻
这次经历凸显了现代人工智能工具如何加速错误搜寻过程。虽然它们不能取代人类的直觉和经验,但它们可以:
-
快速识别大型数据集中的模式
-
生成全面的测试用例
-
发现生成的模式
-
加速假设检验
安全研究的未来在于人类直觉和人工智能分析的综合。这些工具增强了我们的能力,但核心技能保持不变:好奇心、毅力和发现不太适合的模式的能力。
请关注SecLink安全空间获取我们最新的更新
欢迎加入企业微信SecLink安全空间探讨安全问题!
原文始发于微信公众号(SecLink安全空间):从一个文件ID 到 PII 泄漏:使用AI挖掘数据
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论