PHP正则表达式漏洞下注
一个同事今天与我打赌,他知道一种提供特殊格式的字符串的方法,可以通过以下正则表达式检查,并仍然提供扩展名为.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上呈现.然而,它确实是我的同事告诉我的,它将通过正则表达式检查,并以可执行扩展名保存文件.以下是使用PHP 5.3.13在WampServer 2.2上进行了测试: 将以下字符串传递到test.php上面的正则表达式检查:.jpg(注意在所需扩展名结尾处的“:”冒号符号)将验证它,并且函数copy()似乎省略了包含符号的冒号后的所有内容本身.
没有一个步骤或完全直接的方式来利用你的代码,但这里有一些想法.
你在这个例子中传递给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字节 //$_FILES['image']['name'] === "test.php .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 .gif"; include ($input); // Will load foo.php :) 我的结论: 注意:有更多的关于文件名和图片的问题,因为他们很多时间包括在页面以后,如果没有被正确过滤,并安全地包括你暴露了许多更多的XSS的东西,但这不在话题. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |