首页 > 解决方案 > 正则表达式和编码攻击 - PHP 内部编码如何工作?

问题描述

我使用 UTF-8 正则表达式来获取Content-Type:标题行的部分,因为我习惯于将我的服务器配置为始终使用 UTF-8。

// example type, actually this will be negotiated from request `Accept:` header line.
$content_type = 'TeXt/HtMl';
preg_match('~^([\w-]+\*?)/([\w-]+\*?)$~ui', $content_type, $matches);

我考虑从基于子模式匹配构建的文件系统路径加载类。

'/../'有没有什么可行的方法通过编码攻击注入一些?内部编码一般如何工作?在 PHP 代码中处理数据时,我是否必须关心请求编码的字符集,或者转换是否自动可靠地工作?编码安全性还有什么要记住的?如何确保在未知系统上运行的已部署代码中进行编码?

编辑:如评论中所问,一些进一步的代码可能如下所示:

m1 = strtolower($matches[1]);
m2 = strtolower($matches[2]);
include_once "/path/to/project/content_handlers/{$m1}_{$m2}";

备注:我的问题是为了更笼统。让我们考虑一些场景: PHP 脚本以 UTF-8 编码。服务器的文件系统以字符集 A 编码。客户端操纵要以编码 B 发送的请求。是否存在接受的标头以 preg_* 函数无法识别某些'/../'(父目录)但文件系统?问题不限于示例中的特定正则表达式。如果不采取进一步的预防措施,攻击者能否包含文件系统中存在的任意文件?

备注 2:在提供的示例中,我不能依赖,http_negotiate_content_type因为不确定目标服务器上是否安装了pecl_http 。还有一个脚本化的 polyfill。再说一遍:这不是针对特定情况的问题。我想学习如何处理(甚至操纵)客户端编码。

备注3:这里讨论了一些类似的问题(SQL编码攻击):PDOprepared statements是否足以防止SQL注入?但是,我的问题是关于文件系统编码。会发生类似的事情吗?

标签: phpregexutf-8character-encoding

解决方案


我会大胆地说你的代码将有效地防止恶意子字符串。如果有人试图偷偷摸摸一系列字符,他们将被击倒preg_match()。您对锚点和角色类的使用没有任何回旋余地。模式很好,很严格。

只是几个注意事项:

  1. \w已经不区分大小写,因此i不需要模式修饰符。
  2. 您的捕获组存储在$matches[1]和中$matches[2]。全字符串匹配在$matches[0].

代码:

$content_type = 'TeXt/HtMl';
if (!preg_match('~^([\w-]+\*?)/([\w-]+\*?)$~u', $content_type, $matches)) {
    echo "invalid content type";
} else {
    var_export($matches);
}

输出:

array (
  0 => 'TeXt/HtMl',
  1 => 'TeXt',
  2 => 'HtMl',
)

推荐阅读