Эксплойт с включением локального файла при включении языкового файла

У меня есть php-код для моего веб-сайта, и друг сказал мне, что мой код имеет уязвимость включения локальных файлов, потому что я использую метод «включить».

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

вот код ниже, чтобы быть более понятным:

<?php 

if(isSet($_GET['lang']))
$lang = $_GET['lang'];
else $lang='en';

include 'languages/'.$lang.'.php'; 
include("header.php");
?>

P.S. У меня только 2 языковых файла: английский = "en.php" и арабский = "ar.php"

Я был бы очень признателен, если бы кто-то мог помочь.


person Seven-up    schedule 19.05.2016    source источник
comment
Ошибка заключается в том, что если я введу xxx в поле lang вашей формы, вы попытаетесь включить несуществующий файл.   -  person RiggsFolly    schedule 19.05.2016


Ответы (2)


НИКОГДА не доверяйте пользовательскому вводу!

<?php 

if ( isset($_GET['lang']) && $_GET['lang'] == 'en') {
    $lang = 'en';
} else {
    $lang = 'ar';
}

include 'languages/'.$lang.'.php'; 
include("header.php");

?>

Или, готовясь к возможным дополнительным языкам, я бы сделал так:

<?php 

$lang = !empty($_GET['lang']) ? $_GET['lang'] : 'en';

switch($lang) {
    default:
    case 'en':
        include 'languages/en.php'; 
        break;
    case 'ar':
        include 'languages/ar.php'; 
        break;
}

include("header.php");

?>

Таким образом, вы можете легко добавить дополнительные языки позже, а также всегда следить за тем, чтобы был включен только необходимый файл.

person Peon    schedule 19.05.2016
comment
Большое спасибо Дайнису Аболсу за повтор. Второй код работал у меня, но что-то не так с первым кодом. - person Seven-up; 19.05.2016
comment
отсутствуют точки с запятой, так как я на самом деле не запускал скрипт: D - person Peon; 19.05.2016

Уязвимость заключается в том, что можно отправить любой относительный путь в $lang. Это особенно опасно, если пользователи могут загружать файлы и выяснять их реальный путь на сервере.

Пример:

  • Хакер может использовать некоторые функции загрузки файлов на вашем сайте для загрузки evil.php. Хакер может знать/обнаружить/догадаться, что он хранится в /var/www/uploads/evil.php, а ваше приложение работает в /var/www/html.
  • Обычно никто не может запустить этот файл, если /var/www/uploads недоступен через HTTP.
  • Но можно было бы открыть http://example.com/index.php?lang=../../uploads/evil и угадайте, что он будет включать languages/../../uploads/evil.php, который разрешится в /var/www/uploads/evil.php!

Это, конечно, также работает без загрузки файлов, если есть какие-либо другие файлы, которые можно использовать для эксплуатации чего-либо, получив к ним доступ и вызвав их, например, файлы в обычно защищенном паролем каталоге (например, phpMyAdmin).

И если вы теперь думаете, что "здесь довольно много предположений и "может" и "если", вам нужно быть очень удачливым, чтобы преуспеть в этом", тогда будьте осторожны, хотя есть некоторые очевидные откровенно открытые уязвимости, где вы сделать один URL-вызов, и вы можете, скажем, обогнать сервер или удалить базу данных, наиболее опасными являются те, которые требуют нескольких кусочков головоломки, чтобы заставить эксплойт работать, потому что они остаются незамеченными в течение длительного времени, и это может быть сложно чтобы понять, как сервер был фактически взломан, когда это произошло, и у вас, естественно, будет более опытный и, следовательно, более опасный (возможно, скрытный) хакер на вашем пороге. Если кто-то полон решимости найти дыру в безопасности (либо потому, что у него есть реальная цель атаковать ваш сайт или вас, либо потому, что ему просто нравится иметь плохих веб-мастеров, чтобы потешить свое эго), они будут продолжать искать и ломать голову над тем, что требуется для достижения цели. чего они хотят.


Есть несколько решений.

Как предложил u_mulder, если у вас есть только ar и en, просто проверьте, является ли это одним из них.

Если у вас больше языков, вы можете просто создать массив со списком допустимых значений и проверить, находится ли отправленный язык в этом массиве, например:

$languages = ['de', 'en', 'ar', 'jp', 'fr'];
if(in_array($_GET['lang'], $languages)) {
    $selectedLanguage = $_GET['lang'];
} else {
    $selectedLanguage = 'en'; // default
    // Note that you could also show an error "invalid language" instead
}

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

if(preg_match("/^[a-z]*$/", $_GET['lang'])) { ... }

Обратите внимание, что при таком подходе вы обязательно должны также проверить, существует ли указанный файл, в противном случае все еще можно было бы иметь сайт без языка, указав недопустимый язык (тем более, что include не выдает ошибку для несуществующих файлов, в отличие от require).

person CherryDT    schedule 19.05.2016