Public/Get-SharePermissionReport.ps1

function Get-SharePermissionReport {
    <#
    .SYNOPSIS
        Audits SMB share-level permissions for compliance issues.
 
    .DESCRIPTION
        Examines the share-level permissions (not NTFS ACLs) on SMB shares using
        Get-SmbShare and Get-SmbShareAccess. Share permissions are a separate security
        layer that is often overlooked. Common findings include Everyone with Full Control,
        shares with no explicit deny rules, and overly broad access.
 
        Note: Share permissions and NTFS permissions are evaluated together by Windows.
        The most restrictive of the two applies. However, auditors expect both layers to
        follow least-privilege.
 
    .PARAMETER ComputerName
        One or more computer names to audit. Defaults to localhost.
 
    .PARAMETER ExcludeDefault
        When specified, excludes default administrative shares (ADMIN$, C$, D$, IPC$, etc.).
 
    .EXAMPLE
        Get-SharePermissionReport
 
    .EXAMPLE
        Get-SharePermissionReport -ComputerName 'FileServer01', 'FileServer02' -ExcludeDefault
    #>

    [CmdletBinding()]
    param(
        [Parameter(Position = 0)]
        [ValidateNotNullOrEmpty()]
        [string[]]$ComputerName = @('localhost'),

        [Parameter()]
        [switch]$ExcludeDefault
    )

    begin {
        # Patterns for default administrative shares
        $defaultSharePatterns = @(
            '*$'    # All admin/hidden shares end with $
        )

        function Test-DefaultShare {
            param([string]$ShareName)
            foreach ($pattern in $defaultSharePatterns) {
                if ($ShareName -like $pattern) { return $true }
            }
            return $false
        }

        $results = [System.Collections.Generic.List[PSObject]]::new()
    }

    process {
        foreach ($computer in $ComputerName) {
            Write-Verbose "Scanning shares on: $computer"

            # Get all SMB shares
            $smbParams = @{
                ErrorAction = 'Stop'
            }

            if ($computer -ne 'localhost' -and $computer -ne $env:COMPUTERNAME -and $computer -ne '.') {
                $smbParams['CimSession'] = New-CimSession -ComputerName $computer -ErrorAction Stop
            }

            try {
                $shares = Get-SmbShare @smbParams
            }
            catch {
                Write-Warning "Cannot enumerate shares on $computer : $_"
                continue
            }

            foreach ($share in $shares) {
                # Skip default shares if requested
                if ($ExcludeDefault -and (Test-DefaultShare -ShareName $share.Name)) {
                    Write-Verbose "Skipping default share: $($share.Name)"
                    continue
                }

                # Get share-level access rules
                try {
                    $accessRules = Get-SmbShareAccess -Name $share.Name @smbParams
                }
                catch {
                    Write-Warning "Cannot read access on share $($share.Name): $_"
                    continue
                }

                $hasExplicitDeny = $false
                foreach ($rule in $accessRules) {
                    if ($rule.AccessControlType -eq 'Deny') {
                        $hasExplicitDeny = $true
                    }
                }

                foreach ($rule in $accessRules) {
                    # Determine findings
                    $findings = [System.Collections.Generic.List[string]]::new()

                    # Everyone with Full Control
                    if ($rule.AccountName -match '(^Everyone$|\\Everyone$)' -and $rule.AccessRight -eq 'Full') {
                        $findings.Add('EVERYONE FULL CONTROL')
                    }

                    # Everyone with any access
                    if ($rule.AccountName -match '(^Everyone$|\\Everyone$)' -and $rule.AccessRight -ne 'Full') {
                        $findings.Add('EVERYONE ACCESS')
                    }

                    # Full Control for non-admin accounts
                    if ($rule.AccessRight -eq 'Full' -and
                        $rule.AccountName -notmatch '(^Everyone$|\\Everyone$)' -and
                        $rule.AccountName -notmatch '(BUILTIN\\Administrators|NT AUTHORITY\\SYSTEM)') {
                        $findings.Add('FULL CONTROL GRANTED')
                    }

                    # No explicit deny on the share
                    if (-not $hasExplicitDeny -and $rule.AccessControlType -eq 'Allow') {
                        $findings.Add('NO EXPLICIT DENY ON SHARE')
                    }

                    $finding = if ($findings.Count -gt 0) {
                        $findings -join '; '
                    }
                    else {
                        'OK'
                    }

                    $result = [PSCustomObject]@{
                        ComputerName      = $computer
                        ShareName         = $share.Name
                        SharePath         = $share.Path
                        AccountName       = $rule.AccountName
                        AccessRight       = $rule.AccessRight
                        AccessControlType = $rule.AccessControlType
                        Finding           = $finding
                    }

                    $results.Add($result)
                }
            }

            # Clean up CIM session if we created one
            if ($smbParams.ContainsKey('CimSession')) {
                Remove-CimSession -CimSession $smbParams['CimSession'] -ErrorAction SilentlyContinue
            }
        }
    }

    end {
        $results
    }
}