//连接数据库
$coon = mysql_connect('localhost','root','root') or die('Connect Error '.mysql_error());
mysql_select_db('sqlinjection',$coon) or die('Datebase Error '.mysql_error());
//构造查询语句
$query="SELECT * FROM user WHERE username='".$_GET["username"]."' AND password='".$_GET["password"]."'";
echo $query."<br/>";
//执行sql语句
$result= mysql_query($query);
//echo $result;
//判断返回数据的数目
$rowcount=mysql_num_rows($result);
//判断 如果数量大于1标示登录成功
//echo $rowcount;
if($rowcount!=0){
echo "OK";
}else{
echo "ERROR";
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>SQL injection test</title>
</head>
<body>
<form class="" action="test.php" method="GET">
<input type="test" name="username" value=""><br/>
<input type="password" name="password" value=""><br/>
<input type="submit" name="sub" value="Login">
</form>
</body>
</html>
首先我们先看一下测试代码,首先可以看到的是参数并没有进行相关的过滤,肯定会产生注入,但是今天我们讨论的是万能密码的问题。
关于万能密码我们应该都知道,常见的万能密码包括:
1:"or "a"="a
2: ')or('a'='a
3:or 1=1--
4:'or 1=1--
5:a'or' 1=1--
6:"or 1=1--
7:'or'a'='a
8:"or"="a'='a
9:'or''='
10:'or'='or'
11:1 or '1'='1'=1
12:1 or '1'='1' or 1=1
13: 'OR 1=1%00
通过我们的测试代码可以发现,开发在验证登录的时候,只是将用户输入作为查询条件进行查询,然后mysql_num_rows函数进行判断返回数据的数量,如果返回的数量大于1证明数据库中存在该用户,然后允许登录,正常情况下执行的SQL语句为:
[AppleScript] 纯文本查看 复制代码
| 1 |
|
但是当我们提交 【' or '1'='1】时,由于程序并没有对特殊字符进行过滤,将用户输入的直接带入查询,最后执行的SQL语句为:
[AppleScript] 纯文本查看 复制代码
| 1 |
|
这样SQL返回的值始终为1,就成功绕过了程序的验证。
关于修复:
[PHP] 纯文本查看 复制代码
| 1 2 3 4 5 6 7 8 9 |
|
以上代码对返回的数据与用户输入数据进行了比较验证,避免了万能密码的产生。
先看一段存在sql注入的代码:
[PHP] 纯文本查看 复制代码
| 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
|
参数没有进行任何过滤 而且查询后没有对数据进行验证,看到这我们应该想到万能密码(http://bbs.ichunqiu.com/thread-10851-1-1.html)
正常的查询如图
我们用万能密码尝试登录,我们可以看到红线之后的所有数据已经被注释掉,只有之前的语句被mysql所执行,同时后边的and 1=1返回永远为1,从而造成万能密码
下面看一下我们修改为预置参数查询后的代码:
[PHP] 纯文本查看 复制代码
| 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
|
我们正常登录 
我们看一下执行的语句(mysql日志)
我们再试一下万能密码 发现登录并没有成功
我们再看一下执行的语句
我们将将16进制转换一下
--------
我们将参数化查询与普通的查询对比一下
可以看到 参数化查询在真正执行之前会进行数据库预编译 放在缓存里面,当运行时动态地参数传递,即使参数里有敏感字符 数据库也会作为一个参数一个字段的属性值来处理而不会作为一个SQL指令。
1687

被折叠的 条评论
为什么被折叠?



