2013-04-20 3 views
1

Есть ли какие-либо риски безопасности, связанные с использованием $_SERVER['REQUEST_URI'] для включения файла? Можете ли вы передать ../../.. через запрос uri?PHP Включить на основе REQUEST_URI

Что я имею в виду что-то вроде этого:

<?php 
$path = $_SERVER['REQUEST_URI']; 
$path = preg_replace('~\\.html?$~', '.php', $path); 
include $path; 
?> 

Это должно заменить «.htm» или «.html» идентификаторы URI для «.php» пути и сделать их. Но я беспокоюсь о безопасности здесь.

+0

Как будет выглядеть запрошенный URI и как вы можете сопоставить запрошенный путь к файлу PHP? – Gumbo

+0

вы можете передать все, что хотите, в request_uri, включая html/javascript. это зависит от ВАС и ВАШЕГО кода, чтобы убедиться, что значение используется безопасно. Вы должны ** НИКОГДА НИКОГДА не позволять пользователю указывать путь, который будет использоваться в include/require, независимо от того, насколько хорошо вы считаете свою безопасность. поскольку он стоит прямо сейчас, они попадают в http: //yoursite.com/http: // malicioussite.com/remote_takeover.php', который выводит php-код в текстовом формате, а ваш сервер полностью и полностью разрушен. –

+0

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

ответ

3

$_SERVER['REQUEST_URI'] содержит запрошенный путь URI и строку запроса, как он появился в HTTP request line. Поэтому, когда запрашивается http://example.com/foo/bar?baz=quux, и сервер передает запрос в файл сценария /request_handler.php, $_SERVER['REQUEST_URI'] все равно будет /foo/bar?baz=quux. Я использовал mod_rewrite для отображения любого запроса request_handler.php следующим образом:

RewriteEngine on 
RewriteCond %{REQUEST_FILENAME} !-f 
RewriteRule^/request_handler.php 

Так за правильность, прежде чем использовать $_SERVER['REQUEST_URI'] в пути файловой системы, вам нужно будет избавиться от строки запроса. Вы можете использовать parse_url сделать так:

$_SERVER['REQUEST_URI_PATH'] = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); 

Но так как это значение поступает непосредственно из запроса HTTP линии без разрешения до пути, он все еще может содержать символьные сегменты пути, как ...

Однако обход трассы не требуется, поскольку запрошенный путь URI уже является абсолютной ссылкой на траекторию, и запрос http://example.com/etc/passwd должен привести к включению /etc/passwd.

Так что это на самом деле local file inclusion vulnerability.

Теперь, чтобы исправить это, требуется определенный корневой каталог с использованием method, который вы, chowey, представили, является хорошим улучшением. Но вы на самом деле нужно было бы добавить к ней префикс $basedir:

$path = realpath($basedir . $_SERVER['REQUEST_URI_PATH']); 
if ($path && strpos($path, $basedir) === 0) { 
    include $path; 
} 

Это решение обеспечивает несколько обещаний:

  • $path либо действительным, разрешен путь к существующему файлу, или false;
  • включение этого файла происходит только в том случае, если $basedir является префиксным путем $path.

Однако это может по-прежнему разрешать доступ к файлам, которые защищены каким-либо другим видом access control like the one provided by Apache’s mod_authz_host module.

0

Это на самом деле не ответить на вопрос ...

Обратите внимание, что вы можете обеспечить точки запроса Uri до фактического действительного FilePath в текущем рабочем каталоге. Вы можете использовать функцию realpath для нормализации пути.

Следующий код будет делать трюк:

<?php 
$basedir = getcwd(); 

$path = $_SERVER['REQUEST_URI']; 
$path = preg_replace('~\\.html?$~', '.php', $path); 
$path = realpath($path); 

if ($path && strpos($path, $basedir) === 0) { 
    include $path; 
} else { 
    return false; 
} 
?> 

Здесь я использовал strpos, чтобы убедиться, что в $path начинается с $basepath. Так как realpath удалит любые смешные дела ../../.., это должно безопасно держать вас в каталоге $basepath.

0

Действительно не доверяйте $ _SERVER ['REQUEST_URI'] перед проверкой базового маршрута.

И не создавайте фильтр, который удаляет ../ из пути, нападающие могут создать новый способ впрыска, если они поймут процессы фильтрации.

0

У меня был тот же вопрос, и решил сделать следующий основываясь на себя ответ илистого в:

$_SERVER['REQUEST_URI_PATH'] = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); 

$path = realpath(FOLDER_ROOT . $_SERVER['REQUEST_URI_PATH']); 

$directory_white_list_array = array('/safe_folder1', '/safe_folder1/safe_folder2'); 

if ($path && strpos($path, FOLDER_ROOT) === 0 && (in_array(dirname($path), $directory_white_list_array) && ('php' == pathinfo($path, PATHINFO_EXTENSION)))) { 
    include $path; 
}else{ 
    require_once FOLDER_ROOT."/miscellaneous_functions/navigation_error.php"; 
    navigation_error('1'); 
} 

Резюме: Добавлен каталог БелОГо и .php ограничение расширения.

Смежные вопросы