在开发网站的时候,出于安全考虑,需要过滤从页面传递过来的字符。通常,用户可以通过以下接口调用数据库的内容:URL地址栏、登陆界面、留言板、搜索框等。这往往给骇客留下了可乘之机。轻则数据遭到泄露,重则服务器被拿下。一、sql注入的步骤
a) 寻找注入点(如:登录界面、留言板等)
b) 用户自己构造sql语句(如:' or 1=1#,后面会讲解)
d) DBMS接收请求,并将该请求解释成机器代码指令,执行必要的存取操作
e) DBMS接受返回的结果,并处理,返回给用户
因为用户构造了特殊的sql语句,必定返回特殊的结果(只要你的sql语句够灵活的话)。
下面,我通过一个实例具体来演示下sql注入
二、sql注入实例详解(以上测试均假设服务器未开启magic_quote_gpc)
1) 前期准备工作
首先,创建一张试验用的数据表:
`id`int(11) NOT NULL AUTO_INCREMENT,
`username`varchar(64) NOT NULL,
`password`varchar(64) NOT NULL,
`email`varchar(64) NOT NULL,
PRIMARYKEY (`id`),
UNIQUEKEY `username` (`username`)
)ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;
添加一条记录用于测试:
VALUES('MarcoFly',md5('test'),'marcofly@test.com');
当用户点击提交按钮的时候,将会把表单数据提交给validate.PHP页面,validate.PHP页面用来判断用户输入的用户名和密码有没有都符合要求(这一步至关重要,也往往是sql漏洞所在)
代码如下:
<Meta http-equiv="content-type"content="text/html;charset=utf-8">
PHP
$conn=@MysqL_connect("localhost",'root','')or die("数据库连接失败!");;
MysqL_select_db("injection",$conn) or die("您要选择的数据库不存在");
$name=$_POST['username'];
$pwd=$_POST['password'];
$sql="select * from users where username='$name' andpassword='$pwd'";
$arr=MysqL_fetch_array($query);
if(is_array($arr)){
header("Location:manager.PHP");
}else{
}
?>
代码分析:如果,用户名和密码都匹配成功的话,将跳转到管理员操作界面(manager.php),不成功,则给出友好提示信息。
到这里,前期工作已经做好了,接下来将展开我们的重头戏:SQL注入
2) 构造SQL语句
填好正确的用户名(marcofly)和密码(test)后,点击提交,将会返回给我们“欢迎管理员”的界面。
因为根据我们提交的用户名和密码被合成到SQL查询语句当中之后是这样的:
比如:在用户名输入框中输入:' or 1=1#,密码随便输入,这时候的合成后的SQL查询语句为:
语义分析:“#”在MysqL中是注释符,这样井号后面的内容将被MysqL视为注释内容,这样就不会去执行了,换句话说,以下的两句sql语句等价:
等价于
没错,该sql语句的作用是检索users表中的所有字段
小技巧:如果不知道' or 1=1#中的单引号的作用,可以自己echo 下sql语句,就一目了然了。
看到了吧,一个经构造后的sql语句竟有如此可怕的破坏力,相信你看到这后,开始对sql注入有了一个理性的认识了吧~
没错,sql注入就是这么容易。但是,要根据实际情况构造灵活的sql语句却不是那么容易的。有了基础之后,自己再去慢慢摸索吧。
有没有想过,如果经由后台登录窗口提交的数据都被管理员过滤掉特殊字符之后呢?这样的话,我们的万能用户名' or 1=1#就无法使用了。但这并不是说我们就毫无对策,要知道用户和数据库打交道的途径不止这一条。