[极客大挑战 2019]HardSQL1
空格,等号,上次的or也是我们遇到过的过滤。显示的是特殊的文案,说明我们进入了另一个分支,那我们可以猜测服务器对我们多输入的 or 1=1;12.在学习了报错注入的基本用法以后我们按照之前的四步走,爆库名,用库名查表,再用库名查字段名,看看有没有可疑的,一般在这一步都能看类似于flag一样的关键字。它的核心目的,是利用数据库的报错机制,把原本看不见的数据库信息(比如当前数据库名)直接“炸”出来显示
1.进去以后我们先观察一下界面

2.这熟悉的界面。。。和我们之前做的两题可以说一模一样(实际上也是一个系列的题目。
那我先试试单独输入一个admin

3.这里显示的意思是要同时输入用户名和密码。
4.那我们试试在两个表单输入框里面输入1',1"看看这题存不存在sql注入

5.可以看到有报错回显,说明这题是存在sql注入的
这里解释一下为什么输入1'会有报错回显。
后端程序员在写登录验证代码时,通常会使用字符串拼接的方式来构建 SQL 语句。正常的 SQL 语句长这样:SELECT * FROM users WHERE username = '你输入的用户名' AND password = '你输入的密码';
当你输入一个单引号(比如 admin')时,后端会原封不动地把它拼接到语句里,变成了:SELECT * FROM users WHERE username = 'admin'' AND password = '...';
所以我们输入1'会导致后面多出来一个',让服务器解析不了,自然就会报错了。
6.那确认了有sql注入之后,我们试试万能密码能不能用

7.用不了。而且没报错。显示的是特殊的文案,说明我们进入了另一个分支,那我们可以猜测服务器对我们多输入的 or 1=1;里面的其中有些字符进行了过滤,导致返回的结果特殊。
8.那我们可以慢慢试试到底是那些字符被过滤。最常见的比方说。空格,等号,上次的or也是我们遇到过的过滤。具体测试我们就不演示了。我们直接说结果继续做下去,虽然我们这里跳过了,大家做的时候还是具体自己去试一下。那经过我们测试,发现 *、|、空格、等号会被过滤掉。
9.此路不通我们换一条路
先试试1'and#和1'union#看看有没有联合查询注入的可能


10.结果还是不行。到这里,就到我知识的上限了。这题要想做下去的话我只能去其他师傅的wp里面学习了。
11.在参考了其他师傅的wp以后,我知道了这题还有第三种的方法,也就是报错注入。这个东西属于新知识,我也不是很清楚,不知道的东西我们就问问AI
报错注入(Error-based Injection)攻击代码。它的核心目的,是利用数据库的报错机制,把原本看不见的数据库信息(比如当前数据库名)直接“炸”出来显示在网页的报错信息里。
updatexml()是报错注入的核心函数, 原本是 MySQL 用来更新 XML 文档的函数,它有三个参数:updatexml(目标文档, XPath路径, 新值)。
报错原理:数据库规定,第二个参数(XPath路径)必须是合法的 XML 路径格式(通常以 / 开头)。如果我们故意传入一个非法的字符,数据库无法识别,就会抛出语法错误(XPATH syntax error),并且把这段非法的内容原样显示在报错信息里。
12.在学习了报错注入的基本用法以后我们按照之前的四步走,爆库名,用库名查表,再用库名查字段名,看看有没有可疑的,一般在这一步都能看类似于flag一样的关键字。
13.那我们先查库名
1'or(updatexml(1,concat(0x7e,database(),0x7e),1))#
这里解释一下这段报错注入。1‘没啥好说的,就是用来闭合字段的,这个很熟悉了。
updatexml()前面解释过了。值得说的就是这里前面一个1代表目标文档,我们没信息,所以填个1占个位。后面那个1我们也不知道能填啥,所以也填个1。我们只知道我们需要得到数据库名。
这里
concat():这是一个拼接函数。它把 ~ + 数据库名 + ~ 串联在了一起。
0x7e:这是特殊符号波浪号 ~ 的十六进制表示。为什么要用它?因为 ~ 在 XML 路径中是非法字符,只要它一出现,就能完美触发报错。同时,它像一个醒目的“书签”,方便攻击者在长长的报错信息中快速定位到想要的数据。
特别注意的是URL和sql注入里面的#是不一样的。
使用hackbar的payload应该是
1'or(updatexml(1,concat(0x7e,database(),0x7e),1))%23
14.然后我们接着查表名
?username=1&password=1'or(updatexml(1,concat(0x7e,(select(group_concat(table_name))from(information_schema.tables)where(table_schema)like(database())),0x7e),1))%23
这串payload有点长,看起来可能会有点懵,我们一起拆开来看
结构啥的就不说了,我们说一下concat()里面的东西,这里面的东西是精华。
首先。GROUP_CONCAT(table_name)是一个是一个聚合函数,它能将这些分散的表名(table_name)全部拼接成一个长字符串,中间用逗号隔开。
然后。information_schema 是 MySQL 自带的一个“元数据数据库”,它像一个巨大的目录,记录了服务器上所有数据库、表、字段等基础信息。而 tables 是其中专门存储所有表名信息的表。
最后看WHERE后面,也就是筛选,
table_schema 代表数据库的名字。
DATABASE() 是一个内置函数,它会返回当前正在使用的数据库名称。
这句话的作用是进行过滤:只查找属于当前这个数据库的表,排除掉系统自带的其他数据库。
15.看懂了payload我们进网页输入看看

16.成功。那这个H4rDsq1就是表名了。
17.拿到了表名下一步不用我多说,我们开始查字段
username=1&password=1'or(updatexml(1,concat(0x7e,(select(group_concat(column_name))from(information_schema.columns)where(table_name)like('H4rDsq1')),0x7e),1))%23
18.这里大部分和查表一样。有不同的地方我们这里说一下。
information_schema.columns:这是 MySQL 的系统表,里面记录了所有数据库、所有表的字段(列)信息。
WHERE table_name LIKE 'H4rDsq1':这里进行了精准定位,只查找表名为 H4rDsq1 的记录。
GROUP_CONCAT(column_name):和你上次遇到的逻辑一样,利用聚合函数把这张表里的所有字段名(比如 id,username,password)拼成一个长字符串,方便一次性提取。
19.输入进去看一下

20.得到字段名,id,username,password。那我们按常规逻辑判断,flag肯定藏在password里面。我们直接全爆出来。
这里我可以用到从其他大佬那边学来的substring函数,
SUBSTRING(字符串, 起始位置, 截取长度)
updatexml 报错注入的极限通常是 32 个字符。
所以我们用substring函数可以完整的提取长数据
?username=admin&password=1'or(updatexml(1,concat(0x7e,(select(concat(id,',',username,',',substring(password,1,33)))from(H4rDsq1)),0x7e),1))%23

21,被过滤了。。。说明substring函数并不行了。这里没招了再看看其他师傅的wp。发现可以用left和right函数
?username=admin&password=1'or(updatexml(1,concat(0x7e,(select(left(password,33))from(H4rDsq1)),0x7e),1))%23

?username=admin&password=1'or(updatexml(1,concat(0x7e,(select(right(password,26))from(H4rDsq1)),0x7e),1))%23
21.拼接一下得到flag
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐

所有评论(0)