SQLI Lab: 第一章第一课

这个系列会从头详细整理一些关于sql注入的东西。主要以sqli lab为实验。

首先开始第一个lesson,参考了博客(https://blog.csdn.net/u012763794/article/details/51207833):

在url后输入?id=1 可以得到正常输出,就是表中id为1的数据。为了理解方便,我改动了PHP源码使得网页会返回sql语句。

在1之后输入单引号,我们可以看到错误提示。

首先我们用union语句来遍历表的列数。Union语句可以将几个搜索结果合并在一起,但前提是几个结果的列数要一致。如果几个搜索结果的列数不一致就会报错。所以我们可以用union语句来遍历出表的列数:

127.0.0.1/sqli-labs7/Less-1/?id=1' union select 1

输入union语句,我们可以看到数据库报出了语法错误。

为了解决这个问题我们需要把语句之后的limit注释掉。如果直接在url中输入#,#会被转码成其他字符:

我们用%23代替#(#ascii码的hex是23):

select 1的时候可以看到数据库报错说列数不对,所以我们继续尝试。尝试到3的时候页面可以正常返回,这说明这个表有三列:

Limit的作用是返回搜索结果中的前几个。比如说Limit 0,1中,0是offset就是从第0个数开始算。1是返回的数量。所以Limit 0,1就是返回结果中的第一列。比如结果是{1,2,3,4},limit 0,1之后的结果就是1,limit 1,2的结果就是2,3,即跳过第0个数,之后的两个结果。

但是我们在上面这个语句中把limit给注释掉了,同样的语句在mysql中跑应该会得到这样的结果:

为什么网页只有第一行的结果呢?

查看PHP源码:

看到mysqli_fetch_array函数只被调用了一次,这个函数会取出一行数据库查询的结果。所以不管我们的sql语句怎么变,网页只会返回查询结果的第一行。

为了能看到我们输入语句的结果,我们需要让我们的结果作为查询结果的第一行返回。其中一个方法是将第一个查询的结果变成空,比如说输入一个不存在的id:

这样就可以显示之后的查询结果了。

由于我们只能输出两个查询的数据,所以我们必须要将多个查询的结果合并成一条返回。SQL语句中的concat函数。它可以将多个查询合并到一条返回

如果想要在每个结果中间加入分隔符,我们可以用concat_ws( concatenate with separator), 

用这个函数,我们就可以在我们的union语句中查询出数据库的信息,输入url:http://127.0.0.1/sqli-labs7/Less-1/?id=-1%27%20union%20select%201,2,concat_ws(char(32,58,32),user(),database(),version());%20%23

user()返回数据库用户的用户名;

database()返回当前使用的数据库名;

version()是当前数据库的版本

接下来我们要找到这个数据库中其他的表名。要得到这个,我们需要利用information_schema 这个数据库。这是一个系统数据库,里面有当前各个数据库、表、列、用户权限等的信息。转几个常用的表的功能:

SCHEMATA表:储存mysql所有数据库的基本信息,包括数据库名,编码类型路径等,show databases的结果取之此表。TABLES表:储存mysql中的表信息,(当然也有数据库名这一列,这样才能找到哪个数据库有哪些表嘛)包括这个表是基本表还是系统表,数据库的引擎是什么,表有多少行,创建时间,最后更新时间等。show tables from schemaname的结果取之此表COLUMNS表:提供了表中的列信息,(当然也有数据库名和表名称这两列)详细表述了某张表的所有列以及每个列的信息,包括该列是那个表中的第几列,列的数据类型,列的编码类型,列的权限,猎德注释等。是show columns from schemaname.tablename的结果取之此表。--- 作者:giantbranch 来源:CSDN 原文:https://blog.csdn.net/u012763794/article/details/51207833 

注意在information_schema中查询的时候where语句后面不能直接跟英文。要将英文前后加上单引号或者用16进制表示。

将查询语句放到sql注入中执行:

可以看到依然只能返回一个结果。我们可以用limit的offset来遍历所有表名:

但遍历超过范围时,将不会返回查询结果:

这样我们就可以得到所有四个表名。

接着,用colums表我们可以得到users表中的列名:

知道了列名,我们就可以遍历得到admin的密码:


用一个python脚本来执行结果:https://github.com/SevenWen/SQLiLab/blob/master/sqliLab1.py

你可能感兴趣的:(SQLI Lab: 第一章第一课)