Создание FileStream, который учитывает привилегию NTFS «Добавить данные» - PullRequest
0 голосов
/ 31 мая 2019

Рассмотрим папку NTFS с явными разрешениями Создание файлов / запись данных , примененные к Только для этой папки , и Создание папок / Добавление данных , применяемые к Только файлы (и атрибуты чтения, потому что я понимаю, что это необходимо).

> icacls x:\pathto\folder
x:\pathto\folder CONTOSO\Domain Users:(CI)(S,WD)
                 CONTOSO\Domain Users:(OI)(IO)(S,AD,REA,RA)
                 BUILTIN\Administrators:(I)(OI)(CI)(F)
                 NT AUTHORITY\SYSTEM:(I)(OI)(CI)(F)

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

Теперь, учитывая, как на самом деле открывается этот файл для добавления?

Я пробовал простое перенаправление командной строки / пакета:

> echo foo >> x:\pathto\folder\thefile.txt
> echo foo >> x:\pathto\folder\thefile.txt
Access denied.

... и VBScript

Dim fso : Set fso = CreateObject("Scripting.FileSystemObject")
Dim stream : Set stream = fso.OpenTextFile("x:\pathto\folder\thefile.txt", 8, True, 0)  ' 8-ForAppending
stream.WriteLine("foo")
-----
> cscript writefoo.vbs //nologo //e:vbs
> cscript writefoo.vbs //nologo //e:vbs
Microsoft VBScript Runtime Error(2, 14): Permission denied

...и .NET (через PowerShell)

> (1..2) | %{
>   Write-Host $_
>   $f = [IO.File]::AppendText('x:\pathto\folder\thefile.txt')
>   $f.WriteLine("foo")
>   $f.Dispose()
> }
1
2
Exception calling "AppendText" with "1" argument(s): Access to the path "x:\pathto\folder\thefile.txt" is denied.

... и другой подход .NET (снова через PowerShell)

> (1..2) | %{
>   Write-Host $_
>   $f = [IO.File]::Open('x:\pathto\folder\thefile.txt', [IO.FileMode]::Append, [IO.FileAccess]::Write, [IO.FileShare]::None)
>   $f = New-Object IO.StreamWriter -Arg $f
>   $f.WriteLine("foo")
>   $f.Dispose()
> }
1
2
Exception calling "Open" with "4" argument(s): Access to the path "x:\pathto\folder\thefile.txt" is denied.

Во всех случаях, когда запущен Sysinternals Procmon, яможно увидеть, что базовый CreateFile всегда выполняется с запросом Generic Write для его разрешений.

Если я правильно понимаю, Generic Write означает FILE_GENERIC_WRITE Win32, который представляет собой комбинацию битового флага FILE_APPEND_DATA | FILE_WRITE_DATA (и других), для которой потребуется Создание файлов / Запись данных на file , а также каталог .

Однако, если я помещу Create Files / Write Data в файл, файлы больше не добавляютсятолько они не могут быть удалены и переписаны, но они могут быть усечены и переписаны - что противоречит цели.

Итак, какие механизмыдействительно доступны для открытия файла, действительно только для добавления?

Ответы [ 2 ]

1 голос
/ 03 июня 2019

Вы действительно должны открывать файлы только с Добавить данные. Разница между FILE_WRITE_DATA и FILE_APPEND_DATA .

echo и другие методы не могут добавлять данные только с помощью функции «Добавить доступ к данным» (в соответствии с вашим тестом существуют другие сложные доступы внутри, но почему бы не создать команду «Добавить» напрямую (например, echo) напрямуюиспользуя CreateFile?Права доступа можно строго контролировать с помощью CreateFile.

Append.cpp:

#include <windows.h>
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
    if (argc != 3)
        return 0;
    //cout << argv[1] << "," << argv[2] << endl;
    HANDLE hFile = CreateFile(argv[2], FILE_APPEND_DATA, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    WriteFile(hFile,argv[1],strlen(argv[1]),0,0);
    CloseHandle(hFile);
}

Затем скопируйте Append.exe в папку, в которую вы хотите выполнить echo или «C».: \ Windows \ System32" .Используйте команду it like:

Append foo x:\pathto\folder\thefile.txt
0 голосов
/ 19 июня 2019

Разобрался, по крайней мере, для PowerShell / .NET.Объект .NET FileStream предлагает конструктор, который принимает параметр enum FileSystemRights, который позволяет явно ограничить базовый вызов CreateFile, чтобы он не требовал Generic Write.

> (1..3) | %{
>   Write-Host $_
>   $f = New-Object -TypeName 'IO.FileStream' `
>                   -ArgumentList $private:file,`
>                                 ([IO.FileMode]::Append),`
>                                 ([Security.AccessControl.FileSystemRights]::AppendData),`
>                                 ([IO.FileShare]::Read),`
>                                 4KB,`
>                                 ([IO.FileOptions]::None)
>   $f = New-Object -TypeName 'IO.StreamWriter' `
>                   -ArgumentList $f
>   $f.WriteLine("foo")
>   $f.Dispose()
> }
1
2
3

.знать для VBScript или Batch (за исключением предложение Дрейка о прокрутке собственного COM-типа или append.exe, который вызывает CreateFile напрямую через C ++ / Win32).

...