.net - 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?
解决方案
你真的应该只打开带有附加数据的文件。 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
推荐阅读
- kubernetes - 删除部署中的一个 pod 后服务无法正常工作
- node.js - 嵌入响应时,它仅从随机选择 Discord.js 中返回 1 个集合答案
- node.js - Nodejs - 如何将音频文件缓冲区数据流式传输到 nodejs 服务器
- node.js - 如何在 React 应用程序中使用 fetch 从 AWS RDS 中获取数据?
- java - 如何从 kstream 应用程序中读取 Kafka 消息头
- apache-spark - kmeans pyspark org.apache.spark.SparkException:作业因阶段失败而中止
- r - 选择 R 中均值最高的组
- vue.js - 前端/后端路由配置
- android - 升级到 AndroidX 和 Android Studio 4.0 后出现 java.lang.ClassNotFoundException 错误
- terraform - 我应该如何在多 pod 中使用 terraform?