假期试着做了一下这场美国的CTF比赛,无奈题目看了一遍都没什么想法,只好等比赛结束再学习了。在这里总结一下学到的姿势。
(以下是六道php代码审计题目)
1.Prudential
I don‘t think that sha1 is broken. Prove me wrong.
代码如下:
level1
Invalid password.';
}
?>
经验证md5()函数同样存在此漏洞。
测试截图:
2.Symphony
A less than four characters number, bigger than 999? Maybe the bug is elsewhere.
代码如下:
level2
999)
die('Flag: '.$flag);
else
print 'Too little
';
} else
print 'Too long
';
} else
print 'Password is not numeric
';
}
?>
3.Northeastern Univ.
Of course, a timing attack might be the answer, but I'm quite sure that you can do better than that.
代码如下:
level3
Invalid password.';
}
?>
4.Museum of Fine Arts
Because cryptography is hard, we only implemented a hand-made PRNG. What could possibly go wrong?
代码如下:
level4
Wrong guess.';
}
// Unpredictable seed
mt_srand((microtime() ^ rand(1, 10000)) % rand(1, 10000) + rand(1, 10000));
?>
' . mt_rand (0, 0xffffff) . '';
$_SESSION['password'] = mt_rand (0, 0xffffff);
?>
5.Longwood Medical
Because we dont trust mysqli_real_escape_string, we wrote our own military-grade sanitization method.
代码如下:
level5
querySingle ($request);
$db->close ();
if ($result === FALSE)
echo '"Invalid login or password
';
else
die('Flag: ' . $flag);
} else
echo 'Invalid chars detected
';
}
?>
6.Brigham Circle
Sanitization is hard, lets use regexp!
代码如下:
level6
You password must be alphanumeric';
else if (strpos ($_GET['password'], '--') !== FALSE)
die('Flag: ' . $flag);
else
echo 'Invalid password
';
}
?>
此外还有一个非常微妙的方法。把password构造为数组,如:?password[]=a,由于ereg()也是只能处理字符串的,遇到数组做参数返回NULL,注意第一处判断用的是 === ,要求类型也相同,而NULL跟FALSE类型是不同的;第二处判断strpos()的参数同样不能为数组,否则返回NULL,而判断用的是 !== ,所以这里的条件成立,也能得到flag。
注:这里的第二处判断 !== 并非多此一举,因为当strpos()返回位置为0时用 == 将不知道到底是找到了还是没找到,于是不转换类型的 === 或 !== 是实际中普遍使用的。