今天一位同事与我打赌,他知道一种提供特殊格式字符串的方法,该字符串可以通过以下正则表达式检查并仍然提供扩展名为 .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 () 似乎省略了冒号后的所有内容,包括符号本身。
同样,这仅适用于 Windows。在 Linux 上,文件将使用与传递给函数的名称完全相同的名称写入。
最佳答案
没有一个单一的步骤或完全直接的方法来利用您的代码,但这里有一些想法。
在这个例子中你将它传递给 copy() 但是你已经提到你已经使用这个方法来验证文件分机一段时间了所以我假设你有其他可能使用过这个的情况在不同的 PHP 版本上也包含其他函数的过程。
将此视为测试过程(利用 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) && preg_match('/\.(asp|jsp|php)$/i', $name) == false) {
echo "in!!!!";
copy($_FILES['image']['tmp_name'], "../uploads/".$name);
} else {
echo "Invalid image file";
}
再次完美。该文件被复制到“uploads”文件夹中 - 您无法直接访问它(因为 Web 服务器会去掉 # 的右侧)但是您注入(inject)了该文件,攻击者可能会找到一个以后调用它的方式或另一个弱点。
此类执行场景的示例在共享和托管站点中很常见,其中文件由 PHP 脚本提供服务,(在某些不安全的情况下)可能会通过将文件包含在错误类型的函数中来加载文件,例如 require, include, file_get_contents 都是易受攻击的,可以执行文件。
空字节 空字节攻击是 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', $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”的文件。
php 修复的方法是在将字符串传递给创建实际 char 数组的更深层次的 C 过程之前和之后检查字符串长度,如果字符串被空字节截断(这表示 C 中字符串的结尾) ) 长度将不匹配。 read more
奇怪的是,即使在已打补丁的现代 PHP 版本中,它仍然存在:
$input = "foo.php\0.gif";
include ($input); // Will load foo.php :)
我的结论:
您验证文件扩展名的方法可以得到显着改进 - 您的代码允许名为 test.php#.jpg 的 PHP 文件通过,而它不应该通过。成功的攻击大多是通过组合多个甚至是次要漏洞来执行的 - 您应该将任何意外结果和行为视为一个问题。
注意:关于文件名和图片的问题更多,因为它们会多次包含在以后的页面中,如果它们没有被正确过滤和安全包含,您就会面临更多的 XSS 问题但那是题外话。
关于PHP 正则表达式漏洞赌注,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33762339/
在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg
目录1.漏洞简介2、AJP13协议介绍Tomcat主要有两大功能:3.Tomcat远程文件包含漏洞分析4.漏洞复现 5、漏洞分析6.RCE实现的原理1.漏洞简介2020年2月20日,公开CNVD的漏洞公告中发现ApacheTomcat文件包含漏洞(CVE-2020-1938)。ApacheTomcat是Apache开源组织开发的用于处理HTTP服务的项目。ApacheTomcat服务器中被发现存在文件包含漏洞,攻击者可利用该漏洞读取或包含Tomcat上所有webapp目录下的任意文件。该漏洞是一个单独的文件包含漏洞,依赖于Tomcat的AJP(定向包协议)。AJP自身存在一定缺陷,导致存在可控
@raw_array[i]=~/[\W]/非常简单的正则表达式。当我用一些非拉丁字母(具体来说是俄语)尝试时,条件是错误的。我能用它做什么? 最佳答案 @raw_array[i]=~/[\p{L}]/使用西里尔字符进行测试。引用:http://www.regular-expressions.info/unicode.html#prop 关于ruby-正则表达式将非英文字母匹配为非单词字符,我们在StackOverflow上找到一个类似的问题: https://
我需要一个非常简单的字符串验证器来显示第一个符号与所需格式不对应的位置。我想使用正则表达式,但在这种情况下,我必须找到与表达式相对应的字符串停止的位置,但我找不到可以做到这一点的方法。(这一定是一种相当简单的方法……也许没有?)例如,如果我有正则表达式:/^Q+E+R+$/带字符串:"QQQQEEE2ER"期望的结果应该是7 最佳答案 一个想法:你可以做的是标记你的模式并用可选的嵌套捕获组编写它:^(Q+(E+(R+($)?)?)?)?然后你只需要计算你获得的捕获组的数量就可以知道正则表达式引擎在模式中停止的位置,你可以确定匹配结束
我想从then子句中访问case语句表达式,即food="cheese"casefoodwhen"dip"then"carrotsticks"when"cheese"then"#{expr}crackers"else"mayo"end在这种情况下,expr是食物的当前值(value)。在这种情况下,我知道,我可以简单地访问变量food,但是在某些情况下,该值可能无法再访问(array.shift等)。除了将expr移出到局部变量然后访问它之外,是否有直接访问caseexpr值的方法?罗亚附注我知道这个具体示例很简单,只是一个示例场景。 最佳答案
这是一个例子:s="abcd+subtext@example.com"s.match(/+[^@]*/)Result=>"+subtext"问题是,我不想在其中包含“+”。我希望结果是“潜台词”,没有+ 最佳答案 您可以在正则表达式中使用括号来创建匹配组:s="abcd+subtext@example.com"s=~/\+([^@]*)/&&$1=>"subtext" 关于ruby-正则表达式-排除一个字符,我们在StackOverflow上找到一个类似的问题:
我们有一个字符串:“”这个正则表达式://i如何从当前字符串中获取所有匹配项? 最佳答案 "".scan(//)参见scan在ruby-docs上 关于ruby-如何遍历Ruby中所有正则表达式匹配的字符串?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/6857852/
我正在尝试通过正则表达式拆分参数列表。这是一个带有我的参数列表的字符串:"a=b,c=3,d=[1,3,5,7],e,f=g"我想要的是:["a=b","c=3","d=[1,3,5,7]","e","f=g"]我试过先行,但Ruby不允许使用动态范围后行,所以这行不通:/(?如何让正则表达式忽略方括号中的所有内容? 最佳答案 也许这样的东西对你有用:str.scan(/(?:\[.*?\]|[^,])+/)编辑再三考虑。简单的非贪婪匹配器在某些嵌套括号的情况下会失败。 关于Ruby正则
我想找到给定字符串中的所有匹配项,包括重叠匹配项。我怎样才能实现它?#Example"a-b-c-d".???(/\w-\w/)#=>["a-b","b-c","c-d"]expected#Solutionwithoutoverlappedresults"a-b-c-d".scan(/\w-\w/)#=>["a-b","c-d"],but"b-c"ismissing 最佳答案 在积极的前瞻中使用捕获:"a-b-c-d".scan(/(?=(\w-\w))/).flatten#=>["a-b","b-c","c-d"]参见Rubyde
我想为名字验证编写一个正则表达式。正则表达式应包括所有字母(拉丁/法语/德语字符等)。但是我想从中排除数字并允许-。所以基本上它是\w(减)数(加)-。请帮忙。 最佳答案 ^[\p{L}-]+$\p{L}匹配anykindofletterfromanylanguage. 关于ruby-on-rails-rails中的正则表达式匹配[\w]和"-"但不匹配数字,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.c