Можно ли использовать filesystem :: canonical для предотвращения внедрения пути к файлу для файловых путей, передаваемых в fstream - PullRequest
7 голосов
/ 10 апреля 2019

У меня есть общая папка pub с подпапками и файлами в ней. Пользователь дает мне теперь относительный путь к файлу, я выполняю некоторые сопоставления, и я читаю файл с fstream и возвращаю его пользователю.

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

Прежде чем изобретать велосипед, я искал в библиотеке файловой системы и я видел, что есть эта std :: filesystem :: canonical функция, и довольно много говорится о нормальной форме. У меня есть общий вопрос: можно ли использовать эту функцию и вариант std :: filesystem :: weakly_canonical для предотвращения этих типов уязвимостей? Так в принципе этого достаточно?

Кроме того, библиотека файловой системы моей системы все еще находится в экспериментальном режиме, а std::filesystem::weakly_canonical отсутствует. Но я не могу использовать canonical, потому что файлы должны существовать в canonical. В моем случае у меня есть определенные сопоставления, и файлы в этом смысле не существуют. Так что мне нужно было бы имитировать функцию weakly_canonical, но как?

Я видел связанный с этим вопрос переполнения стека в realpath для несуществующих путей , и ему было предложено повторять каноническое, пока существует путь, а затем добавить к нему несуществующую часть, но она снова уязвима для этого типа инъекций. Так я должен свернуть свой собственный weakly_canonical или я могу каким-то образом имитировать его, комбинируя некоторые std::experimental::filesystem функции?

1 Ответ

1 голос
/ 10 апреля 2019

Короткий ответ №.

Длинный ответ, это смоделировано после posix realpath

Я понимаю источник путаницы. Из реального пути

Функция realpath () должна извлекать из пути, на который указывает file_name, абсолютный путь, который разрешается к той же записи каталога, разрешение которой не включает '.', '..

Из cppref path вы также можете видеть, что двойная точка удалена. Однако путь по-прежнему указывает на тот же файл. Просто лишние элементы удаляются.

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

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

#include <iostream> 
#include <filesystem>
#include <string>
#include <regex>




int main() 
{ 

     std::string bad = "../bad/../other";
    std::filesystem::path p(bad);


    std::cout << std::filesystem::weakly_canonical(p) << std::endl;


    std::regex r(R"(\.\.)");
    p = std::regex_replace(bad, r, "\\.\\.");
    std::cout << std::filesystem::weakly_canonical(p) << std::endl;

}

выход

"/ TMP / прочее"

"/ TMP / 1554895428,8689194 /\.\./ плохой /\.\./ другой"

Пробный образец

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...