PHP正则表达式漏洞赌注 [英] PHP regex vulnerability bet

查看:27
本文介绍了PHP正则表达式漏洞赌注的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

今天的一位同事和我打赌,他知道一种提供特殊格式字符串的方法,该字符串可以通过以下正则表达式检查,并且仍然提供扩展名为 .php 的文件名>.jsp.asp:

A coworker today made a bet with me that he knows of a way to supply a specially formatted string that could pass the following regex check and still supply a file name with extension .php or .jsp or .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.";
}

我很努力地尝试自己并在网上搜索,但我无法找到可以使这种事情成为可能的缺陷.我可以忽略什么吗?鉴于处理了空字节"漏洞,这里还有什么问题?

As hard as I tried myself and searched the net, I was unable to find a flaw that would make such thing possible. Could I be overlooking something? Given that "null byte" vulnerability is dealt with, what else might be the issue here?

注意:我绝不暗示此代码是检查文件扩展名的完整方法,preg_match() 函数可能存在缺陷,或者文件内容可能是不同的格式,我只是根据正则表达式语法本身提出问题.

Note: In no way am I implying that this code is a full-proof method of checking the file extension, there might be a flaw in preg_match() function or the file contents could be of different format, I just ask the question in terms of regex syntax itself.

编辑 - 实际代码:

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

PHP version: 5.3.29

结语

原来漏洞"只出现在 Windows 上.尽管如此,它完全按照我的同事告诉我的去做 - 通过了正则表达式检查并使用可执行扩展名保存了文件.以下是在 WampServer 2.2PHP 5.3.13 上测试的:

Turned out the 'vulnerability' only presents itself on Windows. Nevertheless, it did exactly what my coworker told me it would - passed the regex check and saved the file with executable extension. Following was tested on WampServer 2.2 with PHP 5.3.13:

将以下字符串传递给 test.php:.jpg 上面的正则表达式检查(注意所需扩展名末尾的:"冒号符号)将验证它,函数 copy() 似乎省略了冒号符号之后的所有内容,包括符号本身.同样,这仅适用于 Windows.在 linux 上,文件将与传递给函数的名称完全相同.

Passing the following string to the regex check above test.php:.jpg (note the ":" colon symbol at the end of desired extension) will validate it and the function copy() seems to omit everything after the colon symbol including the symbol itself. Again, this is only true for windows. On linux the file will be written exactly with the same name as passed to the function.

推荐答案

没有一个步骤或完整的直接方法来利用您的代码,但这里有一些想法.

There is not a single step or a full direct way to exploit your code but here are some thoughts.

在此示例中,您将其传递给 copy() 但您已经提到您已经使用此方法来验证文件 ext 一段时间了,因此我假设您有其他可能使用过此方法的情况在不同的 PHP 版本上也有其他函数的过程.

You are passing it to copy() in this example but you have mentioned that you have been using this method to validate file ext awhile now so I assume you had other cases that may have used this procedure with other functions too on different PHP versions.

将此视为测试程序(利用包含、要求):

Consider this as a test procedure (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文件夹中包含它——当然,在这种情况下,你已经被攻击者拥有,但让我们也考虑一下这个选项.这不是上传过程的常见场景,但它是一个可以通过结合多种方法来利用的概念:

This will end up by printing "in!!!!" and executing 'test.php' even if it is uploaded it will include it from the tmp folder - of course that in this case you are already owned by the attacker but let's consider this options too. It's not a common scenario for an uploading procedure but it's a concept that can be exploited by combining several methods:

让我们继续 - 如果你执行:

Let's move on - If you execute:

//$_FILES['image']['name'] === "test.php#.jpg";
$name = $_FILES['image']['name'];
if (preg_match('/\.(jpeg|jpg|gif|png|bmp|jpe)$/i', $name) && preg_match('/\.(asp|jsp|php)$/i', $name) == false) {
    echo "in!!!!";
    copy($_FILES['image']['tmp_name'], "../uploads/".$name);
} else {
    echo "Invalid image file";
}

再次完全没问题.该文件被复制到uploads"文件夹中 - 您不能直接访问它(因为 Web 服务器会去掉 # 的右侧)但是您注入了该文件,攻击者可能会发现稍后调用它的方式或其他弱点.

Again perfectly fine. The file is copied into "uploads" folder - you can't access it directly (since the web server will strip down the right side of the #) but you injected the file and the attacker might find a way or another weak point to call it later.

此类执行场景的示例在共享和托管站点中很常见,其中文件由 PHP 脚本提供服务(在某些不安全的情况下)可能会通过包含错误类型的函数(例如 )来加载文件requireincludefile_get_contents 都存在漏洞并且可以执行文件.

An example for such execution scenario is common among sharing and hosting sites where the files are served by a PHP script which (in some unsafe cases) may load the file by including it with the wrong type of functions such as require, include, file_get_contents that are all vulnerable and can execute the file.

NULL 字节空字节攻击是 php < 的一大弱点.5.3 但在 5.4+ 版本的某些功能(包括所有与文件相关的功能以及扩展中的更多功能)中被回归重新引入.它被打了几次补丁,但它仍然存在并且许多旧版本仍在使用中.如果您使用的是较旧的 php 版本,那么您肯定会暴露:

NULL byte The null byte attacks were a big weakness in php < 5.3 but was reintroduced by a regression in versions 5.4+ in some functions including all the file related functions and many more in extensions. It was patched several times but it's still out there and alot of older versions are still in use. In case you are handling with an older php version you are definitely Exposed:

//$_FILES['image']['name'] === "test.php\0.jpg";
$name = $_FILES['image']['name'];
if (preg_match('/\.(jpeg|jpg|gif|png|bmp|jpe)$/i', $name) && preg_match('/\.(asp|jsp|php)$/i', $name) == false) {
    echo "in!!!!";
    copy($_FILES['image']['tmp_name'], "../uploads/".$name);
} else {
    echo "Invalid image file";
}

将打印in!!!!"并复制名为test.php"的文件.

Will print "in!!!!" and copy your file named "test.php".

php 修复的方法是通过检查字符串长度之前和之后将其传递给创建实际 char 数组的更深层次的 C 过程,如果字符串被空字节截断(这表示 C 中的字符串结束)) 长度将不匹配.阅读更多

The way php fixed that is by checking the string length before and after passing it to more deeper C procedure that creates the actual char array and by that if the string is truncated by the null byte (which indicates end of string in C) the length will not match. read more

奇怪的是,即使在打补丁的现代 PHP 版本中,它仍然存在:

Strangely enough even in patched and modern PHP releases it's still out there:

$input = "foo.php\0.gif";
include ($input); // Will load foo.php :)

我的结论:您验证文件扩展名的方法可以得到显着改进 - 您的代码允许名为 test.php#.jpg 的 PHP 文件通过,而它不应该通过.成功的攻击大多是通过组合多个漏洞甚至是次要漏洞来执行的 - 您应该将任何意外结果和行为视为一个.

My Conclusion: Your method of validating file extensions can be improved significantly - Your code allows a PHP file called test.php#.jpg to pass through while it shouldn't. Successful attacks are mostly executed by combining several vulnerabilities even minor ones - you should consider any unexpected outcome and behavior as one.

注意:关于文件名和图片的问题还有很多,因为它们后来多次包含在页面中,如果它们没有被正确过滤和安全包含,你就会暴露在更多的 XSS 内容中但那是题外话.

Note: there are many more concerns about file names and pictures cause they are many time included in pages later on and if they are not filtered correctly and included safely you expose yourself to many more XSS stuff but that's out of topic.

这篇关于PHP正则表达式漏洞赌注的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆