第1步:设置测试环境
要测试代码,您应该设置一个测试环境。可以在计算机上使用xampp或lampp完成此操作。当然,您可以自己用php设置一个Apache网络服务器。
您将需要一个网络服务器,一个mysql数据库和一个运行中的php解释器来执行代码。
步骤2:示例数据库
对于我们的测试案例,我们使用一个非常基本的数据库,其中有两个用户。使用md5算法保护密码。只需在数据库上运行以下mysql代码即可创建表:
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:关于密码安全性的简短介绍
全世界的计算能力正在飞速增长,md5不再是强大的哈希算法。所使用的哈希是使用以下密码生成的:
b655e3f4ae881514c4896b9cd707e4d2 = top secret password that will never be cracked that fast
5d41402abc4b2a76b9719d911017c592 = hello
由于存在彩虹表之类的东西,即使google本身也是一个很好的密码破解机。当您搜索“ 5d41402abc4b2a76b9719d911017c592”时,第一个结果是明文密码。当您在Google中搜索“ b655e3f4ae881514c4896b9cd707e4d2”时,由于输入字符串太长而无法使用蛮力方法破解,因此您将不会获得任何结果。
因此:请使用在任何词典中都不会出现的长密码!/p》
步骤4:示例代码
出于测试原因,我编写了这个小脚本。它打开一个数据库连接,提供一个表单,并尝试在数据库中查找与您输入的凭据(电子邮件和密码)匹配的用户。只需将脚本保存在Web服务器上,然后将文件命名为“ mysql-injection.php”即可。当数据库名称不同时,可能必须为“ mysql_select_db”函数更新数据库名称:
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浏览器上调用脚本即可。在我的情况下,该网址为http://sand.box:8081/mysql-injection.php,因为我将“ sand.box”路由为“ 127.0.0.1”。您只需调用http://sand.box:8081/mysql-injection.php或http://sand.box:8081/mysql-injection.php即可使其正常工作。
我们现在可以使用以下凭据测试登录:
admin@mysite.com:top secret password that will never be cracked that fast
guest@mysite.com:hello
如您在屏幕快照中所见,脚本返回“ Hello ”以证明您的登录凭据正确。使用任何其他组合可获得“无效的凭据!”错误。
这是有效的用户身份验证。但是它非常危险。请查看下一步,了解原因。
步骤6:幕后花絮
由于脚本输出了用于选择正确用户的数据库查询,因此您可以看到背后发生了什么现场。当您以管理员身份登录时,以下查询:
‘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\‘’
,发送到mysql数据库的是:
SELECT * FROM `user` WHERE `email` = ‘admin@mysite.com’ AND `password` = ‘b655e3f4ae881514c4896b9cd707e4d2’
因此,只需通过电子邮件地址和密码选择一个用户。在这种情况下,这是对邮件验证的可靠期望。变量$ _POST [‘email’]在附加到查询之前是不安全的,因此我们可以在此处注入很多邪恶的东西。 $ _POST [‘password’]变量在被隐式存储到数据库查询之前被传递给md5(),因此这是“意外的安全”,因为md5()仅返回数字和字符,没有任何东西会使我们的查询崩溃。 》
步骤7:破解!
正如我们在上一步中了解到的那样,$ _ POST [‘email’]是我们的后门。因此,当您输入以下电子邮件时,您可以以所需的任何用户身份登录。对于ID为1的用户:
test@test.de‘ OR `id` = 1 OR 1 = ’
对于ID为2的用户:
test@test.de‘ OR `id` = 2 OR 1 = ’
如您所见,使用的mysql查询如下:
SELECT * FROM `user` WHERE `email` = ‘test@test.de’ OR `id` = 1 OR 1 = ‘’ AND `password` = ‘098f6bcd4621d373cade4e832627b4f6’
由于查询中没有括号,因此我们可以通过在电子邮件中传递一个‘来停止字符串。之后,我们可以修改查询本身。因此,我们仅添加另一个与用户ID相关的“ OR”条件。这使电子邮件和密码已过时,因为一旦“ OR”条件为真,mysql就会停止检查条件。因此,如果我们的数据库中有一个ID为“ 1”的用户,我们便已登录。
步骤8:保护您的代码
要确保此代码安全,只需转义用户输入即可。例如,可以使用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’])。‘\’‘;
计算的查询为:
SELECT * FROM `user` WHERE `email` = ’test@test.de\‘ OR `id` = 1 OR 1 = \’‘ AND `password` = ’098f6bcd4621d373cade4e832627b4f6‘
因此,您可以看到,字符串中的单引号现在已转义,不再结束mysql字符串。这将导致查询搜索以下电子邮件地址:
test@test.de\’ OR `id` = 1 OR 1 = \‘
当然,这将失败,因为数据库中没有匹配的电子邮件。
第9步:仅仅为了获得一个想法
编写此指令是为了在一个非常基本的情况下获得mysql注入的想法。在2015年,您不会自己编写php应用程序,而是使用可以为您处理大部分安全性和数据库内容的框架和库。但是您应该知道在幕后发生了什么事,以便快速,安全地编写代码。
例如,一个好的解决方案是使用symfony2框架。
-
Web服务器
+关注
关注
0文章
138浏览量
24399 -
漏洞
+关注
关注
0文章
204浏览量
15368
发布评论请先 登录
相关推荐
评论