Комментарии 22
А есть по итогу решение-то какое-то подобного вопроса? Сомневаюсь, что этот вопрошающий на SO - первый кто задался таким вопросом. Библиотека какая-то, которая уже прошла через эти грабли?
А вряд ли. Если программа может открывать файлы на запись - значит может и удалять информацию. А спрятать, что собственно она делает, можно под обфускацией..
apparmor и selinux в руки. От системного вызова действительно защититься нельзя. Но запесочить программу, чтобы она не лезла, куда не просят - возможно. Правда, задолбаешься профиль писать.
...в >90% "руководств по настройке %appname% в Linux" где-то в первых абзацах встречается строка про отключение selinux...
Всегда воспринимал подобный подход с негодованием - ведь если в приложении (особенно, какой-нибудь CMS, типа битрикса) есть уязвимость (а она есть почти всегда), то единственное, что предотвратит её катастрофическую эксплуатацию - это apparmor/selinux. Да, придётся или искать нормальное приложение, идущее с настроенным шаблоном разрешений, или потратить лишнее время на ковыряния с setroubleshoot, но зато в последствии не придётся вычищать с хостинга мириады объявлений о продаже виагры и прочих массажёров...
Решение - выполнять весь код, которому нет доверия в песочнице, где все запрещено с одним каналом связи наружу по которому ваше приложение будет с ним общаться.
Мы конечно просто скидываем наши проблемы на песочницу, но к ним доверия должно быть больше.
Создать в системе отдельного пользователя, выдать ему нужные права и запустить код уже под ним.
Правда, с этим подходом тоже есть подводные камни. Вот статья с разбором разных нюансов изоляции процессов в Windows
Такого кодоанализатора, на сколько я знаю, нет. Из коробки есть песочница AppDomain. Но в последних версиях фреймворка от нее осталось одно название. На поддержку AppDomain.PermissionSet, таких, напрмер, как FileIOPermission, подзабили. Еще есть Managed Add-In Framework для работы с плагинами. В новых версия фактически тоже не поддерживается.
Во многих частных случаях поставленный подобным образом вопрос можно свести к проблеме остановки, то есть к невычислимой задаче. Поэтому вообще не следует проверять, делает ли код определенные действия, а следует делать сами эти действия невозможными и возвращающими ошибку.
Вопрос, кстати, классический случай XY problem: вопрошающему надо не допустить, скажем, доступа к диску и сети, но спрашивает он, как определить наличие вызовов в коде, которые лезут на диск или в сеть (причем как-то близоруко. Как будто HttpClient и WebClient - это исключительное множество способов передать информацию по сети).
На самом деле такие вещи решаются белым списком, а не черным.
У тех же Space Engineers моды/скрипты вполне работают.
Это (создание своего транслитератора/транслятора/компилятора), кстати — единственный способ добиться максимальных гарантий безопасности исполнения произвольного стороннего кода (но не 100% — есть мастера передавать сообщения через троттлинг процессора :) )
нет, там полноценный C#(8-ой вроде), кроме нескольких исключений, например финализаторы и небезопасный код не разрешены, но это идет на уровне проверок, а не вырезано из языка.
Компиляция кода работает через Roslyn, никакой песочницы нет, но моды/скрипты распространяются в исходниках, а не в бинарниках.
Они там работают как раз в песочнице, дёргая предоставленный разработчиками безопасный API. Там даже не cовсем C#, а по сути очень-очень похожий на него скриптовый язык (уже порядком отставший от нововведений).
Нет, там очень даже настоящий C#, просто собираемый через Mono.
Можно даже подключить dll-ки из папки с игрой в проект в студии/райдере и пользоваться нормальным редактором, а потом без зазрения совести копировать код в игру — всё будет работать.
Рефлексия и IO, как я догадываюсь, реализована через mono.cecil
в общем - если уж у вас внутри есть eval, то лучше чтобы и строку для него, чтобы вы сами делали, и извне приходили только примитивы: строки и числа.
Это тоже не спасет на 100%, но хоть как-то ...
Примеры выглядят так словно проблема заключается в использовании Activator'а. Нельзя ли его в чёрный список внести?
Есть еще минимум 5 способов инициализировать объект.
Кроме Activator'а, там еще почти отсутствует защита от рефлексии. И вместо:
var type = Type.GetType("System.IO.StreamWriter");
using (var sw = (IDisposable)Activator.CreateInstance(type, new object[] { "<file>" }))
type.GetMethod("Write", new[] { typeof(string) }).Invoke(sw, new object[] { "WASTED" });
можно, например:
Type.GetType("System.IO.File")
.GetMethod("WriteAllText", new[] { typeof(string), typeof(string) })
.Invoke(null, new object[] { "<file>", "WASTED" });
И вполне возможно, что на этом список уязвимостей не исчерпывается.
Вот автор вопроса на System.dll
не ссылается, но если ему понадобятся LinkedList<T>
, ObservableCollection<T>
или Timer
оттуда, то он её добавит. И тогда можно будет использовать Process
из этой библиотеки:
using (var process = Process.Start(
new ProcessStartInfo(
"cmd.exe",
"/c echo WASTED> <file>")
{
CreateNoWindow = true,
UseShellExecute = false,
}))
process.WaitForExit();
ИМХО ловить на этапе исходного кода бессмысленно. Уже после компиляции, загрузки и биндинга можно пройтись по байткоду на предмет обращения к методам, и полям. Ну и как писали ораторы выше только вайтлист можно считать хоть как-то безопасным способом исполнять произвольный код.
История одного НЕ-ОТВЕТА на stackoverflow