在没有读取权限的情况下写入文件

Posted

技术标签:

【中文标题】在没有读取权限的情况下写入文件【英文标题】:Write to a file without read permission 【发布时间】:2016-04-14 06:23:38 【问题描述】:

我正在尝试在 C# 中的本地 Windows 帐户上实现 Bell-La Padula 模型,在此模型中,较低安全级别的用户可以写入属于较高安全级别的文件而无需读取它! 我已经为这样的文件添加了权限

file.txt : 读取 [拒绝] - 写入 [允许]

现在我正在研究允许用户将文本附加到 file.txt 而不阅读它。 我用过这个:

using (FileStream aFile = new FileStream(filename, FileMode.Append, FileAccess.Write))
                using (StreamWriter sw = new StreamWriter(aFile))
                
                    sw.WriteLine(DateTime.Now.ToString() + " Modified BY :" + username + Environment.NewLine);
                    sw.WriteLine(textBox1.Text);
                    sw.WriteLine("---------- END User Edition --------------");
                

当我从管理员帐户运行程序时它可以工作,但是当我尝试从 Guset 帐户运行它时它会引发异常:您无法访问此文件!

我尝试在开始编辑之前添加读取权限并在完成后将其删除,但文件权限从未改变。

是否有任何编程方式可以实现,或者允许我的应用程序在来宾帐户中运行时对文件生效?

【问题讨论】:

【参考方案1】:

花了一点时间,但弄明白了。不得不使用 procmon 来解决这个问题。你的代码很好。但是,您需要正确设置权限。

对于您的文本文件,您需要将有限的帐户权限授予只写。不要检查拒绝列下的任何内容。因为如果你这样做,拒绝访问将胜过其他任何事情。您还需要向该帐户授予 Read AttributesRead Extended Attributes 权限。

您可以使用icaclscacls 完成同样的事情。以下是有关如何手动操作的手动说明。这是基于Windows 10(Win7应该是类似的):

    右键文件

    点击属性。

    切换到安全选项卡。

    点击“编辑”按钮

    点击“添加...”按钮

    找到受限用户帐户。

    返回权限选项卡,选择帐户。

    取消选中除“写入”复选框之外的所有内容。

    单击“确定”关闭此对话框。

    点击“高级”按钮。

    选择账户并点击“编辑”按钮。

    在下一个对话框中,单击“显示高级权限”

    确保选中以下复选框。

    读取属性 读取扩展属性 创建文件/写入数据 创建文件夹/追加数据 写属性

    编写扩展属性

    在所有对话框上单击“确定”。

【讨论】:

您的解决方案对我有用。就我而言,我想在网络共享上执行此操作,因此我必须将完全控制权授予每个人才能使其正常工作。【参考方案2】:

要以编程方式执行此操作,您需要允许:

System.Security.AccessControl.FileSystemRights.AppendData
System.Security.AccessControl.FileSystemRights.CreateFiles
System.Security.AccessControl.FileSystemRights.ReadAttributes
System.Security.AccessControl.FileSystemRights.ReadExtendedAttributes
System.Security.AccessControl.FileSystemRights.WriteAttributes
System.Security.AccessControl.FileSystemRights.WriteExtendedAttributes

Extra info here

Read/Write(Extended)Attributes 是写操作所必需的,上面将允许用户创建日志文件并将文本附加到它们而无法读取任何内容,如果添加Delete 权限,这将使日志文件的滚动成为可能好吧(我想说大多数人都需要它,因为拥有无限大小的日志而不滚动是非常危险的)

这可以通过任何 .NET 语言、PowerShell 示例来完成(创建和写入日志文件并滚动它们的权限):

$acl = Get-Acl "C:\logs"

$acl.SetAccessRuleProtection($true, $false) # Remove inherited
$acl.Access | %  $acl.RemoveAccessRule($_)  | Out-Null # Remove existing
$acl.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule("SYSTEM", "FullControl", "ContainerInherit, ObjectInherit", "None", "Allow")))
$acl.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule("Administrators", "FullControl", "ContainerInherit, ObjectInherit", "None", "Allow")))

$logsRights = [System.Security.AccessControl.FileSystemRights]::AppendData -bor `
              [System.Security.AccessControl.FileSystemRights]::CreateFiles -bor `
              [System.Security.AccessControl.FileSystemRights]::Delete -bor `
              [System.Security.AccessControl.FileSystemRights]::ReadAttributes -bor `
              [System.Security.AccessControl.FileSystemRights]::ReadExtendedAttributes -bor `
              [System.Security.AccessControl.FileSystemRights]::WriteAttributes -bor `
              [System.Security.AccessControl.FileSystemRights]::WriteExtendedAttributes

$acl.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule("Users", $logsRights, "ContainerInherit, ObjectInherit", "None", "Allow")))
Set-Acl "C:\logs" $acl
Write-Host "logs ACL"
$acl.Access

根据您的用例,您可能需要也可能不需要清除现有规则并添加系统/管理员,但您明白了

【讨论】:

以上是关于在没有读取权限的情况下写入文件的主要内容,如果未能解决你的问题,请参考以下文章

在不使用 UTL_FILE 的情况下从 PL/SQL 中的文件读取/写入数据

如何在文件写入时防止其他人读取/写入文件

Windows文件服务器共享的时候分配权限对于目录深文件量大的情况下,权限写入非常慢,有啥办法可以解决

如何在不重新打开文件的情况下读取然后写入/追加到文本文件?

在没有原始文件系统权限的情况下获取磁盘扇区大小

云中的 Zipfile 文件(amazon s3),无需先将其写入本地文件(无写入权限)