MySQL注入部分知识讲解
Posted 佛大信息安全
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL注入部分知识讲解相关的知识,希望对你有一定的参考价值。
目录
1.万能密码登录
2.猜解注入获取密码
3.UNION注入绕过无密码字段查询
万能密码登陆
首先来一个登陆逻辑来看看:
<?php
header("Content-Type: text/html;charset= utf-8");
const USERNAME = "root";
const PASSWORD = "root";
const HOST = "localhost";
const DB = "test";
if($_POST){
$user = $_POST['user'];
$pwd = md5($_POST['pwd']);
$pdo = new PDO("mysql:host=".HOST.";dbname=".DB,USERNAME,PASSWORD);
$sql="select * from user where user='$user' and pwd='$pwd'";
echo $sql."<br/>"; //为了讲解方便,加入了sql语句的输出
$rs = $pdo -> query($sql);
$row = $rs -> fetch();
if($row){
echo "登陆成功";
}else{
echo "登录失败";
}
die();
}
?>
随便输入用户名和密码
![MySQL注入部分知识讲解](https://image.cha138.com/20210411/a5f65cd5fed54fa4a4c614919afe7624.jpg)
当然不负期望的,登录失败了咯
![MySQL注入部分知识讲解](https://image.cha138.com/20210411/24cf4aeb16d94073b67f40e6a552b40d.jpg)
输入的值拼接成如上sql语句。
这时候要想成功进行登录,就必要$row有数据,select语句where必须为真,那么拼接后的sql语句只需要满足where为真的条件即可,这里pwd字段进行了md5加密,无法构造,所以从user字段入手。
一般网站的密码不会明文存储,都会进行如md5的加密,加盐乱七八糟,不可逆的。
用户名输入 admin’ or ‘1’=’1 ,密码随便。
拼接成这样,因为and优先级大于or,所以where结果是true or (true and false)=true,登录成功。
上面是sql注入的原理入门。
猜解注入获取密码
第一步:先构造出登录成功的语句。(为了方便,使用发包方式)
![MySQL注入部分知识讲解](https://image.cha138.com/20210411/2ff08801894f43b191e2d671da3f0e52.jpg)
![MySQL注入部分知识讲解](https://image.cha138.com/20210411/ab3d2345111f4b5cab80d147edc43c0a.jpg)
跟在浏览器输入是一样的,不会发包看得懂就行。
因为#是mysql的注释,所以输入admin’#(假设数据库中有admin这个user),相当于where user=’admin’#,user='admin' 为true登录成功并且井号注释了后面的语句,所以密码可以随意。像刚刚第一个例子,你输入的语句,只要能够正确拼接就行,随便你写什么。
第二步:猜测密码字段
现在我是不知道表有什么字段,要获取密码就要把密码字段猜测出来,但是我知道登录的时候肯定用的是用户表。所以这里不需要猜测账号在什么表里。常见的密码字段有pwd,pass,password,以及与form表单中相同的字段。另外也可以使用字典爆破。
现在输入admin' and pass!=''#
![MySQL注入部分知识讲解](https://image.cha138.com/20210411/5e037788e78048ab99c09bad97fe2fe2.jpg)
![MySQL注入部分知识讲解](https://image.cha138.com/20210411/19e4fd7fe8994aea80a33528a2c0294e.jpg)
假如pass不是密码字段,不存在这个字段的话,一般就会报错或者本来是登录成功的变成登录失败,因为密码一般不为空,所以字段存在就为true,而user=’admin’也是true的,所以可以利用这个特性判断字段是否正确。
这里直接用pwd字段了。
![MySQL注入部分知识讲解](https://image.cha138.com/20210411/0d80a75d2cfe4695a38dc2edcd16d37b.jpg)
![MySQL注入部分知识讲解](https://image.cha138.com/20210411/f2ed8bbe9b1e4f42ac0d2fab0ac876df.jpg)
得出pwd是密码字段
第三步:获取密码长度
Mysql中有一个length函数,用来获取当前字段的值的长度。
![MySQL注入部分知识讲解](https://image.cha138.com/20210411/2f2adc7ffeb44785ae352015390a8d63.jpg)
![MySQL注入部分知识讲解](https://image.cha138.com/20210411/8ef81394908e4c63be64cc30ac513c31.jpg)
因为where是否为true取决于pwd字段length(pwd)>20是为true的,所以密码大于20位。
为了加快效率,用二分法就能获取密码的长度。(二分法就是数字游戏中的猜数字,1-100,猜50,小了50-100猜75这样)
![MySQL注入部分知识讲解](https://image.cha138.com/20210411/e0e67df317b1400ea1837e773a9f2b44.jpg)
![MySQL注入部分知识讲解](https://image.cha138.com/20210411/7f3453e10bd046ffb810a0849359ac4b.jpg)
失败,密码在21-40位之间。
![MySQL注入部分知识讲解](https://image.cha138.com/20210411/7b7b3329b08f4f2c94ccb1ed92a70760.jpg)
![MySQL注入部分知识讲解](https://image.cha138.com/20210411/91d8e7e0eee244d0a31e6653f7d366fa.jpg)
以此类推,得到密码位32位。
第四步:猜解密码
Mysql中mid函数MID(字符串,位置,长度)。ASCII函数获取一个字符的ascii值,常用的acsii的值有‘0’为48,‘A’为65,‘a’为97。
因此输入admin' and ascii(mid(pwd,1,1))>65#
![MySQL注入部分知识讲解](https://image.cha138.com/20210411/62485455cf9540498e33e2194e9ffa43.jpg)
![MySQL注入部分知识讲解](https://image.cha138.com/20210411/ab095e74e8694fdbabc94fc833965a97.jpg)
发现第一位密码为数字。
![MySQL注入部分知识讲解](https://image.cha138.com/20210411/5a96db3676044249b7563b6e2f3df4bb.jpg)
![MySQL注入部分知识讲解](https://image.cha138.com/20210411/3a9314e6d2964968ae94e52efa20be25.jpg)
小于52。
![MySQL注入部分知识讲解](https://image.cha138.com/20210411/07437ad319c54cb3ac3d1e4220d9dc14.jpg)
![MySQL注入部分知识讲解](https://image.cha138.com/20210411/d1f6f0ff2e19498b9d9c54484a0649a0.jpg)
不大于50。
![MySQL注入部分知识讲解](https://image.cha138.com/20210411/543784f1572543f6b22c72038078ab60.jpg)
![MySQL注入部分知识讲解](https://image.cha138.com/20210411/d10b1fbb93344dca99b52a066a0ac1e5.jpg)
最终确定是50,对应的字符为’2’,这就是第一位密码,
接下来31位也如此处理。
最后得到结果
21232f297a57a5a743894a0e4a801fc3。
虽然说MD5不可逆,无法解密,但是可以利用彩虹表,就是先把一些密码加密成md5值,然后找到对应的原文。
![MySQL注入部分知识讲解](https://image.cha138.com/20210411/c91c525d1fef448d8555420d35447885.jpg)
密码为admin。
![MySQL注入部分知识讲解](https://image.cha138.com/20210411/cb25f164230641e4beea3184564a5b02.jpg)
![MySQL注入部分知识讲解](https://image.cha138.com/20210411/7dd847d8011644d28e6a31ee3aaf9ca2.jpg)
登陆成功。
UNION注入绕过无密码字段查询
但是,有点经验的程序员一般用下面这种代码验证。
<?php
header("Content-Type: text/html;charset= utf-8");
const USERNAME = "root";
const PASSWORD = "root";
const HOST = "localhost";
const DB = "test";
if($_POST){
$user = $_POST['user'];
$pwd = md5($_POST['pwd']);
$pdo = new PDO("mysql:host=".HOST.";dbname=".DB,USERNAME,PASSWORD);
$sql="select * from user where user='$user' and pwd='$pwd'";
echo $sql."<br/>"; //为了讲解方便,加入了sql语句的输出
$rs = $pdo -> query($sql);
$row = $rs -> fetch();
if($row['pwd']===$pwd){
echo "登陆成功";
}else{
echo "登录失败";
}
die();
}
?>
这个与(1)的区别就是密码验证不是判断是否有数据返回,而是通过用户查询的这条记录,然后判断传入的密码是否跟数据库中的相同。
如果依旧输入admin'#
![MySQL注入部分知识讲解](https://image.cha138.com/20210411/133c73e1cdee4c6eaebc0038a9e30b6d.jpg)
![MySQL注入部分知识讲解](https://image.cha138.com/20210411/e7122aefe3dc4745a864fec6966825a3.jpg)
发现登陆失败,因为虽然构造sql语句成功,也返回了结果,但是这里的判断还是没有通过,因为密码不正确。
不同第一种只要有数据就判断通过,这种也验证的密码的正确性。那应该怎么才能登录成功?这里能想到,如果能控制返回结果不就行了么?
第一步:判断表中有多少个字段
使用order by可以进行判断表中有多少个字段,order by除了可以按字段名排序外,也可以按字段的列数来排序。如admin' order by 3#
![MySQL注入部分知识讲解](https://image.cha138.com/20210411/227b38b34a074d36bf9b5f74d2aff5db.jpg)
![MySQL注入部分知识讲解](https://image.cha138.com/20210411/b5d90a1c11454ed9b71302e39ce494e3.jpg)
这里表示按第3列排序
但是如果这里写4
![MySQL注入部分知识讲解](https://image.cha138.com/20210411/cc9d52047bbb40b8a6d434b5b387eb87.jpg)
![MySQL注入部分知识讲解](https://image.cha138.com/20210411/191e8840491d420f815262e8849d3e70.jpg)
就报错了。
证明用户表有3个字段。如果列数超过表中的字段数,mysql会报错,所以能判断字段数。
第二步:使用UNION查询
在mysql里union可以把两条语句查询的结果合并,但两个结果集字段的列数要相等。
union相关知识:
http://www.runoob.com/mysql/mysql-union-operation.html
这里我们先清除语句1的结果(使得语句1结果集为空,where条件为false),合并后的结果就只是语句2了
![MySQL注入部分知识讲解](https://image.cha138.com/20210411/4822072e3363484eaa277c44480589ad.jpg)
![MySQL注入部分知识讲解](https://image.cha138.com/20210411/a6d143dd350b437783f05c1a82b15db9.jpg)
select null,null,null。上面这条语句返回的就是最终结果
这里有一个问题就是,我不知道密码账号分别在第几个字段,所以这里可以将所有字段都填入密码。
首先将随便一个字符串md5加密
Md5(’123’)=’ 202cb962ac59075b964b07152d234b70’
最后用户名输入:
admin' and 0 union select '202cb962ac59075b964b07152d234b70','202cb962ac59075b964b07152d234b70','202cb962ac59075b964b07152d234b70'#
密码输入:123
![MySQL注入部分知识讲解](https://image.cha138.com/20210411/67857e597b704ddca689e0b729d0d25d.jpg)
![MySQL注入部分知识讲解](https://image.cha138.com/20210411/28dc33e037b84fc2a21d64b8a2ed6f2c.jpg)
为什么这样能登录成功?
这个语句的结果
判断的时候,输入的密码正好是123的md5值,登录成功。
END
文案:Zn风扇
排版:黄浚杰
校队:色鹿
以上是关于MySQL注入部分知识讲解的主要内容,如果未能解决你的问题,请参考以下文章
48-mysql-Navicat数据库查询题目讲解(多表操作)python操作MySQLsql注入问题pymysql模块增删改查数据操作
Mysql DBA 高级运维学习笔记-DQL语句之select知识讲解