【发布时间】:2015-11-17 16:38:06
【问题描述】:
今天的一位同事和我打赌,他知道一种方法可以提供特殊格式的字符串,该字符串可以通过以下正则表达式检查,并且仍然提供扩展名为 .php 或 .jsp 或 .asp 的文件名:
if (preg_match('/\.(jpeg|jpg|gif|png|bmp|jpe)$/i', $var) && preg_match('/\.(asp|jsp|php)$/i', $var) == false)
{
echo "No way you have extension .php or .jsp or .asp after this check.";
}
尽管我努力尝试自己并在网上搜索,但我无法找到使这种事情成为可能的缺陷。我可以忽略一些东西吗?鉴于处理了“空字节”漏洞,这里还有什么问题?
注意:我绝不暗示此代码是检查文件扩展名的完整方法,preg_match() 函数可能存在缺陷或文件内容可能具有不同的格式,我只是问正则表达式语法本身的问题。
编辑 - 实际代码:
if (isset($_FILES["image"]) && $_FILES["image"]["name"] && preg_match('/\.(jpeg|jpg|gif|png|bmp|jpe)$/i', $_FILES["image"]["name"]) && preg_match('/\.(asp|jsp|php)$/i', $_FILES["image"]["name"]) == false) {
$time = time();
$imgname = $time . "_" . $_FILES["image"]["name"];
$dest = "../uploads/images/";
if (file_exists($dest) == false) {
mkdir($dest);
}
copy($_FILES['image']['tmp_name'], $dest . $imgname);
}else{
echo "Invalid image file";
}
PHP 版本:5.3.29
编辑:尾声
原来“漏洞”只出现在 Windows 上。尽管如此,它确实做到了我的同事告诉我的——通过了正则表达式检查并保存了带有可执行扩展名的文件。以下在WampServer 2.2 和PHP 5.3.13 上进行了测试:
将以下字符串传递给test.php:.jpg上方的正则表达式检查(注意所需扩展名末尾的“:”冒号)将对其进行验证,并且函数copy()似乎省略了冒号之后的所有内容,包括符号本身。
同样,这仅适用于 Windows。在 linux 上,该文件将使用与传递给函数的名称完全相同的名称写入。
【问题讨论】:
-
为什么 2 个单独的
preg_match? -
为了更好的说明,这不是实际的生产代码
-
为什么要问我们?如果您的同事真的知道方法,请让他说出来:P
-
@SeanBright 是的。关于问题本身的任何信息?
-
@revo 这是
D (PCRE_DOLLAR_ENDONLY)php.net/manual/en/reference.pcre.pattern.modifiers.php