首页 > 解决方案 > Creating a FileStream that honours the "Append Data" NTFS privilege

问题描述

Consider an NTFS folder that has the explicit permissions Create Files / Write Data applied onto This Folder Only, and Create Folders / Append Data applied onto Files Only (and Read Attributes, because I understand that to be necessary).

> 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)

In theory, this should allow a user to create a file if it doesn't exist, and append to a file if it does exist, but not otherwise overwrite or truncate the contents of the file, nor delete it.

Now, given that, how does one actually open that file for appending?

I've tried simple command-line/batch redirection:

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

...and 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

...and .NET (via 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.

...and another .NET approach (again via 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.

In all cases, with Sysinternals Procmon running, I can see that the underlying CreateFile is always made requesting Generic Write for its permissions.

If I understand correctly, Generic Write means Win32's FILE_GENERIC_WRITE, which is a bitflag combination of FILE_APPEND_DATA | FILE_WRITE_DATA (and others) which would require Create Files / Write Data on the file as well as the directory.

However, if I place Create Files / Write Data on the file, then files are no longer append-only -- they can't be deleted and re-written, but they can be truncated and rewritten -- which defeats the purpose.

So what mechanisms are available to me to open the file really, really for Append only?

标签: .netbatch-filewinapivbscriptntfs

解决方案


你真的应该只打开带有附加数据的文件。 FILE_WRITE_DATA 和 FILE_APPEND_DATA 之间的区别

echo和其他方法不能仅通过附加数据访问附加数据(根据您的测试,内部还有其他复杂的访问),但为什么不echo直接使用创建“附加”命令(如)CreateFile?访问权限可以通过CreateFile.

附加.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

推荐阅读