[英]Timing attack with PHP
我正在尝试在 PHP 中产生计时攻击,并且正在使用 PHP 7.1 和以下脚本:
<?php
$find = "hello";
$length = array_combine(range(1, 10), array_fill(1, 10, 0));
for ($i = 0; $i < 1000000; $i++) {
for ($j = 1; $j <= 10; $j++) {
$testValue = str_repeat('a', $j);
$start = microtime(true);
if ($find === $testValue) {
// Do nothing
}
$end = microtime(true);
$length[$j] += $end - $start;
}
}
arsort($length);
$length = key($length);
var_dump($length . " found");
$found = '';
$alphabet = array_combine(range('a', 'z'), array_fill(1, 26, 0));
for ($len = 0; $len < $length; $len++) {
$currentIteration = $alphabet;
$filler = str_repeat('a', $length - $len - 1);
for ($i = 0; $i < 1000000; $i++) {
foreach ($currentIteration as $letter => $time) {
$testValue = $found . $letter . $filler;
$start = microtime(true);
if ($find === $testValue) {
// Do nothing
}
$end = microtime(true);
$currentIteration[$letter] += $end - $start;
}
}
arsort($currentIteration);
$found .= key($currentIteration);
}
var_dump($found);
这是搜索具有以下约束的单词
该脚本可以毫无问题地找到单词的长度,但是单词的值永远不会通过计时攻击按预期返回。
有什么我做错了吗?
脚本通过长度循环,正确识别长度。 然后循环遍历每个字母 (az) 并检查这些字母的速度。 理论上,'haaaa' 应该比 'aaaaa' 稍慢,因为第一个字母是 h。 然后继续处理五个字母中的每一个。
跑步给出了类似 'brhas' 的东西,这显然是错误的(每次都不同,但总是错误的)。
有什么我做错了吗?
我不这么认为。 我尝试了你的代码,我也像你和其他在评论中尝试过的人一样,在第二个循环中得到完全随机的结果。 第一个(长度)大多是可靠的,尽管不是 100%。 顺便说一句,建议的$argv[1]
技巧并没有真正提高结果的一致性,老实说,我真的不明白为什么应该这样做。
由于我很好奇,我查看了 PHP 7.1 源代码。 字符串标识函数 ( zend_is_identical
) 如下所示:
case IS_STRING:
return (Z_STR_P(op1) == Z_STR_P(op2) ||
(Z_STRLEN_P(op1) == Z_STRLEN_P(op2) &&
memcmp(Z_STRVAL_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op1)) == 0));
现在很容易理解为什么对长度的第一次计时攻击效果很好。 如果长度不同,则永远不会调用memcmp
,因此它返回得更快。 即使没有太多迭代,差异也很容易被注意到。
一旦确定了长度,在第二个循环中,您基本上是在尝试攻击底层memcmp
。 问题是时间的差异在很大程度上取决于:
memcmp
的实现我推荐这篇题为“Benchmarking memcmp for Timing Attacks”的文章以获得更详细的解释。 他们做了一个更精确的基准测试,但仍然无法在时间上获得明显的明显差异。 我简单地引用一下文章的结论:
总之,如果
memcmp()
受到计时攻击,这在很大程度上取决于具体情况。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.