0%

国赛初赛sql注入

1.前言

最近在疯狂恶补sql注入的知识,了解到国赛初赛有一道sql注入的题目,就去看了一下

2.分析过滤

1
2
3
4
5
6
7
<?php
function safe($a) {
$r = preg_replace('/[\s,()#;*~\-]/','',$a);
$r = preg_replace('/^.*(?=union|binary|regexp|rlike).*$/i','',$r);
return (string)$r;
}
?>

这是waf代码

  • 可以看到过滤了双括号,空格(\s),注释符号(/**/,#)
  • 过滤了union 就不能进行联合查询
  • 根据提示utf8mb4_bin是要进行大小写区分的

3.语句分析

1
0'||case'1'when`password`collate'utf8mb4_bin'like'{}%'then+9223372036854775807+1+''else'0'end||'
  • case

    如果按正常的语句,一般是用if(condition,1,0)进行判断,但是这里过滤了(),那么就不能正常使用了,同理也不能用时间盲注去进行判断了,因为使用函数都需要用括号。
    那么这里使用的是

    1
    2
    3
    4
    5
    case case_value
    when condition then statement
    when condition then statement
    else statement
    end
  • utf8mb4_bin

    主要用于编码,让mysql可以支持4位的utf8编码,让字符变为二进制,然后开始对比。
    一般配合collate进行使用,例如
    select * from users where username collate utf8mb4_bin='admin'
    就会将列名username下的值和字符admin转为utf8mb4_bin进行对比

  • 最后的重点就是 9223372036854775807

    在mysql中,默认数字会视为BIGINT类型,也就是-9223372036854775808-9223372036854775807
    如果9223372036854775807+1就会溢出,然后报错。
    但是如果是9223372036854775808,他会默认把这个数字转换成unsigned bigint类型
    如下图


    那么如果直接设置9223372036854775808,他是不会报错的,因为会把他转化为unsigned bigint类型
    所以需要9223372036854775807+1,这样就超过bigint类型的最大范围
    当然也可以超过unsigned bigint,比如18446744073709551615+1,当然还有很多其它类型double类型之类的,都可以去溢出,原理相同,这种方法不会在语句中出现括号

4.参考链接