Уязвимости языка PHP

Hint: flag is not a frag: once you've got it, you can get one more...

Здесь будут мысли и наработки по уязвимостям интерпретатора PHP..

Обход open_basedir

Просмотрев все стандартные функции, работающие с файлами, я обнаружил некоторые недоработки.

Во-первых почти все функции по-разному реагируют на существующий и несуществующий файлы в корневой директории, то есть можно произвести листинг корневой директории. Видимо считается, что в ней ничего интересного быть не должно. Функции:

chgrp, chmod, chown, disk_free_space, disk_total_space, diskfreespace, file_exists, file_get_contents, file_put_contents, file, fileatime, filectime, filegroup, fileinode, filemtime, fileowner, fileperms, fopen, is_dir, is_executable, is_link, is_readable, is_writable, is_writeable, lchgrp, lstat, mkdir, parse_ini_file, readfile, readlink, realpath, rename, stat, symlink, tempnam, touch, unlink

Далее. BlackFan уже писал эксплойт для листинга директорий при помощи linkinfo() и realpath(). У меня вышло, что realpath не работает ни на 5.3.2, ни на 5.3.8, а вот linkinfo работает и там, и там.

Также стоит отметить функцию tmpfile(), которая почему-то плюёт на open_basedir и всегда позволяет создавать временные файлы во временной директории, даже если доступ в неё запрещён. Читая исходники, я обнаружил, что проверка на наличие ограничения проводится на каком-то уровне, но не стал углубляться, в чём же причина неудачи.

Листинг директории через glob() работал давным-давно, и его давно пофиксили. Но открыв список доступных протоколов PHP, я не мог обойти вниманием обёртку glob://. Выяснилось, что она-таки не видит установку open_basedir. Отсюда родился эксплойт.

Очередная функция/метод, позволяющая произвести листинг директории при помощи брутфорса -- это finfo.

$finfo = finfo_open(FILEINFO_MIME); $filename = "/var/www"; var_dump(finfo_file($finfo, $filename));

Функция говорит, что файл не существует или же ругается на open_basedir. На директории вообще не ругается.