Friday, August 5, 2011

PowerShell script for dumping access control lists (ACL)

I don’ t know if I have ever mentioned, that I am in charge for the security of some of our systems. According to “The Open Web Application Security Project (OWASP)” (https://www.owasp.org/index.php/Top_10_2010-Main) security misconfiguration is at the 6th place of the TOP10 Risks. Since I am responsible for a web cluster I wrote a small PowerShell script for reporting the access control list (ACLs) . Given an root folder, the script traverse all child object recursively (depth first) and it only outputs those ACLs which are not inherited by the parent folder. I use the script for doing security reviews. This script can be also very useful if you are planning to migrate a webserver.

Clear-Host
$path =  $args[0]   
$outPutFile =  $args[1]  
$startDate = Get-Date 
$newLine = "`r`n" #is a carrage return/line feed. 

#check input parameters
if([System.IO.Directory]::Exists($path) -eq $false){
    throw (new-object System.IO.DirectoryNotFoundException("Directory does not exist or is missing!"))
}
If($path.EndsWith("\"))
{
    $path = $path.Remove($path.Length-1, 1)
}
if ([System.String]::IsNullOrEmpty($outPutFile)){
    throw (new-object System.ApplicationException("OutputFile is missing!"))
}

#Build information for the header of the output file, if file exist it will be owerwritten!  
$header = "Start: " + $startDate + $newLine + "Output file: " + $outPutFile + $newLine + "ACL of the analyzed path: " + $path + $newLine
$mainPathAcl = get-ACL $path | Format-List
out-file -encoding ASCII -filePath $outPutFile -InputObject $header
out-file -encoding ASCII -filePath $outPutFile -append -InputObject $mainPathAcl

#depth first traverse
$myStack = new-object  System.Collections.Stack 
[System.IO.DirectoryInfo]$rootInfo = New-Object System.IO.DirectoryInfo($path)
$myStack.Push($rootInfo)

while ($myStack.Count -ne 0){
    $actualItem = $myStack.Pop();  #get last item
    #add children to stack
    if ($actualItem -is [System.IO.DirectoryInfo])
    {
        [System.IO.FileSystemInfo[]]$dirs2 = $actualItem.GetFileSystemInfos() | Sort-Object Name -Descending
        if ($dirs2){#check if it is null.
            Foreach ($dir1 in $dirs2) {  #add to the stack
                $myStack.Push($dir1)
            }
        }
        
        if($actualItem.Parent.FullName -eq $rootInfo.FullName){
            $appHeader = "" + $newLine + "------------------------" + $newLine + $actualItem.Name + $newLine + "------------------------"
              out-file -encoding ASCII -filePath $outPutFile -append -InputObject $appHeader    
        }
    }
    
    #dump acls if not inherited
    $aclActFile = Get-Acl -Path $actualItem.FullName
    $WriteFileHeader = $true; 
    Foreach ($Access in $aclActFile.Access) { 
        $Inherited = [string]$Access.IsInherited 
        if ($Inherited -eq "False") {
            #write File Header
              if ($WriteFileHeader) {
                $fileHeader = "File: " + $actualItem.FullName + $newLine + "SDDL: " + $aclActFile.Sddl
                out-file -encoding ASCII -filePath $outPutFile -append -InputObject  $fileHeader
                $WriteFileHeader = $false;
            }
            #write AccessControl in csv
            $output = "ACL:  " + $Access.AccessControlType + ", " + $Access.IdentityReference + ", " + $Access.FileSystemRights 
            out-file -encoding ASCII -filePath $outPutFile -append -InputObject $output
        }    
    }
}

#Footer
$endDate = Get-Date 
$elapsedTime = $endDate - $startDate 
$footer = "" + $newLine + "Run completed at: " + $endDate + $newLine + "Elapsed Time:" + $newLine + $elapsedTime + $newLine
out-file -encoding ASCII -filePath $outPutFile -append -InputObject $footer 

Instructions:

  1. Copy this script in a file (example: aclDump.ps1)
  2. Open PowerShell
  3. Execute the following cmd, where parameter 1 is the root folder for dumbing ACL, and parameter 2 is the output file: .\aclDump.ps1 X:\Intepub C:\AclReport.txt.

PS: If you need to full backup ACLs or to transfer ACLs you should use tools like: SubInAcl (http://www.microsoft.com/download/en/details.aspx?id=23510)