第1步:設(shè)置測試環(huán)境
要測試代碼,您應(yīng)該設(shè)置一個測試環(huán)境。可以在計算機上使用xampp或lampp完成此操作。當然,您可以自己用php設(shè)置一個Apache網(wǎng)絡(luò)服務(wù)器。
您將需要一個網(wǎng)絡(luò)服務(wù)器,一個mysql數(shù)據(jù)庫和一個運行中的php解釋器來執(zhí)行代碼。
步驟2:示例數(shù)據(jù)庫
對于我們的測試案例,我們使用一個非常基本的數(shù)據(jù)庫,其中有兩個用戶。使用md5算法保護密碼。只需在數(shù)據(jù)庫上運行以下mysql代碼即可創(chuàng)建表:
SET SQL_MODE = “NO_AUTO_VALUE_ON_ZERO”;
SET AUTOCOMMIT = 0;
START TRANSACTION;
SET time_zone = “+00:00”;
CREATE TABLE IF NOT EXISTS `user` (
`id` bigint(15) NOT NULL,
`email` varchar(255) NOT NULL,
`password` varchar(32) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
INSERT INTO `user` (`id`, `email`, `password`) VALUES
(1, ‘admin@mysite.com’, ‘b655e3f4ae881514c4896b9cd707e4d2’),
(2, ‘guest@mysite.com’, ‘5d41402abc4b2a76b9719d911017c592’);
ALTER TABLE `user`
ADD PRIMARY KEY (`id`);
ALTER TABLE `user`
MODIFY `id` bigint(15) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=3;COMMIT;
步驟3:關(guān)于密碼安全性的簡短介紹
全世界的計算能力正在飛速增長,md5不再是強大的哈希算法。所使用的哈希是使用以下密碼生成的:
b655e3f4ae881514c4896b9cd707e4d2 = top secret password that will never be cracked that fast
5d41402abc4b2a76b9719d911017c592 = hello
由于存在彩虹表之類的東西,即使google本身也是一個很好的密碼破解機。當您搜索“ 5d41402abc4b2a76b9719d911017c592”時,第一個結(jié)果是明文密碼。當您在Google中搜索“ b655e3f4ae881514c4896b9cd707e4d2”時,由于輸入字符串太長而無法使用蠻力方法破解,因此您將不會獲得任何結(jié)果。
因此:請使用在任何詞典中都不會出現(xiàn)的長密碼!/p》
步驟4:示例代碼
出于測試原因,我編寫了這個小腳本。它打開一個數(shù)據(jù)庫連接,提供一個表單,并嘗試在數(shù)據(jù)庫中查找與您輸入的憑據(jù)(電子郵件和密碼)匹配的用戶。只需將腳本保存在Web服務(wù)器上,然后將文件命名為“ mysql-injection.php”即可。當數(shù)據(jù)庫名稱不同時,可能必須為“ mysql_select_db”函數(shù)更新數(shù)據(jù)庫名稱:
error_reporting(E_ALL ^ E_DEPRECATED);
mysql_connect(‘localhost’, ‘root’, ‘’);
mysql_select_db(‘mysql-injection’);
if (!empty($_POST[‘email’]) && !empty($_POST[‘password’]))
{
$query = ‘SELECT * FROM `user` WHERE `email` = \’‘.$_POST[’email‘]。’\‘ AND `password` = \’‘.md5($_POST[’password‘])。’\‘’;
echo ‘Used query: ’,$query,‘’;
$resource = mysql_query($query);
$matches = mysql_num_rows($resource);
if ($matches 》 0)
{
$user = mysql_fetch_assoc($resource);
echo ‘Hello ’.$user[‘email’]。‘!’;
}
else
{
echo ‘Invalid credentials!’;
}
}
?》
Log in to get privileges!
Mail:
Password:
步驟5:測試腳本
要開始使用,只需在Web瀏覽器上調(diào)用腳本即可。在我的情況下,該網(wǎng)址為http://sand.box:8081/mysql-injection.php,因為我將“ sand.box”路由為“ 127.0.0.1”。您只需調(diào)用http://sand.box:8081/mysql-injection.php或http://sand.box:8081/mysql-injection.php即可使其正常工作。
我們現(xiàn)在可以使用以下憑據(jù)測試登錄:
admin@mysite.com:top secret password that will never be cracked that fast
guest@mysite.com:hello
如您在屏幕快照中所見,腳本返回“ Hello ”以證明您的登錄憑據(jù)正確。使用任何其他組合可獲得“無效的憑據(jù)!”錯誤。
這是有效的用戶身份驗證。但是它非常危險。請查看下一步,了解原因。
步驟6:幕后花絮
由于腳本輸出了用于選擇正確用戶的數(shù)據(jù)庫查詢,因此您可以看到背后發(fā)生了什么現(xiàn)場。當您以管理員身份登錄時,以下查詢:
‘SELECT * FROM `user` WHERE `email` = \’‘.$_POST[’email‘]。’\‘ AND `password` = \’‘.md5($_POST[’password‘])。’\‘’
計算為:
‘SELECT * FROM `user` WHERE `email` = \’admin@mysite.com\‘ AND `password` = \’‘.md5(’top secret password that will never be cracked that fast‘)。’\‘’
,然后計算為:
‘SELECT * FROM `user` WHERE `email` = \’admin@mysite.com\‘ AND `password` = \’b655e3f4ae881514c4896b9cd707e4d2\‘’
,發(fā)送到mysql數(shù)據(jù)庫的是:
SELECT * FROM `user` WHERE `email` = ‘a(chǎn)dmin@mysite.com’ AND `password` = ‘b655e3f4ae881514c4896b9cd707e4d2’
因此,只需通過電子郵件地址和密碼選擇一個用戶。在這種情況下,這是對郵件驗證的可靠期望。變量$ _POST [‘email’]在附加到查詢之前是不安全的,因此我們可以在此處注入很多邪惡的東西。 $ _POST [‘password’]變量在被隱式存儲到數(shù)據(jù)庫查詢之前被傳遞給md5(),因此這是“意外的安全”,因為md5()僅返回數(shù)字和字符,沒有任何東西會使我們的查詢崩潰。 》
步驟7:破解!
正如我們在上一步中了解到的那樣,$ _ POST [‘email’]是我們的后門。因此,當您輸入以下電子郵件時,您可以以所需的任何用戶身份登錄。對于ID為1的用戶:
test@test.de‘ OR `id` = 1 OR 1 = ’
對于ID為2的用戶:
test@test.de‘ OR `id` = 2 OR 1 = ’
如您所見,使用的mysql查詢?nèi)缦拢?/p>
SELECT * FROM `user` WHERE `email` = ‘test@test.de’ OR `id` = 1 OR 1 = ‘’ AND `password` = ‘098f6bcd4621d373cade4e832627b4f6’
由于查詢中沒有括號,因此我們可以通過在電子郵件中傳遞一個‘來停止字符串。之后,我們可以修改查詢本身。因此,我們僅添加另一個與用戶ID相關(guān)的“ OR”條件。這使電子郵件和密碼已過時,因為一旦“ OR”條件為真,mysql就會停止檢查條件。因此,如果我們的數(shù)據(jù)庫中有一個ID為“ 1”的用戶,我們便已登錄。
步驟8:保護您的代碼
要確保此代碼安全,只需轉(zhuǎn)義用戶輸入即可。例如,可以使用mysql_real_escape_string方法來完成此操作。另一個功能可能是斜杠。因此,“安全”解決方案將使用:
mysql_real_escape_string($_POST[’email‘])
而不是
$_POST[’email‘]
所以這是最終的php代碼:
$query = ’SELECT * FROM `user` WHERE `email` = \‘’.mysql_real_escape_string($_POST[‘email’])。‘\’ AND `password` = \‘’.md5($_POST[‘password’])。‘\’‘;
計算的查詢?yōu)椋?/p>
SELECT * FROM `user` WHERE `email` = ’test@test.de\‘ OR `id` = 1 OR 1 = \’‘ AND `password` = ’098f6bcd4621d373cade4e832627b4f6‘
因此,您可以看到,字符串中的單引號現(xiàn)在已轉(zhuǎn)義,不再結(jié)束mysql字符串。這將導(dǎo)致查詢搜索以下電子郵件地址:
test@test.de\’ OR `id` = 1 OR 1 = \‘
當然,這將失敗,因為數(shù)據(jù)庫中沒有匹配的電子郵件。
第9步:僅僅為了獲得一個想法
編寫此指令是為了在一個非常基本的情況下獲得mysql注入的想法。在2015年,您不會自己編寫php應(yīng)用程序,而是使用可以為您處理大部分安全性和數(shù)據(jù)庫內(nèi)容的框架和庫。但是您應(yīng)該知道在幕后發(fā)生了什么事,以便快速,安全地編寫代碼。
例如,一個好的解決方案是使用symfony2框架。
-
Web服務(wù)器
+關(guān)注
關(guān)注
0文章
138瀏覽量
24371 -
漏洞
+關(guān)注
關(guān)注
0文章
204瀏覽量
15358
發(fā)布評論請先 登錄
相關(guān)推薦
評論