Частично мне удалось сделать более-менее эффективный sandbox под виндой.
Главная проблема в том, что инициализация windivert требует админских прав.
Это никак не поменять, не пересобирая драйвер, который нужно потом подписывать.
В winobj ясно видны права на Device\WinDivert как Administrators:F, SYSTEM:F
Этот девайс будет просто не открыть , не имея такого доступа.
Можно, конечно, принудительно поставить на него DACL, пока есть админ права, но это открыло бы секурити дырку
Но можно ведь открыть, потом сбросить права. Да, можно, с некоторыми оговорками.
Нельзя сбрасывать, если заданы --nlm-filter или --wlan-filter. Потому что механика обслуживания этих фильтров предполагает останов перехвата в случае отсутствия сети и повторный его запуск при появлении.
Эти параметры используются нечасто, так что польза от сброса прав все равно есть.
Как он реализован технически.
Что вообще делает админа админом ? В linux это uid=0 и caps.
В windows это привилегии Se* и группа BUILTIN/Administrators в токене текущего процесса.
Такие инструменты, как process hacker или process explorer от Руссиновича (sysinternals) показывают во вкладках security что там в токене процесса.
Привилегии Se* можно сбросить без проблем. Нам не нужно право загружать драйвер или ребутать комп. Драйвера загружает менеджер служб, напрямую через недокументированное API - не к чему.
Привилегии сбрасываются в любом случае, вне зависимости от nlm/ssid фильтра. Оставляется только одна привилегия - SeChangeNotifyPrivilege. Она отвечает за траверс директорий, если на самой директории в ACL нет права Traverse для запрашивающего доступ. Эта привилегия стандартна и обычно включена по умолчанию для всех процессов.
Как сбросить админа ? Для этого надо заменить токен текущего процесса, убрав оттуда группу Administrators. Документированным API это сделать не получается. SetTokenInformation(TokenGroups) не дает поменять группы, возвращая ERROR_INVALID_PARAMETER. Вероятно это сделать можно через NtSetProcessInformation - недокументированной API из ntdll.dll. Но это жесткие хаки.
AdjustTokenGroups тоже не вариант, поскольку все группы получают флаг mandatory. Их нельзя задисаблить. Не получается и поставить флаг “deny only” - то, что выставляется при использовании UAC для процессов, если юзер имеет группу Administrators.
Можно только запустить дочерний процесс с другим токеном - CreateProcessAsUser. Но нам это не надо.
Есть вариант попроще. Можно поставить low mandatory label. Мандатность - фишка, придуманная еще с висты. Несколько костыльная штука. Если на обьекте не стоит в ACL mandatory label, то считается, что он имеет medium mandatory level. Если mandatory level процесса (наличие в token группах mandatory label SID) ниже mandatory label обьекта, то к нему запрещается доступ на чтение/запись/исполнение в зависимости от поставленных в mandatory ACE опций. Обычно это запрет на запись - icacls показывает как “NW” - No Write.
Получается, можно отсечь возможность записи на практически всю файловую систему.
И это хорошо, что LUA ничего не сможет записать, если не выставят на NTFS low mandatory на разрешенные директории, куда можно писать
Как можно посмотреть или изменить mandatory level ?
icacls dir
icacls dir /setintegritylevel low
Типичный пример, где это используется - %USERPROFILE%/AppData
cd "%USERPROFILE%\AppData"
icacls Local
BUILTIN\Administrators:(I)(OI)(CI)(F)
COMP\username:(I)(OI)(CI)(F)
Successfully processed 1 files; Failed processing 0 files
icacls LocalLow
BUILTIN\Administrators:(I)(OI)(CI)(F)
COMP\username:(I)(OI)(CI)(F)
Mandatory Label\Low Mandatory Level:(OI)(CI)(NW)
LocalLow - это appdata для процессов под текущим юзером, имеющих low mandatory level.
И некоторые процессы действительно сбрасывают свои права. Замечал, что это делают некоторые игры и пишут сейвы в LocalLow.
Броузеры вообще ставят Untrusted mandatory level для своих дочерних процессов. Часть механизма песочницы.
Так что если ваш LUA код хочет писать какие-то файлы, то придется для этого ставить low mandatory label, если, конечно, у вас нет nlm или ssid фильтра в параметрах winws2.
Или писать в LocalLow
На все файлы, создаваемые в C коде еще до сброса мандатности в low, буду принудительно ставить low mandatory. Это логи прежде всего и автолисты. Иначе будет их потом не записать