安全小游戏:寻找漏洞

  • A+
所属分类:未分类

0×1 前言

YouTube上的一个视频,分享给大家。

这里存在一个Bug,你能找到Ta吗?

<?php

if (empty($_POST['hmac']) || empty($_POST['host'])) {
	header('HTTP/1.0 400 Bad Request');
	exit;
}

$secret = getenv("SECRET");

if (isset($_POST['nonce']))
	$secret = hash_hmac('sha256', $_POST['host'], $secret);

$hmac = hash_hmac('sha256', $_POST['host'], $secret);

if ($hmac !== $_POST['hmac']) {
	header('HTTP/1.0 403 Forbidden');
	exit;
}

echo exec("host ".$_POST['host']);
?>

0×2 初步分析

首先大致游览一下,这很像一个CTF题目。最后的目标要执行: 

echo exec("host ".$_POST['host']);

我们可以控制的输入有:

$_POST['hmac'] $_POST['host'] $_POST['nonce']

为了执行到目标需要跳过2个判断:

if (empty($_POST['hmac']) || empty($_POST['host'])) {
	header('HTTP/1.0 400 Bad Request');
	exit;
}
if ($hmac !== $_POST['hmac']) {
	header('HTTP/1.0 403 Forbidden');
	exit;
}

第一个判断只需要post参数hmac和host不为空就可以,第二个判断需要使得hmac和_POST['hmac']相等。

如果我们设置了nonce的值,那么中间会多执行一个步骤:

if (isset($_POST['nonce']))

$secret = hash_hmac(‘sha256′, $_POST['host'], $secret);

0×2 进一步分析

关键就在于第二个判断,能不能绕过他呢?hmac经过了sha256的哈希,而sha256是单向散列函数,我们不知道secret就不能倒推出散列值,如果穷举或采用字典查询这样并不符合题目的要求(穷举和字典攻击不是漏洞,任何系统都无法避免),这条路断了。

那么我们考虑一下PHP的类型自动转换:

在变量定义中不需要(不支持)明确的类型定义。变量类型是根据使用该变量的上下文所决定的。

安全小游戏:寻找漏洞为什么会相等呢?因为这里的上下文环境(context)自动将其转为了数字,而0e123(0*10^123) 和0e999(0*10^999)都是0,所以相等。

为什么会相等呢?因为这里的上下文环境(context)自动将其转为了数字,而0e123(0*10^123) 和0e999(0*10^999)都是0,所以相等。

安全小游戏:寻找漏洞在md5判断的时候就会出错,因为他们都是0e开头的。

在md5判断的时候就会出错,因为他们都是0e开头的。

这时我们看一下PHP的比较运算符:

例子 名称 结果
$a == $b  等于 TRUE,如果类型转换后 $a 等于 $b。 
$a === $b  全等 TRUE,如果 $a 等于 $b,并且它们的类型也相同。 
$a != $b  不等于 TRUE,如果类型转换后 $a 不等于 $b。 
$a !== $b  不全等 TRUE,如果 $a 不等于 $b,或者它们的类型不同。 

这里采用里不全等,那么之前我们提到的漏洞就不能使用了。而且如果if (isset($_POST['nonce']))这步被跳过那么后面的

$hmac = hash_hmac('sha256', $_POST['host'], $secret);

那么hmac就根本无法预测。所以这步至关重要,这里我们可以控制的变量只有host和nonce。

安全小游戏:寻找漏洞在传入参数的时候,PHP不仅可以让你决定传入的值是什么,还可以让你决定传入的类型。所以可以是nonce=123,也可以传入一个数组nonce[]=123。那么我们试试:

在传入参数的时候,PHP不仅可以让你决定传入的值是什么,还可以让你决定传入的类型。所以可以是nonce=123,也可以传入一个数组nonce[]=123。那么我们试试:

安全小游戏:寻找漏洞可以看到,返回了NULL,有的PHP版本同时还会提示一个warning,但返回的也是NULL。那么我们如果nonce传入一个数组,接下来的hmac我们也会知道:

可以看到,返回了NULL,有的PHP版本同时还会提示一个warning,但返回的也是NULL。那么我们如果nonce传入一个数组,接下来的hmac我们也会知道:

安全小游戏:寻找漏洞

我们在host参数传入;id,最后会执行host ;id就会打印出当前的计算机用户名。

0×3 exploit

最终我们的需要post的数据为:

 hmac=58dedd736c5af324a198c6c663e569df59691854d1f53d704bdbce40f1d139c1&host=;id&nonce[]=1

参考 

翻译来源YouTube

hmac 

php比较运算符 

*本文作者:晴雯晴雯晴雯,转载请注明来自FreeBuf.COM

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: