【漏洞练习-Day17】php中 md5(xxx,true)引发的漏洞
开始练习【红日团队】的PHP-Audit-Labs 代码审计 Day17
链接:https://github.com/hongriSec/PHP-Audit-Labs
感兴趣的同学可以去练习练习
预备知识:
内容题目均来自 PHP SECURITY CALENDAR 2017
Day 17 - Mistletoe代码如下:
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);
}
}$auth = new RealSecureLoginManager(
$_POST['user'],
$_POST['passwd']
);
if (!$auth->isValid()) {
exit;
}
漏洞解析 :
这题实际上和我们之前分析Day13 很相似,从
第17行-20行
代码中明显存在SQL语句拼接的形式,而
$pass
变量和$user
变量是在 第30行和31行
中通过 POST 方式
由用户进行控制。这里很明显存在SQL注入
漏洞,所以这题应该是考察SQL注入
漏洞。$queryBuilder = $this->em->createQueryBuilder()
->select("COUNT(p)")
->from("User", "u")
->where("password = '$pass' AND user = '$user'");
$query = $queryBuilder->getQuery();
这里为什么说这题和
Day13
很相似呢,我们继续往下看。程序代码第14行
调用 sanitizeInput
函数$user = $this->sanitizeInput($this->user);
针对用户输入的
$user
变量进行了处理,跟进一下sanitizeInput
函数,在第24行
找到这个函数。public function sanitizeInput($input) {
return addslashes($input);
}
这个函数的作用就是调用
addslashes 函数
针对输入数据进行处理。具体定义如下:
addslashes() 函数:
(PHP 4, PHP 5, PHP 7)
功能: addslashes() 函数返回在预定义的字符前添加反斜杠的字符串。
预定义字符是:定义:
- 单引号(’)
- 双引号(")
- 反斜杠(\)
- NULL
addslashes(string)
说明:
参数 | 描述 |
---|---|
string | 必需。规定要转义的字符串。 |
文章图片
结果:
Who’s Peter Griffin? This is not safe in a database query.回到题目:
Who’s Peter Griffin? This is safe in a database query.
所以按照这种情况下这个地方,似乎不存在注入点了,先别急,我们继续往下看,我们看到
第13行
代码$pass = md5($this->password, true);
针对用户输入
password
的值调用 md5
函数进行相关处理。我们先来了解一下这个 md5 函数md5 — 计算字符串的 MD5 散列值
功能: md5() 函数计算字符串的 MD5 散列。
定义:
string md5 ( string $str [, bool $raw_output = false ] )
说明:
参数 | 描述 |
---|---|
string | 必需。规定要计算的字符串。 |
raw_output | 可选。规定十六进制或二进制输出格式:TRUE - 原始 16 字符二进制格式;FALSE - 默认。32 字符十六进制数 |
13行代码
这里在
$raw_output
位置设置为了true
,根据描述如果可选的那我们先来看看效果raw_output
被设置为TRUE
,那么MD5 报文
摘要将以16字节
长度的原始二进制格式返回。
文章图片
现在整理一下这道题,我们知道我可以控制的点有两个变量,一个是
$user
,一个是 $pass
,$pass
经过了md5
的处理,但是返回字段不是标准的md5
值,$user
经过了 addslashes
函数的处理,无法引入特殊符号去闭合。这里做个假设,如果我们经过 $pass = md5($this->password, true);
处理之后的值逃逸出一个反斜杆,那么实际上带入到数据库的值就如下所示:select count(p) from user s where password='xxxxxx\' and user='xxx#'
如果这种情况发生,实际上也存在了
SQL注入
。我们尝试fuzz一下
,看看会不会存在某个值经过了md5(xxx, true)
处理之后,最后一位是反斜杠
。文章图片
我们针对
1-1000
进行一下fuzz
,发现 md5(128, true)
最后的结果带有反斜杠。因此这题最后的payload如下:user= OR 1=1#&passwd=128
带入到数据库查询的语句如下:
select count(p) from user s where password='v?a?n???l???q??\' and user=' OR 1=1#'
最后我们之前 Day13 也是通过逃逸反斜杆,转义单引号,从而逃逸出一个单引号闭合了之前的SQL语句,之前 Day13 的payload如下所示:
select count(p) from user where user = '1234567890123456789\' AND password = 'or 1=1#'
这里也是因为SQL语句中有两个地方可控,因此,我们也可以通过这个办法造成SQL注入的问题,所以我才会说这道题实际上和 Day13 很相似。
实例分析:
由于找不到由 md5(xxx,true) 函数引起的漏洞实例,所以本次实例分析选择实验吧的一道CTF题目,进行分析题目地址
漏洞POC 本站提供安全工具、程序(方法)可能带有攻击性,仅供安全研究与教学之用,风险自负! 漏洞分析: 首先打开该题目提示后台登陆
文章图片
猜测可能是个注入的题目,先看看有没有相关信息泄漏,右键源代码,发现泄漏的登陆逻辑代码。
$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 '密码错误!';
}
从上面代码中的
第4行
可以看到,当查询结果返回大于0
的时候,就会输出 flag
,我们前面分析过当 md5
函数的 $raw_output
设置会true
的时候, md5
函数返回前16字节
长度的原始二进制
,然后再将二进制
转换成字符串
,这种情况下可能会引入单引号等特殊字符。这里贴上两个别人构造好的字符串:
content: 129581926211651571912466741651878684928 (这是我们输入的字符串,用来进行md5编码)hex: 06da5430449f8f6f23dfc1276f722738(编码后得到的二进制字节码,用16进制的形式表示)raw: \x06\xdaT0D\x9f\x8fo#\xdf\xc1'or'8string: T0Do#'or'8 (这是通过二进制字节码在utf-8编码下显示出来的字符串)
content: ffifdyophex: 276f722736c95d99e921722cf9ed621craw: 'or'6\xc9]\x99\xe9!r,\xf9\xedb\x1cstring: 'or'6]!r,b
经过试验,两个都是成功的。把content的内容复制到输入框里就得到flag
修复建议:
建议在使用 md5 函数的时候,不要将 $raw_output 字段设置为true 。
结语
【【漏洞练习-Day17】php中 md5(xxx,true)引发的漏洞】再次感谢【红日团队】
推荐阅读
- 宽容谁
- 我要做大厨
- CVE-2020-16898|CVE-2020-16898 TCP/IP远程代码执行漏洞
- 增长黑客的海盗法则
- 画画吗()
- 2019-02-13——今天谈梦想()
- 远去的风筝
- 三十年后的广场舞大爷
- 叙述作文
- 20190302|20190302 复盘翻盘