Vander
Команда форума
- 10.11.2019
- 495
- 1 158
Помимо прочих важных настроек отображения в Интернете, важным шагом является обеспечение правильной проверки ввода. На самом деле, стоит полностью отказаться от пользовательского ввода при работе с файлами системы, если это возможно. В качестве дополнительной меры можно также использовать whitelist, позволяющий свести к минимуму риск того, что злоумышленник воспользуется любыми ошибками в настройках доступа.
Также (в особенности, если администратор хочет выйти за привычные рамки его обязанностей) стоит провести достоверное тестирование вашего приложения на уязвимость directory traversal. Существуют специальные инструменты для подобных проверок DirBuster, ZAP и DotDotPwn, хотя все эти процедуры можно легко сделать вручную.
Наиболее эффективный способ предотвращения уязвимостей при обходе пути к файлу состоит в том, чтобы вообще не передавать вводимые пользователем данные в API файловой системы. Многие функции приложения, которые делают это, могут быть переписаны для обеспечения того же поведения более безопасным способом.Если считается неизбежным передавать предоставленные пользователем входные данные API-интерфейсам файловой системы, то для предотвращения атак следует использовать два уровня защиты:
- Приложение должно проверять вводимые пользователем данные перед их обработкой. В идеале проверка должна сравниваться с белым списком разрешенных значений. Если это невозможно ввиду требуемой функциональности, то необходимо убедиться, что ввод содержит разрешенный контент, например, только буквенно-цифровые символы.
- После проверки предоставленных входных данных приложение должно добавить входные данные в базовый каталог и использовать API файловой системы платформы для канонизации пути. Следует убедиться, что канонизированный путь начинается с ожидаемого базового каталога.
Ниже приведен пример простого Java-кода для проверки канонического пути файла на основе пользовательского ввода:
Код:
File file = new File(BASE_DIRECTORY, userInput);
if (file.getCanonicalPath().startsWith(BASE_DIRECTORY)) {
// process file
}
Пример PHP-кода содержащего уязвимость Directory Traversal:
Код:
<?php
$template = 'red.php';
if (isset($_COOKIE['TEMPLATE']))
$template = $_COOKIE['TEMPLATE'];
include ("/home/users/phpdemo/templates/" . $template);
?>
Код:
$basepath = '/foo/bar/baz/';
$realBase = realpath($basepath);
$userpath = $basepath . $_GET['path'];
$realUserPath = realpath($userpath);
if ($realUserPath === false || strpos($realUserPath, $realBase) !== 0) {
//Directory Traversal!
} else {
//Good path!
}
Incorrect Path Validation
Пример кода содержащего уязвимость:
Код:
Regex regex = new Regex(@"([a-zA-Z0-9\s_\\.\-:])+(.dat)"); Match match = regex.Match(location);
if (match.Success){}
Пример кода содержащего уязвимость:
Код:
location = location.Replace(@"..\", ""); //win
if(File.Exists(location))
Проверка абсолютного пути означает, что мы собираемся проверить от корня, является ли файл, к которому мы собираемся получить доступ, тем, чего мы ожидали. Другими словами, мы разделяем ресурсы путем канонизации пути, поэтому делаем его абсолютным, прежде чем использовать его в бизнес-логике приложения.
- Канонизация - это процесс без потерь приведения пользовательского ввода к его эквивалентной простейшей известной форме. В C # есть метод с именем «System.IO.Path.GetFullPath», который дает канонизированный путь, и мы просто проверяем, начинается ли он с авторизованного местоположения.
Код:
protected string readFile(string location){
Regex regex = new Regex(@"([a-zA-Z0-9\s_\\.\-:])+(.dat)$"); Match match = regex.Match(location);
if (match.Success){
if(File.Exists(location) && Path.GetFullPath(location).StartsWith(@"C:\Applications\Documents",StringComparison.OrdinalIgnoreCase))
{
using (StreamReader reader = new StreamReader(location))
{
return reader.ReadToEnd();
}
}
else
{
return "File not found";
}
}
else
{
return "File name not valid";
}
}
Поскольку безопасность - это не статическая ситуация и не конечная цель, а непрерывный процесс, приближающийся к исправлению Directory Traversal только одним методом, он может быть упрощенным и часто не решающим.
Поэтому абсолютно лучший способ - использовать ориентированный на безопасность менталитет, который включает в себя разные уровни процесса разработки, но если говорить с технической точки зрения:
- Validation
- Sanitization
- Canonicalization
Материал подготовлен специально для protey.net