没有一个步骤或完全直接的方式来利用你的代码,但这里有一些想法.
你在这个例子中传递给copy(),但是你已经提到你已经使用这个方法验证文件ext了一段时间,所以我假设你有其他情况可能已经使用这个过程与其他功能在不同的PHP版本.
将其视为测试程序(Exploiting include,require):
$name = "test.PHP#.txt";
if (preg_match('/\.(xml|csv|txt)$/i',$name) && preg_match('/\.(asp|jsp|PHP)$/i',$name) == false) {
echo "in!!!!";
include $name;
} else {
echo "Invalid data file";
}
这将最终通过打印“in !!!!”并执行’test.PHP’,即使它是上传它将包括它从tmp文件夹 – 当然,在这种情况下,你已经拥有的攻击者,但我们也考虑这个选项.
上传过程不是常见的情况,但它是一个可以通过组合几种方法来利用的概念:
我们继续吧 – 如果你执行:
//$_FILES['image']['name'] === "test.PHP#.jpg";
$name = $_FILES['image']['name'];
if (preg_match('/\.(jpeg|jpg|gif|png|bmp|jpe)$/i',$name) == false) {
echo "in!!!!";
copy($_FILES['image']['tmp_name'],"../uploads/".$name);
} else {
echo "Invalid image file";
}
再次完美的该文件被复制到“uploads”文件夹 – 您无法直接访问它(因为Web服务器将剥离#的右侧),但是您注入该文件,并且攻击者可能会找到一种或另一个弱点来调用后来
这种执行场景的示例在共享和托管站点之间是常见的,其中文件由PHP脚本提供(在某些不安全的情况下)可以通过将文件包含在错误类型的函数中来加载文件,例如require,include,file_get_contents都是易受攻击的,可以执行该文件.
NULL字节
空字节攻击是PHP < 5.3但是在5.4版本中通过一些函数重新引入了一些函数,包括所有与文件相关的函数和更多的扩展.它被修补了好几次,但它仍然在那里,很多旧版本仍在使用中.如果您使用较老版本的PHP版本进行处理,则您绝对会被暴露:
//$_FILES['image']['name'] === "test.PHP\0.jpg";
$name = $_FILES['image']['name'];
if (preg_match('/\.(jpeg|jpg|gif|png|bmp|jpe)$/i',"../uploads/".$name);
} else {
echo "Invalid image file";
}
会打印“在!!!!”并复制名为“test.PHP”的文件.
通过检查字符串长度之前和之后,将其传递给更深入的C过程,创建实际的字符数组,以及如果该字符串被空字节(表示C中的字符串结尾)截断的长度将不匹配. read more
奇怪的是,即使在补丁和现代PHP版本,它仍然在那里:
$input = "foo.PHP\0.gif";
include ($input); // Will load foo.PHP :)
我的结论:
您的验证文件扩展名的方法可以显着改善 – 您的代码允许一个名为test.PHP#.jpg的PHP文件通过,而不应该.成功的攻击主要是通过组合几个脆弱性甚至是小的攻击来执行的 – 你应该将任何意想不到的结果和行为视为一个.
注意:有更多的关于文件名和图片的问题,因为他们很多时间包括在页面以后,如果没有被正确过滤,并安全地包括你暴露了许多更多的XSS的东西,但这不在话题.