在mysql和sqlist中,在进行字符串比较的时候,会在较短的字符串后面添加上空格,使两者长度一样,再进行比较,比如如下两个查询语句:(已经知道数据库中存在id="sxdxwb"字段)
1.select*from admin where id="sxdxwb"
2.select*from admin where id="sxdxwb "(注意b后面存在一个空格)
那么在查询的时候,这两个句子的效果是一样的,因为我在查询的时候,会进行比较,数据据库中本来存在的是id="sxdxwb",我现在输入id="sxdxwb ",那么比较就产生了,由于数据库中的字符串较短,所以会在后面加上一个空格,这样就就和我们的查询输入一样了,就会返回结果.
接下来举一个例子:比如我想要入侵一个用户名为sxdxwb的账号,但是我又不知道他的密码,我可以怎么做呢,我可以先创建一个名叫sxdxwb ;的账号(此处空格尽量多,最好超过截断最大长度,在最后一位输入;是为了防止检测出同名),接下来,数据库在创建信息的时候会进行截断,(为什么会进行截断?因为在创建一个字段时,需要对最大长度进行限制)这样我们的用户名就变成了sxdxwb ,和我们要进行入侵的用户除了在后面多了一大串空格,其他没有什么不同假设此时php检测的代码如下:
<?php
$username = mysql_real_escape_string($_GET['username']);
$password = mysql_real_escape_string($_GET['password']);
$query = "select username from users
where username='$username'
and password='$password' ";
$res = mysql_query($query, $database);
if($res) {
if(mysql_num_rows($res) > 0){
return $username;
}
}
return Null;
?>
这时我们使用刚才我们所注册的sxdxwb(入侵用户),及我们刚才创建的sxdxwb 密码登录,当然,数据库还是匹配到的是我们的账户,因为密码的缘故,那么,哪里会出现问题呢,注意最后return $username这个代码,返回用户名,这就值得推敲了,因为最后返回了用户名,这是目标的,后面如果不加以验证,继续以该用户名开展业务,这样就操作目标帐户,达到水平越权的目的了.
当然也需要满足一定的条件,从前面的叙述中,我们发现,我们的输入没有被限制,如果我们在创建是被设置了字数限制,没有导致数据库截断,那么也就不存在了.还有,登录SQL账号和密码必须一起验证,如果是验证流程是先根据用户名查找出对应的密码,然后再比对密码的话,那么也不能进行利用。因为当使用Dumb为用户名来查询密码的话,数据库此时就会返回两条记录,而一般取第一条则是目标用户的记录,那么你传输的密码肯定是和目标用户密码匹配不上的。验证成功后返回的必须是用户传入的用户名而不是从数据库取出来的。因为当我们以用户sxdxwb(入侵账号)和自己账号sxdxwb ,密码登陆时,其实数据库返回的是我们自己的用户信息,而我们的用户名其实是sxdxwb ,如果此后的业务逻辑以该用户名为准,那么就不能达到越权的目的了