Какой самый безопасный способ проверить, находится ли файл в базовом каталоге? - PullRequest
0 голосов
/ 24 марта 2020

Какой самый безопасный и безопасный способ в Go проверить на любой платформе, что данный путь к файлу лежит в базовом пути?

Пути изначально предоставляются в виде строк и используют "/" как разделители, но они предоставляются пользователем, и мне нужно предположить, что много вредоносных входных данных . Какой тип нормализации пути мне следует выполнить, чтобы убедиться, что, например, последовательности, подобные "..", были оценены, чтобы я мог безопасно проверить базовый путь? На какие исключения следует обратить внимание в различных файловых системах и платформах? Какие библиотеки Go должны быть безопасными в этом отношении?

Результаты будут переданы во внешние функции, такие как os.Create и sqlite3.Open, и любой отказ признать, что оставлен базовый путь, будет нарушение безопасности.

1 Ответ

2 голосов
/ 24 марта 2020

Я полагаю, что вы можете использовать filepath.Rel для этого (и проверить, возвращает ли оно значение, не начинающееся с ..).

Rel возвращает относительный путь, который лексически эквивалентен targpath, когда соединен с базовой платформой с помощью промежуточного разделителя. То есть Join (basepath, Rel (basepath, targpath)) эквивалентен самому targpath. В случае успеха возвращаемый путь всегда будет относительно basepath, даже если basepath и targpath не имеют общих элементов. Возвращается ошибка, если targpath не может быть сделан относительно basepath или если необходимо знать текущий рабочий каталог для его вычисления. Rel вызывает Очистить результат.

filepath.Rel также вызывает filepath.Clean на своих входных путях, разрешая любые . s и .. s.

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

  1. Замените несколько элементов Separator одним.
  2. Исключите каждый. элемент имени пути (текущий каталог).
  3. Удалите каждый внутренний элемент имени пути .. (родительский каталог) вместе с не .. элементом, который предшествует ему.
  4. Удалите элементы .. которые начинаются с корневого пути: то есть замените "/ .." на "/" в начале пути, предполагая, что разделитель равен '/'.

Вы также можете использовать filepath.Clean и проверьте префикс, когда это будет сделано. Вот несколько примеров выходных данных для filepath.Clean:

ps := []string{
    "/a/../b",
    "/a/b/./c/../../d",
    "/b",
}
for _, p := range ps {
    fmt.Println(p, filepath.Clean(p))
}

Отпечатки:

/a/../b /b
/a/b/./c/../../d /a/d
/b /b

При этом манипулирование путями не должно быть единственным механизмом безопасности, который вы развернуть . Если вы действительно беспокоитесь об эксплойтах, используйте глубокую защиту путем песочницы, создания виртуальной файловой системы / контейнеров и т. Д. c.

...