摘要:
基于php+mysql平台的sql注入攻防的实操,提供较详细的ubuntu平台上的操作步骤,方便练手。
使用的平台:
Ubuntu 12.04,php 5.3.10, mysql Ver 14.14, Apache/2.2.22
步骤:
1. 在ubuntu上安装Apache,mysql,具体过程自行百度;
2.1 首先熟悉如何再mysql中建立数据表?包括用户名和对应的密码;并且熟悉其中的查询命令;完成查询测试;
2.2 完成php端的代码,完成php和mysql的链接;完成链接查询测试;
2.3 基于浏览器端的sql攻击测试;
2.1首先是对mysql的操作:
a)创建user数据库:create database user;
b)切换到user数据库:use user;
c)创建account表:create table account(name VARCHAR(20), password VARCHAR(20));里面包含用户的名字和密码;
d)在account表中插入数据:
insert into account values
(‘aaa‘, ‘111‘),
(‘bbb‘, ‘222‘);
即完成在数据库user的account表中插入两个用户的用户名和密码;
2.2 如何将php与mysql相联接?
mysql端需要设置权限,将user数据库的访问权授予findme,并且密码为findmeifyoucan.
grant select, delete on user.* to findme identified by ‘findmeifyoucan‘;
在php后端需要建立链接的代码如下:
$db = new mysqli(‘localhost‘, ‘findme‘, ‘findmeifyoucan‘, ‘user);
2.3下面分别是浏览器端和php后端的对应的代码(显示原理为主,代码尽量简化);浏览器端的html代码login.html:
<html> <head> <title>Please log in.</title> </head> <body> <form action="result.php" method="post"> Enter your user name:<br /> <input name="user" type="text" size="40" /> <br /> Enter your password:<br /> <input name="psd" type="text" size="40" /> <br /> <input type="submit" name="submit" value="search" /> </form> </body> </html>
下面是php端的代码result.php:
<span style="font-size:14px;"><html> <head> <title>see if you can login</title> </head> <body> <h1>Check wether you can login in or not?</h1> <?php function check($db) { $name = $_POST["user"]; $password = $_POST["psd"]; $result = $db->query("select count(*) from account where name = '$name' and password = '$password'"); $row = $result->fetch_assoc(); if($row['count(*)'] != 0){ echo 'you login in'; }else{ echo 'you not login'; } } $db = new mysqli('localhost', 'findme', 'findmeifyoucan', 'user'); if(mysqli_connect_errno()){ echo 'Error: could not connect to database user. Please try again.'; exit; } check($db); $db->close(); ?> </body> </html></span>
在浏览器中,访问localhost/login.html,再输入登陆的用户名和密码即进行测试。上面的代码不能抵御下面sql注入攻击:
如果输入user:aaa, password:111;则顺利登陆;这不奇怪,但是在password处输入下面的代码:112‘ or ‘1‘=‘1, 也可以正常登陆,此时的sql语句如下:
select count(*) from account where name=‘aaa‘ and password=‘112‘ or ‘1‘=‘1‘;
后面的‘1‘=‘1‘逻辑成立,所以返回不为0。
那怎么应对这种情况呢?常见的解决方式是对输入的值进行转义符操作;具体的操作方式如下:
$name=addslashes($name);
$password=addslash3s($password);
这样的操作后,就可以规避112‘ or ‘1‘=‘1的攻击;原因也很简单,因为select查询语句变为如下:
select count(*) from account where name=‘aaa‘ and password=‘112\‘ or \‘1\‘=\‘1‘;
数据库中用户‘aaa‘的密码明显不可能是‘112\‘而且\‘1\‘=\‘1‘也不成立,所以就起到防御作用。
结论:
1. 上述代码虽然简单,但是本人也不是一次就写对,还是借助了php的调试功能,需要区分php在开发和
生产阶段的调试设置的不同;
2. 实践过程再一次证明:只要系统可观察,就可以理解;