PHP代码审计——Day 9-Rabbit
漏洞解析
class LanguageManager
{
public function loadLanguage()
{
$lang = $this->getBrowserLanguage(); // 获取浏览器语言
$sanitizedLang = $this->sanitizeLanguage($lang); // 去除可能的不安全字符
require_once("/lang/$sanitizedLang"); // 引入相应的语言文件
}
private function getBrowserLanguage()
{
$lang = $_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? 'en'; // 从 $_SERVER['HTTP_ACCEPT_LANGUAGE'] 中获取浏览器发送的语言信息,如果不存在则默认为英文('en')
return $lang;
}
private function sanitizeLanguage($language) // 将'../' 替换为空字符串
{
return str_replace('../', '', $language);
}
}
(new LanguageManager())->loadLanguage();
考察点:str_replace过滤不当导致的任意文件包含漏洞
程序过滤仅仅是将../
替换为空字符串,问题就是这个包含只是单次替换而不是循环替换,所以这种替换就很容易被绕过。只需要叠写一下就好了。构造成...//
, .././
是可以绕过过滤的。
str_replace
:(PHP 4, PHP 5, PHP 7)
- 功能 :子字符串替换
- 定义 : mixed str_replace ( mixed $search , mixed $replace , mixed $subject [, int &$count ] )
该函数返回一个字符串或者数组。如下:
- str_replace(字符串1,字符串2,字符串3):将字符串3中出现的所有字符串1换成字符串2。
- str_replace(数组1,字符串1,字符串2):将字符串2中出现的所有数组1中的值,换成字符串1。
- str_replace(数组1,数组2,字符串1):将字符串1中出现的所有数组1一一对应,替换成数组2的值,多余的替换成空字符串。
构造payload:Accept-Language: .//....//....//etc/passwd
参考文章
https://github.com/hongriSec/PHP-Audit-Labs/blob/master/Part1/Day9/files/README.md
https://lanvnal.com/2020/02/19/rips-php-security-calendar-2017-xue-xi-ji-lu/#toc-heading-2