How to Disable “Scan this dir for additional .ini files” in php.ini for Configuration Lockdown


2 views

When PHP starts up, it follows a specific order to load configuration files:

1. Compiled-in defaults
2. php.ini in PHP's installation directory
3. .user.ini files in the document root
4. Additional .ini files in scan_dir (if enabled)

The directive we're focusing on is scan_dir, which allows PHP to load configuration files from additional directories, potentially overriding your main php.ini settings.

To completely disable the scanning of additional .ini files, you have several options:

Method 1: Empty the scan_dir directive

; In your main php.ini file
; For PHP 5.x and 7.x
scandir = 

; For PHP 8.x
; This is now called php_scandir
php_scandir =

Method 2: Using PHP's -n flag

If you're running PHP via command line, you can use:

php -n your_script.php

The -n flag tells PHP to ignore all configuration files (including additional .ini files).

For complete configuration lockdown, consider these approaches:

1. Set immutable flags for critical directives:

disable_functions = "exec,passthru,shell_exec,system"
disable_functions = ${PHP:disable_functions} ; Makes it immutable

allow_url_fopen = Off
allow_url_fopen = ${PHP:allow_url_fopen} ; Makes it immutable

2. Change php.ini permissions:

chmod 444 /usr/local/php/lib/php.ini
chown root:root /usr/local/php/lib/php.ini

Create a test script to verify no additional .ini files are loaded:

<?php
// List all loaded configuration files
$inifiles = php_ini_scanned_files();
if (empty($inifiles)) {
    echo "No additional .ini files loaded - configuration locked down successfully!";
} else {
    echo "Warning: Additional .ini files loaded: " . $inifiles;
}
?>

For ultimate control, you can compile PHP with hardcoded settings:

./configure \
--with-config-file-scan-dir= \
--disable-all \
--enable-cli \
--your-other-options

This completely removes the scan directory functionality at compile time.

Remember that:

  • Disabling additional .ini files may break applications that rely on them
  • Consider using php-fpm pools with different configurations instead
  • Regularly audit your php.ini using tools like php -i or phpinfo()

PHP's configuration system is designed with flexibility in mind, allowing multiple .ini files to contribute to the final runtime configuration. The main php.ini file (typically at /usr/local/php/lib/php.ini) is loaded first, followed by any additional .ini files found in the scan directory.

While this flexibility is useful in development environments, it can pose security risks in production when:

  • Multiple sysadmins might accidentally override settings
  • Malicious users could potentially add their own .ini files
  • Configuration drift occurs between environments

To completely disable scanning for additional .ini files, add this to your main php.ini:


; Disable scanning for additional .ini files
scan_dir_for_ini = 0

Alternatively, you can set this at runtime in your Apache configuration or .htaccess:


<IfModule mod_php7.c>
  php_admin_value scan_dir_for_ini 0
</IfModule>

For critical security settings that should never be overridden, PHP provides several approaches:

1. Using php_admin_value in Apache:


<VirtualHost *:80>
  ServerName example.com
  php_admin_value open_basedir "/var/www/example.com:/tmp"
  php_admin_value disable_functions "exec,passthru,shell_exec,system"
</VirtualHost>

2. Compiling PHP with hardcoded defaults:

For maximum security, you can recompile PHP with certain settings hardcoded:


./configure --with-config-file-scan-dir=no \
            --disable-all \
            --enable-option-checking=fatal

After making changes, verify your configuration using:


<?php
// Check if additional ini scanning is disabled
if (ini_get('scan_dir_for_ini')) {
    echo "Warning: Additional .ini scanning is still enabled!";
} else {
    echo "Configuration locked successfully!";
}

// View the complete loaded configuration
phpinfo(INFO_CONFIGURATION);
?>