sql注入就是用户通过构造sql语句,完成sql一系列操作
准备素材如下:
这是test.html
<!DOCTYPE html> <html> <meta charset="utf-8" /> <head> <title>mysql攻防探索</title> </head> <body> <form method="POST" action="test.php"> <label>用户名:</label><input type="text" name="user"><br> <label>密码:</label><input type="text" name="password"><br> <input type="submit" value="提交"> </form> </body> </html>
开始探索:
首先我们要清楚sql语句的构成,可以用echo输出sql语句的组成
第一个要介绍的是应对一条sql语句查询账户和密码
素材:这是test.php
header("content-type:text/html;charset=utf-8"); $user=$_POST['user']; $password=$_POST['password']; $con=mysqli_connect("127.0.0.1","root","","test"); $sql="select * from user where username='$user' and password='$password'"; echo $sql."<br>"; $res=$con->query($sql); $a=mysqli_fetch_assoc($res); if($a){ echo "登陆成功"; }else{ echo "登陆失败"; }
素材:这是数据库user表的字段信息
(1)用注释#
php的注释用#表示,当我们只知道用户名为username时,就可以开始用#构造sql语句
这里最终执行的sql其实只有select * from user where username='username',因为后面的password都被注释了
(2)利用and优先级大于or
这里因为and的优先级是大于or的,所以执行了username='username' and password='test',这句话虽然为false,但是后面'1'='1'为真,所以总的来说为真
可能现在基本的情况是密码都经过md5()、sha1()等等,经过测试对密码进行md5加密时上面的第二种破解方式会失败,但是第一种破解方式还是可以的
应对密码进行了md5加密的方法
素材:这是数据库user表的字段信息
(1)猜测密码字段
利用注释#把真实的密码字段注释,然后自己不断的测试密码字段,常见的是pwd、password、或者跟表单的名称一样
这种方式的原理是password字段正确且不等于空为真,所以这个sql语句最终能成功,得出password就是密码字段
(2)猜测密码长度
预测长度大于40时返回失败,继续测试
预测长度大于30时返回成功了,说明这个密码长度在30到40之间
最后一直测试就可以测出长度为32位
(3)猜测密码
这里主要使用了两个函数mid(字符串,位置,长度)获取某个字符、ascii()把字符转成ascii值,比如'0'的ascii值为48,具有可以查表
然后就可以一直测试,先探索密码的第一位
尝试估计ascii值大于45,结果成功
尝试估计ascii值大于50,结果失败
然后按这种方式慢慢缩小范围,最终推出是第一位密码的ascii值是50,查表可得具体值为2,因为前面推测出了密码的长度,所以可以一直按这种方式推出32位具体密码了,最终成功推出21232f297a57a5a743894a0e4a801fc3,然后再网上用md5解密工具就能解出真正密码
第二个要介绍的是应对先查账号,再核对数据库对应的密码(如果是这种写法,上面的破解都不会成功)
素材:这是test.php
header("content-type:text/html;charset=utf-8"); $user=$_POST['user']; $password=md5($_POST['password']); $con=mysqli_connect("127.0.0.1","root","","test"); $sql="select * from user where username='$user'"; echo $sql."<br>"; $res=$con->query($sql); $a=mysqli_fetch_assoc($res); if($a['password']===$password){ echo "登陆成功"; }else{ echo "登陆失败"; }
素材:这是数据库user表的字段信息
这里的破解点是让if条件为真,首先让原来的select语句清除掉,然后可以使用union(查询的列数需要相等)合并自定义的select语句,最终让在用户名输入框里面自定义的密码等于在密码输入框填的密码一样
(1)猜测表的字段长度
这里主要使用order by,它不仅可以根据字段名排序,还可以根据字段的列数进行排序
3的时候没有报语法错误
但是4的时候就报错误了,说明该表有3个字段
之所以可以这样判断是因为order by的另一种使用方法,它可以按照字段的列排序,一旦超出了字段数就会报错
(2)使用union清除原来的sql,拼上自定义的sql
这里随机选个字符串abc进行md5加密,得到900150983cd24fb0d6963f7d28e17f72,因为不清楚密码是在第几个字段,只知道共有3个字段,所以把这三个字段的值都填上这个加密都的密码,然后在密码输入框直接写abc
这里在test.php里面另外打印了$a的值,可以看出这三个字段的值都是通过自定义sql语句生成的,所以最终会使得if条件判断为真,最终登陆成功