原文地址:http://www.pstips.net/managing-access-permissions.html
PowerShell 文件系統系列文章:
PowerShell文件系統(一)前言PowerShell文件系統(二)訪問文件和目錄PowerShell文件系統(三)導航文件系統PowerShell文件系統(四)使用目錄和文件工作PowerShell文件系統(五)管理訪問權限對于NTFS驅動器來說,訪問權限決定著那個用戶可以訪問文件和目錄。對于每一個文件和文件夾,所謂的安全描述符(SD)規定了安全數據。安全描述符決定安全設置是否只對當前目錄有效,或者它可以被傳遞給其它文件和目錄。真正的訪問權限是在訪問控制列表(ACL)中。每一個訪問權限的訪問控制項(ACE)也在ACL中。
注意:文件和目錄訪問權限相當于一個復雜的電子鎖。如果使用得當,你可以把它變成一個有力的安全系統。然而,如果使用不當,你可能很容易把自己鎖在外面,失去了訪問重要數據的權限,或者破壞了Windows操作系統(當你無意間禁止了訪問關鍵系統目錄的權限后)。作為文件和目錄的所有者,你總是有更正權限的選項;作為一個管理員,你也總能取得文件和目錄的擁有權。但這是不得已的后門,你不能依賴它:你應當在你能意識到后果的情況下更改權限。最好一開始使用測試文件和目錄做實驗。
PowerShell使用Get-Acl 命令 Set-Acl 來管理權限。此外,類似cacls這樣的傳統命令也可以在PowerShell的控制臺上面使用。通常他們更改起來訪問權限會比PowerShell命令更快。尤其在你處理非常多的文件和目錄時。由于Windows Vista的發布,cacls一直被視為過時。如果可能的化,你可以使用它的繼任者icacls。
PS> icacls /?ICACLS name /save aclfile [/T] [/C] [/L] [/Q] 將匹配名稱的文件和文件夾的 DACL 存儲到 aclfile 中 以便將來與 /restore 一起使用。請注意,未保存 SACL、 所有者或完整性標簽。ICACLS directory [/substitute SidOld SidNew [...]] /restore aclfile [/C] [/L] [/Q] 將存儲的 DACL 應用于目錄中的文件。ICACLS name /setowner user [/T] [/C] [/L] [/Q] 更改所有匹配名稱的所有者。該選項不會強制更改所有 身份;使用 takeown.exe 實用程序可實現 該目的。ICACLS name /findsid Sid [/T] [/C] [/L] [/Q] 查找包含顯式提及 SID 的 ACL 的 所有匹配名稱。ICACLS name /verify [/T] [/C] [/L] [/Q] 查找其 ACL 不規范或長度與 ACE 計數不一致的所有文件。ICACLS name /reset [/T] [/C] [/L] [/Q] 為所有匹配文件使用默認繼承的 ACL 替換 ACL。ICACLS name [/grant[:r] Sid:perm[...]] [/deny Sid:perm [...]] [/remove[:g|:d]] Sid[...]] [/T] [/C] [/L] [/Q] [/setintegritylevel Level:policy[...]] /grant[:r] Sid:perm 授予指定的用戶訪問權限。如果使用 :r, 這些權限將替換以前授予的所有顯式權限。 如果不使用 :r,這些權限將添加到以前授予的 所有顯式權限。 /deny Sid:perm 顯式拒絕指定的用戶訪問權限。 將為列出的權限添加顯式拒絕 ACE, 并刪除所有顯式授予的權限中的相同權限。 /remove[:[g|d]] Sid 刪除 ACL 中所有出現的 SID。使用 :g,將刪除授予該 SID 的所有權限。使用 :d,將刪除拒絕該 SID 的所有權限。 /setintegritylevel [(CI)(OI)]級別將完整性 ACE 顯式 添加到所有匹配文件。要指定的級別為以下級別 之一: L[ow] M[edium] H[igh] 完整性 ACE 的繼承選項可以優先于級別,但只應用于 目錄。 /inheritance:e|d|r e - 啟用繼承 d - 禁用繼承并復制 ACE r - 刪除所有繼承的 ACE注意: Sid 可以采用數字格式或友好的名稱格式。如果給定數字格式, 那么請在 SID 的開頭添加一個 *。 /T 指示在以該名稱指定的目錄下的所有匹配文件/目錄上 執行此操作。 /C 指示此操作將在所有文件錯誤上繼續進行。 仍將顯示錯誤消息。 /L 指示此操作在符號 鏈接本身而不是其目標上執行。 /Q 指示 icacls 應該禁止顯示成功消息。 ICACLS 保留 ACE 項的規范順序: 顯式拒絕 顯式授予 繼承的拒絕 繼承的授予 perm 是權限掩碼,可以指定兩種格式之一: 簡單權限序列: N - 無訪問權限 F - 完全訪問權限 M - 修改權限 RX - 讀取和執行權限 R - 只讀權限 W - 只寫權限 D - 刪除權限 在括號中以逗號分隔的特定權限列表: DE - 刪除 RC - 讀取控制 WDAC - 寫入 DAC WO - 寫入所有者 S - 同步 AS - 訪問系統安全性 MA - 允許的最大值 GR - 一般性讀取 GW - 一般性寫入 GE - 一般性執行 GA - 全為一般性 RD - 讀取數據/列出目錄 WD - 寫入數據/添加文件 AD - 附加數據/添加子目錄 REA - 讀取擴展屬性 WEA - 寫入擴展屬性 X - 執行/遍歷 DC - 刪除子項 RA - 讀取屬性 WA - 寫入屬性 繼承權限可以優先于每種格式,但只應用于 目錄: (OI) - 對象繼承 (CI) - 容器繼承 (IO) - 僅繼承 (NP) - 不傳播繼承 (I) - 從父容器繼承的權限示例: icacls c:/windows/* /save AclFile /T - 將 c:/windows 及其子目錄下所有文件的 ACL 保存到 AclFile。 icacls c:/windows/ /restore AclFile - 將還原 c:/windows 及其子目錄下存在的 AclFile 內 所有文件的 ACL。 icacls file /grant Administrator:(D,WDAC) - 將授予用戶對文件刪除和寫入 DAC 的管理員 權限。 icacls file /grant *S-1-1-0:(D,WDAC) - 將授予由 sid S-1-1-0 定義的用戶對文件刪除和 寫入 DAC 的權限。檢查有效的安全設置
文件和目錄的有效安全設置在訪問控制列表中,使用Get-Acl時,會獲取列表中的內容。因此如果你想找出誰能夠訪問某些文件或者目錄,可以這樣處理:
# 列出Windows目錄的權限:PS> Get-Acl $env:windir Directory: C:/Path Owner Access---- ----- ------Windows NT SERVICE/TrustedInstaller CREATOR OWNER Allow 268435456...確認文件所有者的身份
文件和目錄的所有者還有一些特殊的權限。比如文件的所有者總是能夠訪問文件。你可以通過Owner屬性,來獲取所有者名稱。
| 123 | (Get-Acl$env:windir).Owner NT SERVICE/TrustedInstaller |
實際上訪問權限就是——誰可以做什么,下面輸出訪問屬性:
PS> (Get-Acl $env:windir).Access | Format-Table -wrap FileSystemRights AccessControlType IdentityReference IsInherited InheritanceFlags PRopagationFlags ---------------- ----------------- ----------------- ----------- ---------------- ---------------- 268435456 Allow CREATOR OWNER False ContainerInherit, InheritOnly ObjectInherit 268435456 Allow NT AUTHORITY/SYSTEM False ContainerInherit, InheritOnly ObjectInheritModify, Synchronize Allow NT AUTHORITY/SYSTEM False None None 268435456 Allow BUILTIN/Administrat False ContainerInherit, InheritOnly ors ObjectInheritModify, Synchronize Allow BUILTIN/Administrat False None None ors -1610612736 Allow BUILTIN/Users False ContainerInherit, InheritOnly ObjectInherit ReadAndExecute, Allow BUILTIN/Users False None None Synchronize 268435456 Allow NT SERVICE/TrustedI False ContainerInherit InheritOnly nstaller FullControl Allow NT SERVICE/TrustedI False None None nstaller在上面表格的IdentityReference列,告訴你誰有特殊的權限。FileSystemRights列告訴你權限的類型。AccessControlType列格外重要,如果它顯示“拒絕”而不是“允許”,你懂的,它會限制用戶訪問。
創建新的權限
Get-Acl執行后返回的對象,包含若干方法可以用來更新權限和設定所有權。如果你只想設定自己的權限,都沒必要去安全描述符世界深究。往往,讀取一個已經存在的文件安全描述符,把它傳遞給另一個文件,或者按照特殊SDDL語言文字的形式指定安全信息就夠了。
技巧:下面的例子會讓你認識一些日常步驟。注意兩點即可:別忘了cacls這個可靠的工具,因為使用它會比PowerShell命令更高效。此外,Get-ACL和Set-ACL不僅僅應用于文件層面,還可以用于其它有訪問控制的安全描述符的任何地方,比如Windows注冊表(會在下一章講解)。
克隆權限
在一個初級的案例中,你可能都不會創建任何新的權限,只會從一個已經存在的文件或者目錄的訪問控制列表中克隆一個權限,然后把它轉讓給其它文件。優點是可以使用圖形用戶界面來設置那些通常比較復雜的權限。
注意:因為手動調整安全設置是一項專業,各個Windows系統不通用(像Windows xp Home就沒有這個選項)的工作。盡管如此,你卻可以使用PowerShell在不同的Windows版本中設置權限。
開始之前,先創建兩個目錄作為測試:
| 12 | md Prototype | out-nullmd Protected | out-null |
現在,打開資源管理器,設置Prototype目錄的安全設置。
| 1 | explorer . |
在資源管理器中,右擊Prototype目錄,選擇屬性,然后點擊安全選項卡,點擊編輯(win7和win8中)。通過添加其他用戶來更改測試目錄的安全設置。在下面的對話框中給新用戶設置權限。
注意:你也可以通過勾選拒絕復選框來拒絕用戶的權限。這樣做時,可要留心了。因為限制權限總是有高優先級。比如,你給了自己完全控制的權限,但是拒絕了“Everyone”這個組來訪問。這樣就把自己關在文件系統的外面了。因為你也屬于”Everyone”這個組,同時因為限制的優先級比較高,哪怕你已經給了自己“完全控制”的權限,這個限制也作用于你。
你更改了權限后,捎帶在資源管理器中看看第二個目錄Protected。這個目錄仍舊是默認賦予的權限。下一步,我們會把Prototype剛才設置的權限轉交到Protected目錄。
| 12 | $acl= Get-AclPrototypeSet-AclProtected $acl |
注意:你本身需要特殊的權限去設置上面的權限。如果你用的是Windows Vista操作系統,并且啟用了UAC,使用PowerShell操作時,會出現錯誤,提示你沒有權限。這時可以通過讓控制臺以管理員權限運行來獲取權限。
實驗做完了,現在呢,Protected和Prototype一樣安全。當你在資源管理器中查看它們的安全設置時,你會發現所有的設置都是相同的。
前面的例子非常簡單,你所做的只是把已有目錄的安全設置移交給其它目錄。在你的日常工作中,你可能得具備一個你根本就不需要的Prototype目錄。但是你可以通過文本格式的安全描述符來歸納安全設置。每一個安全設置都是被特殊的安全描述符描述語言(SDDL)定義的。它能讓你以文本的形式讀取Prototype目錄的安全信息,以后無須借助Prototype目錄即可使用。
讓我們刪掉這個測試目錄Protected吧,然后在SDDL中保存Prototype目錄的安全信息。
PS> Del ProtectedPS> $acl = Get-Acl PrototypePS> $sddl = $acl.SddlPS> $sddlO:S-1-5-21-2146773085-903363285-719344707-1282827G:DUD:PAI(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;FA;;;S-1-5-21-2146773085-903363285-719344707-1282827)(A;OICI;FR;;;S-1-5-21-2575865618-2571387221-2201921913-1000)然后把這個SDDL文本保存到第二個腳本中,可將該安全設置賦給任意目錄。
| 12345678910 | # 創建新目錄Md Protected# 在 SDDL中的是安全描述符 (一行):$sddl= "O:S-1-5-21-2146773085-903363285-719344707-1282827G:DUD:PAI(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;FA;;;S-1-5-21-2146773085-903363285-719344707-1282827)(A;OICI;FR;;;S-1-5-21-2575865618-2571387221-2201921913-1000)"# 獲取目錄的安全描述:$acl= Get-AclProtected# 使用SDDL定義替換安全描述 :$acl.SetSecurityDescriptorSddlForm($sddl)# 保存更新Set-AclProtected $acl |
注意:你的第二個目錄是完全獨立于Prototype目錄的。你所需要做的可能是,借助Prototype目錄使用圖形用戶界面,臨時生成一個SDDL安全設置定義。
然而,SDDL不能很方便的移交給其它機器。如果你仔細看下,每個授權用戶不是根據用戶名識別,而是根據它們的安全標識符(SID)識別。不同的機器上,即使用戶名相同,這個SID也不會相同,因為它們隸屬不同的賬戶。但是在一個域(domain)中,相同名字的賬號的SID是相同的,因為域會集中管理。其結果就是SDDL解決方案在基于域環境的公司網絡中非常完美。盡管如此,如果你處在一個小型的對等網絡中,SDDL也能非常有用。你只需要使用“復制黏貼”去替換SID而已。不過,在對等網絡中,cacls 或者 icacls命令可能更簡單一點。
權限也可以被手動創建。其優點就是,即使沒有集中域,你也可以根據用戶名來指定授權用戶,這樣可以以相同的方式在任意機器上工作。但是注意,它引入了額外的工作,因為你必須完全創建你自己的安全描述符,接下來的例子會展示。但是在實踐中發現這個過程非常的耗時。使用cacls和icacls都比它簡單一點。現在我們刪除掉測試目錄Protected,再次創建一個新的目錄,讓它只有默認的訪問權限。
| 123456789101112131415161718192021 | $acl= Get-AclProtected# 添加第一個規則:$person= [System.Security.Principal.NTAccount]"Administrator"$access= [System.Security.AccessControl.FileSystemRights]"FullControl"$inheritance= [System.Security.AccessControl.InheritanceFlags]"ObjectInherit,ContainerInherit"$propagation= [System.Security.AccessControl.PropagationFlags]"None"$type= [System.Security.AccessControl.AccessControlType]"Allow"$rule= New-ObjectSystem.Security.AccessControl.FileSystemAccessRule($person,$access,$inheritance,$propagation,$type)$acl.AddAccessRule($rule) # 添加第二個規則:$person= [System.Security.Principal.NTAccount]"Everyone"$access= [System.Security.AccessControl.FileSystemRights]"ReadAndExecute"$inheritance= [System.Security.AccessControl.InheritanceFlags]"ObjectInherit,ContainerInherit"$propagation= [System.Security.AccessControl.PropagationFlags]"None"$type= [System.Security.AccessControl.AccessControlType]"Allow"$rule= New-ObjectSystem.Security.AccessControl.FileSystemAccessRule($person,$access,$inheritance,$propagation,$type)$acl.AddAccessRule($rule) # 保存權限更新:Set-AclProtected $acl |
接下來,讓我們一起看看每個訪問規則是怎么定義的。每一個規則需要5個細節:
Person:這是該規則應當適用的人或者組。Access:這里選擇規則要控制的權限。Inheritance:這里選擇規則要應用的對象。這個規則能夠,并且一般是會授予它的子對象,這樣它就能自動適用于目錄中的文件了。Propagation:決定權限是否要傳遞給子對象(比如子目錄和文件),通常情況下設置為None,僅僅授予權限。Type:它能讓你設置權限或者限制,如果限制,指定的權限會明確不予批準。接下來問題是這些規范允許那些值?這個例子演示通過.NET對象(第六章)顯示這些規范。你可以使用下面的機器列出訪問權限允許的值:
[System.Enum]::GetNames([System.Security.AccessControl.FileSystemRights])ListDirectoryReadDataWriteDataCreateFilesCreateDirectoriesAppendDataReadExtendedAttributesWriteExtendedAttributesTraverseExecuteFileDeleteSubdirectoriesAndFilesReadAttributesWriteAttributesWriteDeleteReadPermissionsReadReadAndExecuteModifyChangePermissionsTakeOwnershipSynchronizeFullControl如果你想設置權限時,實際上得結合上面列表中列出的相關值,比如:
$access = [System.Security.AccessControl.FileSystemRights]::Read `-bor [System.Security.AccessControl.FileSystemRights]::Write$access131209結果是一個數字,讀和寫權限的位掩碼。在上面的例子中,你可以非常簡單第獲取相同的結果,因為允許你指定你想要的項目,甚至把它們放在一個逗號分隔項中,緊跟在括號括起來的.NET枚舉類型后面。
$access = [System.Security.AccessControl.FileSystemRights]"Read,Write"$access Write, Read[int]$access 131209因為這里你沒有指定二進制計算符-bor,它的結果是可讀的文本。而此時需要位掩碼來工作,所以把它轉換成Integer整形數據類型。你可以像這樣隨時得出設置的相關值。
[int][System.Security.AccessControl.InheritanceFlags] `"ObjectInherit,ContainerInherit"3這樣做的意義在于你現在可以測試其它.NET枚舉類型的值,把它們轉換成整數。雖然不能增強你的命令的可讀性,但是可以壓縮腳本。因為下面的腳本行和前面例子中的腳本行可以做同一件事。
| 123456789 | Del ProtectedMd Protected$acl= Get-AclProtected$rule= New-ObjectSystem.Security.AccessControl.FileSystemAccessRule("Administrator",2032127,3,0,0)$acl.AddAccessRule($rule)$rule= New-ObjectSystem.Security.AccessControl.FileSystemAccessRule("Everyone",131241,3,0,0)$acl.AddAccessRule($rule)# 保存更新的權限:Set-AclProtected $acl |
最后,我們看看PowerShell是怎么指定特定用戶的權限的。在上面的例子中,你指定了用戶或者組的名稱,但是權限不能識別用戶名,但能識別賬號的唯一SID,用戶名在內部會被更改成SID,你也可以在腳本中手動更改用戶名,看看指定的用戶名是否存在。
$Account = [System.Security.Principal.NTAccount]"Administrators"$SID = $Account.translate([System.Security.Principal.Securityidentifier])$SIDBinaryLength AccountDomainSid Value------------ ---------------- -----16 S-1-5-32-544一個NTAccount對象描述了一個權限可以分配的安全主體。在實踐中,它是用戶和組。NTAccount對象可以使用Translate()來輸出它包含的與主體對應的SID。而這只會在指定的賬號確實存在的情況下有效。否則,你會得到一個錯誤。因此你也可以使用Translate()來驗證一個賬號的存在性。
通過Translate()獲取的SID非常有用。如果你仔細看,你會發現管理員組的SID和你自己當前賬號的SID完全不同:
([System.Security.Principal.NTAccount]"$env:userdomain/$env:username").`Translate([System.Security.Principal.Securityidentifier]).ValueS-1-5-21-2146773085-903363285-719344707-1282827([System.Security.Principal.NTAccount]"Administrators").`Translate([System.Security.Principal.Securityidentifier]).ValueS-1-5-32-544管理員組的SID不但很短,而且是唯一的。為了整合這個賬號,Windows使用了所謂的眾所周知的SID,它在所有的Windows系統中都是相同的。這一點很重要,因為你德文系統中運行上面的腳本會失敗。在本地化的德文系統上,因為Administrators組叫做”Administratoren”,”Everyone”組叫做”Jeder”。但是這些賬號的SID是相同的。知道了這些組的SID號,你就可以使用它們代替那些本地化的名稱了。下面是怎樣將SID轉換成用戶賬號的名稱:
$sid = [System.Security.Principal.SecurityIdentifier]"S-1-1-0"$sid.Translate([System.Security.Principal.NTAccount])Value-----Everyone這是怎樣讓你的腳本能夠非常完美地在國際本地化機器上運行:
| 1234567891011121314151617181920 | Del ProtectedMd Protected$acl= Get-AclProtected # 管理員完全控制:$sid= [System.Security.Principal.SecurityIdentifier]"S-1-5-32-544"$access= [System.Security.AccessControl.FileSystemRights]"FullControl"$rule= New-ObjectSystem.Security.AccessControl.FileSystemAccessRule( `$sid,$access,3,0,0)$acl.AddAccessRule($rule) # 所有用戶的只讀權限:$sid= [System.Security.Principal.SecurityIdentifier]"S-1-1-0"$access= [System.Security.AccessControl.FileSystemRights]"ReadAndExecute"$rule= New-ObjectSystem.Security.AccessControl.FileSystemAccessRule( `$sid,$access,3,0,0)$acl.AddAccessRule($rule) # 保存權限更新:Set-AclProtected $acl |
原文地址:Working with the File System
本文鏈接: http://www.pstips.net/managing-access-permissions.html請尊重原作者和編輯的辛勤勞動,歡迎轉載,并注明出處!新聞熱點
疑難解答