复现环境
https://buuoj.cn/challenges#[Zer0pts2020]Can%20you%20guess%20it?
考察知识点
- 代码审计
- PHP_SELF与basename变量特性了解
- 正则表达式绕过
解题分析
让猜一个什么东西,直接点击Source查看源码。
<?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.';
}
}
?>
guess 部分是随机一个64比特的随机字节,hash_equals()
来比较字符串,等效于使用===
,那么爆破密码和弱类型这两种就可以不用考虑了。
source 部分是使当前运行的脚本代码高亮,相当于读取源代码。
$_SERVER['PHP_SELF']
返回的是当前正在执行的脚本的名字
'PHP_SELF'
当前执行脚本的文件名,与 document root 有关。例如,在地址为 http://example.com/foo/bar.php 的脚本中使用 $_SERVER['PHP_SELF'] 将得到 /foo/bar.php。FILE 常量包含当前(例如包含)文件的完整路径和文件名。 从 PHP 4.3.0 版本开始,如果 PHP 以命令行模式运行,这个变量将包含脚本名。之前的版本该变量不可用。
basename
则可以返回路径中的文件名部分,就算后面跟上多余的字符也会返回文件名部分。
如果传入/index.php/config.php/
,则$_SERVER['PHP_SELF']
返回/index.php/config.php/
,basename($_SERVER['PHP_SELF'])
返回config.php
。
即/index.php/config.php/
运行的是index.php
,但是basename()
获取到的是config.php
。
正常我们可以/index.php/config.php?source
读取,但是因为存在正则/config\.php\/*$/i
来限制URL结尾出现config.php
字符串。

ASCII值范围为0-255,但ASCII码并没有规定编号为128~255的字符,ASCII表范围为0-127,也就是我们传入128以上的数值,即可绕过正则,128 -> 0x80
payload:/index.php/config.php/%80?source
网友评论