#php #security #code-injection
#php #Безопасность #внедрение кода
Вопрос:
Мне было интересно, был ли этот небольшой фрагмент подвержен уязвимости локального внедрения файла.
<?php
$lang = $_GET['lang'];
include '/some/dir/prefix_'.$lang.'whatever';
Я знаю, что все, что угодно, можно игнорировать, поместив » (нулевой байт) в запрос. Но если в каталоге /some/ dir / нет подкаталога, начинающегося с ‘prefix_’, может ли произойти эксплойт? Каким образом?
Заранее спасибо за ответ.
Ответ №1:
Вы имеете в виду что-то вроде этого?
$lang .= 'en/../../../../../etc/passwd' . 0x00;
Вы можете избежать этого с помощью
$path = '/some/dir/prefix_'.$_GET['path'].'whatever';
$path = realpath($path);
if (($path !== false) amp;amp; (strncmp('/dir/some/prefix_', $path, 17) === 0)) {
// $path is fine
}
Это проверяет, существует ли путь и действительно ли он находится в дереве каталогов, что вы разрешаете ему быть. Этого должно быть достаточно.
Комментарии:
1. Да, я имею в виду что-то вроде этого. Но не так. Каталог /some/dir/prefix_xy / не существует. Как файловая система может преобразовать /some/dir/prefix_xy / ../ в /some / dir /?
2. Это был пример. Может быть, можно использовать
en
вместоxy
(я изменил это в своем ответе). Теперьprefix_en
существует и..
снова работает нормально. В любом случае, ему нельзя доверять 😉3. Я цитирую себя: «в каталоге /some/ dir / нет подкаталога, начинающегося с ‘prefix_'». Итак, нет каталога /some /dir/prefix_en/. «Что угодно» указывает на файл.
4. Также проверка может быть неверной. realpath(‘/var/somehing’) может возвращать ‘/mnt/somethingelse/’.
Ответ №2:
Использование пользовательского ввода непосредственно в вашем коде всегда опасно.
Было бы лучше заставить его проверять, находится ли значение в массиве приемлемых значений.
Комментарии:
1. Я знаю, это не дает ответа на мой вопрос, даже отдаленно.
2. этот ответ должен быть принят. Если вы не знаете, как использовать эксплойт, это не значит, что эксплойт непригоден. Правило простое: не доверяйте вводимым пользователем данным. Без каких-либо исключений.
3. Я знаю. Я не использую этот код, я пытаюсь изучить и понять. Мне любопытно. Это не тот ответ, который я ожидал.
4. То, что это был не тот ответ, которого вы не ожидали, не делает его плохим или неправильным. Хотя этот пост не отвечает на поставленный вами вопрос, в нем содержатся хорошие рекомендации по проверке входных данных.
Ответ №3:
Ну, вы можете внести его в белый список, что-то вроде
$possible_languages = array('en','fr','pt'); #preferably not hardcoded
$lang = $_GET['lang']
if( in_array($lang, $possible_languages) ){
# do your thing
}
else {
#error out
}
В принципе… никогда не доверяйте пользовательскому вводу.
Комментарии:
1. Тот же комментарий, что и выше (для gnur).