powershellaclsmb

Powershell script - Enumerating all SMB shares with their permissions remotely


I was trying to enumerate all open shares with their permissions but getting Access Denied error when trying to use "Get-SmbShareAccess" on the open shares. SO far I could try the below script .

$ComputersNames = Get-ADComputer -Filter * | select Name

$FileShares = [System.Collections.Generic.List[pscustomobject]]::new()

foreach ($ComputerName in $ComputersNames)
{ 
    $newRow = New-Object -TypeName psobject
    $newRow | Add-Member -NotePropertyName 'Computer_Name' -NotePropertyValue $ComputerName
    try 
    {
         $connected = (Test-Connection -BufferSize 32 -Count 1 -ComputerName $ComputerName -Quiet -ErrorAction Ignore)
       
        if ($connected) 
        {
            $Shares = net view \\$ComputerName /all 2>&1 | select-object -Skip 7 |  ? { $_ -match 'disk*' } | % { $_ -match '^(.+?)\s+Disk*' | out-null; $matches[1] }

            foreach ($Share in $Shares) {
                $Access = Invoke-Command -ComputerName $ComputerName -ScriptBlock { Get-SmbShareAccess }                                      
                $newRow | Add-Member -NotePropertyName 'Share_Name' -NotePropertyValue $Share -Force
                $newRow | Add-Member -NotePropertyName 'Access' -NotePropertyValue $Access -Force
            }   
        }
    }
    catch {
        Write-Host $_.Exception.Message
        Write-Host $_.Exception
    }
    $FileShares.Add($newRow)  | Out-Null
}

Firstly is there any workaround to get the user permissions on the smb shares of the remote computers without getting access denied error

Secondly even if a computer has more than 1 open shares but the output of $newRow prints only the last share

Thirdly I need to get the output of the script in a proper format exported to either txt file or csv , something like every open shares with their permissions against their computer Name

Thanks in Advnace


Solution

  • Have you tried adding admin credentials to the Invoke-Command where you run a scriptblock on the remote machine to get the Access of the share?
    Personally, I would run both Get-SmbShare and Get-SmbShareAccess inside the same scriptblock on the remote computer, then select what properties you want returned and collect all that in a variale.

    $credential   = Get-Credential -Message 'Please enter admin credentials'
    $allComputers = (Get-ADComputer -Filter *).Name    # just their names
    
    # loop through the list of computers and capture the output from the loop
    $result = foreach ($computer in $allComputers) { 
        $connected = (Test-Connection -BufferSize 32 -Count 1 -ComputerName $computer -Quiet -ErrorAction SilentlyContinue)
        if ($connected) {
            try {
                Invoke-Command -ComputerName $computer -Credential $credential -ScriptBlock {
                    $shares = Get-SmbShare | Where-Object {$_.ShareType -eq 'FileSystemDirectory'}
                    # if you also want to exclude all sharesnames ending in '$', do
                    # $shares = Get-SmbShare | Where-Object {$_.ShareType -eq 'FileSystemDirectory' -and !($_.Name.Endswith('$'))}
                    foreach($share in $shares) {
                        Get-SmbShareAccess -Name $share.Name | 
                            Select-Object @{Name = 'Computer_Name'; Expression = {$using:computer}},
                                          @{Name = 'Share_Name'; Expression = {$_.Name}},
                                          AccountName, AccessControlType, AccessRight
                    }
                }
            }
            catch {
                Write-Warning $_.Exception.Message
            }
        }
        else {
            Write-Warning "Computer $computer is unreachable"
        }
    }
    
    # remove the extra properties Invoke-Command added and write to CSV file
    $result | Select-Object * -ExcludeProperty PS*, RunSpaceId |
              Export-Csv -Path 'C:\SomePath\FileShareInformation.csv' -NoTypeInformation -UseCulture