解析用户提供的 INI 字符串和文件时的安全注意事项

PHP 提供 parse_ini_string 并重 parse_ini_file 用 PHP 内置的 PHP 解析器的功能,该解析器用于 PHP 自己的基于 INI 的配置文件。

除了解析文本之外,INI 解析器还支持继承解析文本时声明的系统环境值和 PHP 常量。自 PHP 8.3 起,它还支持环境变量的后备值语法

; 普通字符串字面量
my_config_name = normal

; 继承 SESSION_NAME 环境变量,如果不可用则为 ""
my_config_name = ${SESSION_NAME}

; 继承 SESSION_NAME 环境变量,若不存在则使用默认值 "MyDefaultValue"
my_config_name = ${SESSION_NAME:-MyDefaultValue}

; 使用环境变量进行字符串插值
my_config_name = "${MAIL_FROM_USER}@${MAIL_FROM_DOMAIN}"

; 继承 PHP_VERSION 常量的值
my_config_name = PHP_VERSION

虽然这些增强功能对于使用环境变量配置 PHP 以及使用 PHP 的内置 PHP 解析器对用户提供的 INI 值使用可用的 PHP 常量很有用,但这可能是一个安全漏洞,因为 PHP 可能会被欺骗来暴露环境变量和 PHP 常量,这些变量和 PHP 常量可能包含不应暴露的敏感数据。

例如,由用户或不完全受信任的远程服务器提供的配置文件可以利用此漏洞来欺骗解析服务器暴露自己的环境变量和 PHP 常量:

; config.ini
plugin.name = "Free plugin ${DATABASE_NAME} / ${DATABASE_PASSWORD}"
plugin.description = DATABASE_PASSWORD
$conig = parse_ini_file('config.ini');
array(2) {
["plugin.name"]=> string(33) "Free plugin MyDbName / MyPa$$word"
["plugin.description"]=> string(10) "MyPa$$word"
}

但是,PHP 提供了配置参数来禁用 PHP 的类型强制和 environment/constant 替换。parse_ini_fileparse_ini_string 函数的第三个参数接受位掩码,接受的标志之一是 INI_SCANNER_RAW,它禁用 PHP 对类型、环境变量和 PHP 常量的解析:

; config.ini
plugin.name = "Free plugin ${DATABASE_NAME} / ${DATABASE_PASSWORD}"
plugin.description = DATABASE_PASSWORD
$conig = parse_ini_file('config.ini', scanner_mode: INI_SCANNER_RAW);
// or
$conig = parse_ini_file('config.ini', false, INI_SCANNER_RAW);
array(2) {
["plugin.name"]=> string(51) "Free plugin ${DATABASE_NAME} / ${DATABASE_PASSWORD}"
["plugin.description"]=> string(17) "DATABASE_PASSWORD"
}

这里的安全预防措施是 PHP 不默认使用 INI_SCANNER_RAW 标志,这意味着所有没有明确传递 INI_SCANNER_RAW 标志的函数调用在解析用户提供的 INI 值时都将容易受到攻击。

你可能感兴趣的:(php配置文件)