sqlilabs7
第29关
首先研究一下源代码
首先是这个
$_SERVER[‘QUERY_STRING’]
作用:获取?后面的值
https://www.cnblogs.com/mitang/p/3874291.html 学习链接
然后去查阅了一下资料,这关原来是有两个服务器在共同作用
一个是Apache另一个是Tomcat 所以我的理解是,tomcat先对接受的数据进行过滤处理然后再交由apache(PHP),但其实我们可以看出
在这个里面,也就是看看是否带数字,如果是的话就把这个数据传递给Apache,没有怎么进行过滤的感觉呀?
原来使我们理解错了,这个的意思是:从get的id里面匹配以整数结尾的数据,如果我们在这个id 中插入我们的注入语句,那么匹配就会返回false,因为不是以整数结尾,这个过滤很强啊,相当于一个waf那么我们该如何绕过呢?
HPP(HTTPParameterPollution)
利用这个在前面那张图中,我们得知tomcat是取第一个数据,apache是取第二个数据,并且apache才是处理我们数据并且输出的服务器,所以我们可以构造两个数据,让tomcat只取得第一个合法数据,而第二个危险语句就让apache处理,达到我们的注入效果。
接下来构建payload:
?id=1&?id=-2’union select 1,database(),3 –+
即可成功绕过
第三十二关
宽字符注入问题
还是先来分析一下源代码
在这个题目当中,我们可以发现 他对get的的id进行了过滤,这里一开始有个疑问,他这边是对$string 而在下面的时候是对get[$id] 但是其中也没有让$string=这个get的命令。后来发现 在函数中其实get的这个数据就直接等于这个$string了 然后这边过滤的有反斜杠和单引号
第一句是当中出现的
preg_quote()**定义和用法
preg_quote()需要参数 str 并向其中 每个正则表达式语法中的字符**前增加一个反斜杠
然后接下来的两个是为了避免你想加一个反斜杠把上一个反斜杠给注释掉而写进去的
那么我们再往下看 看到一个set names gbk:
可以再在建数据库的时候设置,也可以在创建表的时候设置,或只是对部分字段进行设置,而且在设置编码的时候,这些地方最好是一致的,这样能最大程度上避免数据记录出现乱码
在这个语句中的意思是 对$con1进行 set names gbk编码
然后gbk是两个字节作为一个汉字,而uft-8是三个字节作为一个汉字,例如%aa%5c就是一个汉字(前一个ascii码大于128才能到汉字的范围,两个字节才能形成文字)
那么我们如何实施注入呢,先把流程搞一遍:
输入数据->进行过滤->对数据进行gbk编码->代入查询->输出结果
接下来 攻击流程:
输入带有危险字符的数据->进行过滤添加了反斜杠->对数据进行gbk编码(输出的ascii码大于128的字符转码以后和前面的转码后的反斜杠形成文字,只剩下单引号)->代入查询(执行(危险的)sql语句)->输出结果
PS:iconv()进行编码转换的时候,也可能存在宽字符注入漏洞
我们使用ascii码大于128的有一个%aa和%df
构建payload:?id=1%a0’and 1=1 –+
?id=-1%aa’union select 1,database(),3 –+
为啥那边会变成乱码呢,因为windows系统不支持ascii大于128的显示
下一个payload:
?id=-1%a0’union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=’security’ –+
这个语句是不行的,因为单引号被过滤了,所以我们需要将security编码
正确语句是:
?id=-1%a0’union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=0x7365637572697479 –+
因为mysql支持十六进制的数值,所以我们这里直接将数据转为16进制即可(0x表示16进制)
3.宽字节
GB2312、GBK、GB18030、BIG5、Shift_JIS等这些都是常说的宽字节,实际上只有两字节。宽字节带来的安全问题主要是吃ASCII字符(一字节)的现象,即将两个ascii字符误认为是一个宽字节字符。
MYSQL的字符集转换过程
1.MySQL Server收到请求时将请求数据从character_set_client转换为character_set_connection;
2.进行内部操作前将请求数据从character_set_connection转换为内部操作字符集,其确定方法如下:
- 使用每个数据字段的CHARACTER SET设定值;
- 若上述值不存在,则使用对应数据表的DEFAULT CHARACTER SET设定值(MySQL扩展,非SQL标准);
- 若上述值不存在,则使用对应数据库的DEFAULT CHARACTER SET设定值;
- 若上述值不存在,则使用character_set_server设定值。
将操作结果从内部操作字符集转换为character_set_results。
重点:宽字节注入发生的位置就是PHP发送请求到MYSQL时字符集使用character_set_client设置值进行了一次编码。
PHP中编码为GBK,函数执行添加的是ASCII编码(添加的符号为“\”),MYSQL默认字符集是GBK等宽字节字符集。
一点小体会
1.只有存在转义函数以及gbk编码的时候 才会出现宽字节注入,为什么呢?其实想一下,只有在我们输入单引号,然后函数转义给我们添加了反斜杠,这个时候我们输入ascii大于128的字符能达到吃字符,让单引号逃逸的效果。
三十三关和上一关没多大区别,在看源码的过程中唯一的区别就在于三十三关使用的是addslashes进行转义
无多大区别
第三十四关
这是一个post请求方式,在URL上面直接输入和在框里输入是不太一样的
这里再来系统的了解一下一些编码的知识吧
https://www.cnblogs.com/fnlingnzb-learner/p/6163205.html
在这里我想在区分一下在啊url输入和在下面框里输入的区别:
在上面的url输入的时候,如果你输入的时候 如果你已经输入的是一个符合url编码的格式的时候,他就不会理你,直接原样发送数据,但是当你在下面的框框的输入的时候,%会在经过一次编码变成%25 所以如果我们在下面的框框也是采用同样的输入方式的时候就会出错,那么该如何解决呢?
法1:
我们依旧可以按照做33关的方式输入,只需要用burp suit抓包把多编码的那个25删除即可
方法2:
经过一番探索,终于弄明白了
一个字符代表几个字节在不同的编码下是不一样的
UTF-16编码:一个英文字母字符或一个汉字字符存储都需要2个字节(Unicode扩展区的一些汉字存储需要4个字节)。
UTF-8编码:一个英文字符等于一个字节,一个中文(含繁体)等于三个字节。中文标点占三个字节,英文标点占一个字节
Unicode编码:一个英文等于两个字节,一个中文(含繁体)等于两个字节。中文标点占两个字节,英文标点占两个字节。
url编码就是在uft-8编码的基础上,给编码的每个字节加上百分号
所以POST的请求中,数据的编码过程是这样变化的:当我们一开始输入的是汉字,那么会被先被uft-8编码,然后在被加上百分号就是url编码了
当然也存在uft-16的编码方式,在这里我们输入这个数据:
**’1雲'or 1=1 #’ ** 抓包
得到这个数据,我们可以知道这个汉字被转化为三个字节,,也就是uft-8编码。在传输到数据库里面,并且对单引号%27添加转义反斜杠,再被gbk编码,而这里我们这里我们知道,在gbk中两个字符就会被当成一个汉字,那么我们原本输入一个汉字,这个汉字被转化成三个字节,加上原本的单引号一共四个字节,当转义字符插入,就变成了五个字节,这个时候单引号依旧可以逃逸出。其实我觉得宽字节注入的核心在于:利用gbk编码的两个字符吃掉转义字符反斜杠,使得单引号逃逸出(前面好像说过了,但是现在更加明了哈哈哈哈哈)
方法3:
我们知道输入的数据会被编码为uft-8,然后被url编码,那么如果我们直接将其转化成uft-8,那么是不是也可以实现注入呢答案是不会,因为没有自动识别功能~
https://www.qqxiuzi.cn/bianma/Unicode-UTF.php
这是一个可以转码的网址
OK 接下来就是暴表 啥的 组合拳冲了
补充知识:
了解整个编码解码过程:
https://www.freebuf.com/column/165567.html
第35关
这关属实有点搞笑,转义却在id这里不加引号,直接构造payload就行了,然后后面需要security在转码一下就行
第36关
这一关依旧是需要利用get宽字节注入 不过这关使用的转义函数是mysqli_real_escape_string();
直接构造payload:?id=-1%a0’union select 1,database(),3 –+
下面就是组合拳了
第37关
和前面的post宽字节注入无多大区别,不过用得是mysqli_real_escape_string(),payload都没变
第38关
先研究一下源代码
mysqli_connect()函数
打开一个到 MySQL 服务器的新的连接。
语法:mysqli_connect(host,username,password,dbname,port,socket);
mysqli_select_db()
作用:用于更改连接的默认数据库。
mysqli_select_db(connection,dbname)
mysqli_multi_query()
mysqli_multi_query(connection,query);
mysql_store_result()函数
用于将mysqli_query()查询的结果集存储到变量中
mysqli_more_results();
mysqli_more_results(connection);
参数:connection:必需。规定要使用的mysql连接
功能,检查一个多查询是否有更多的结果。
也没看到有啥过滤的代码
然后看到id被单引号包裹,所以先试试常规操作吧
利用union拼接select即可获得数据
mysqli_multi_query()还是让人比较在意的,所以看看标题,原来这是让我们尝试堆叠注入的
堆叠注入原理:
字面意思就是多条语句一起执行。如何实现?我们都知道在mysql中,每一条语句结尾加分号(;)表示语句的结束,基于此,如果我们在执行完一条语句之后继续构造下一条语句,中间用分号表示前一条语句的结束,那么我们的语句的实现也就成为了可能。
和union的区别:union执行的语句是有限的,只能用来执行查询语句,而堆叠注入可以是任意的语句
局限性:由于是第二条语句,所以页面是不会回显的,所以我们在前端页面无法看到返回结果,所以,在读取查询数据时,我们建议使用union(联合)注入,同时在使用堆叠注入之前,我们大多数时候也是需要一些数据库相关信息的,例如表名,列名字,当然API或者数据库(Oracle数据库)引擎不支持的限制下,也可能限制不足
如果没有mysli_multi_query()的时候我们可以使用堆叠注入吗?
答案是不行,因为此时无法处理多条语句。(局限性之一)
构建payload:’;insert into users(id,username,password) values(5,’admmm’,’admmm’) –+
插入成功,那么delete等危险操作也是可以实现的,如果更改的是管理员的账户,那操作空间还蛮大的,
可是过于局限了。
第39关
数字型注入 引号都不用加,直接注入就行了
第40关
单引号加括号的闭合方式’) 既可以采取union闭合的方式,也可以用堆叠注入
但是错误不会回显,无法用报错注入
第41关
这个是数字型注入,和第三十九关差不多但是无法使用报错注入因为报错也不回显。
第42关
这关和之前的24关卡有点像 但是这关需要使用堆叠注入,并且在一开始登录的时候是没有对密码进行过滤的,所以我们可以添加一个我们的插入语句,因为在更改密码的时候 他依旧没有对用户名进行过滤,所以我们一开始在插入的时候就可以像之前一样,不对,其实是不一样的,因为我们知道前面我们是用#号注释掉后面,这样修改密码就是修改admin的了,就不存在报错,但是在这里,我们插入了语句,我们使用#就会把我们的插入语句后面给注释掉了,就导致报错无法正确插入数据:
payload:admin=adm;
password=1’;insert into users values(15,’admin’,’admin’) –
当然也可以进行update修改 delete删除等操作,前提是要先知道他的表叫users;
接下来知道45关都是一样的,就不说了
小结: