-
-
Save Juanito99/44bcc30cd96128b0bcf3fc31c6436474 to your computer and use it in GitHub Desktop.
Hello @Juanito99, this is really a remarkable script you have shared here.
The only issue is, that there are no copyright and license infos contained in this script.
Therefore, it is hard to say whether someone could make use of it or not.
Would you be so kind as to add those missing infos to the script, so that it can be used by others without violating your copyright?
@stephan-pl , I added license information :-)
@MrMcGuinty , please visit Mikes' site to get some idea how it could work: https://www.networkadm.in/jump-start-powershell-remoting/
Alternatively, you could run this script by your software-deployment solution ( e.g. SCCM ) or via a Monitoring solution such as SCOM.
There are also some inexpensive Inventory tools which can provide such information. - See Jdisc.com for more information.
I was able to figure it out and added it to an onboarding script I use when scoping new AD based environments. This is very helpful and a great time saver. Thank you very much for this, and as to not be the guy that says "I figured it out" without leaving the solution, please see my added tidbits to allow for a call to AD to pull all active servers, export to list, and then run your code against all servers in the list, resulting in a subsequent CSV dump of all known shares, share permissions, and NTFS permissions across the AD Domain servers. Again, thank you very much for this.
Get Server Shares Permissions
Clear-Host
$DomName = Get-ADDomain |Select -Expand NetBIOSName
New-Item -ItemType Directory -Force -Path C:\TEMP${DomName}_Onboarding${DomName}_ServerShares\
Get-ADComputer -Filter {(OperatingSystem -Like 'Server') -AND (Enabled -Eq 'TRUE')}|Select -Expand Name|Out-File C:\TEMP${DomName}_Onboarding${DomName}_ServerShares\Servers.txt
Invoke Share Commands for All Servers in Active Directory
$resultsBSHARES = foreach ($server in $servers) {
Write-host "Processing Server $Server Basic Share Info Please Standby."
try{
Invoke-Command -ErrorAction Stop -cn $server{
<#
License terms
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.
#>
#Get All Shares
$shares = Get-WmiObject -Class Win32_Share
$shareList = New-Object -TypeName System.Collections.ArrayList
foreach ($share in $shares) {
#excluding default shares
if ((
$shareAccessInfo = ''
$ntfsAccessInfo = ''
#extract permissions from the current share
$fileAccessControlList = Get-Acl -Path $($share.Path) | Select-Object -ExpandProperty Access | Select-Object -Property FileSystemRights, AccessControlType, IdentityReference
#excluding uncritical information as Builtin Accounts as Administratrators, System, NT Service and Trusted installer
foreach ($fileAccessControlEntry in $fileAccessControlList) {
if (($fileAccessControlEntry.FileSystemRights -notmatch '\d') -and ($fileAccessControlEntry.IdentityReference -notmatch '(?i)Builtin\\Administrators|NT\sAUTHORITY\\SYSTEM|NT\sSERVICE\\TrustedInstaller')) {
$ntfsAccessInfo += "$($fileAccessControlEntry.IdentityReference); $($fileAccessControlEntry.AccessControlType); $($fileAccessControlEntry.FileSystemRights)" + ' | '
}
} #END foreach ($fileAccessControlEntry in $fileAccessControlList)
$ntfsAccessInfo = $ntfsAccessInfo.Substring(0,$ntfsAccessInfo.Length - 3)
$ntfsAccessInfo = $ntfsAccessInfo -replace ',\s?Synchronize',''
#getting share permissions
$shareSecuritySetting = Get-WmiObject -Class Win32_LogicalShareSecuritySetting -Filter "Name='$($share.Name)'"
$shareSecurityDescriptor = $shareSecuritySetting.GetSecurityDescriptor()
$shareAcccessControlList = $shareSecurityDescriptor.Descriptor.DACL
#converting share permissions to be human readable
foreach($shareAccessControlEntry in $shareAcccessControlList) {
$trustee = $($shareAccessControlEntry.Trustee).Name
$accessMask = $shareAccessControlEntry.AccessMask
if($shareAccessControlEntry.AceType -eq 0) {
$accessType = 'Allow'
} else {
$accessType = 'Deny'
}
if ($accessMask -match '2032127|1245631|1179817') {
if ($accessMask -eq 2032127) {
$accessMaskInfo = 'FullControl'
} elseif ($accessMask -eq 1179817) {
$accessMaskInfo = 'Read'
} elseif ($accessMask -eq 1245631) {
$accessMaskInfo = 'Change'
} else {
$accessMaskInfo = 'unknown'
}
$shareAccessInfo += "$trustee; $accessType; $accessMaskInfo" + ' | '
}
} #END foreach($shareAccessControlEntry in $shareAcccessControlList)
if ($shareAccessInfo -match '|') {
$shareAccessInfo = $shareAccessInfo.Substring(0,$shareAccessInfo.Length - 3)
}
#putting extracted information together into a custom object
$myShareHash = @{'Name'=$share.Name}
$myShareHash.Add('Computer',$share.PSComputerName)
$myShareHash.Add('Description',$share.Description)
$myShareHash.Add('FileSystemSPath',$share.Path )
$myShareHash.Add('SharePermissions',$shareAccessInfo)
$myShareHash.Add('NTFSPermissions',$ntfsAccessInfo)
$myShareObject = New-Object -TypeName PSObject -Property $myShareHash
$myShareObject.PSObject.TypeNames.Insert(0,'MyShareObject')
#store the custom object in a list
$null = $shareList.Add($myShareObject)
} #END if ((
} #END foreach ($share in $shares)
$shareList
}
}
catch {
"$server could not be contacted. System may be Windows Server 2008, be offline, or PS Remoting is not enabled." | Out-File -Append C:\TEMP${DomName}_Onboarding${DomName}_ServerShares${DomName}_Share_Permissions_Exceptions.csv
}
}$resultsBSHARES|Export-csv C:\TEMP${DomName}_Onboarding${DomName}_ServerShares${DomName}_Server_Share_Permissions_Info.csv -NoTypeInformation -Append
Apologies for my comment formatting. I'm still new to how GitHub formats coding in comments, so the copy/paste come back as partly in plain text and the rest in a code block. Either way, I hope this helps someone out there that needs it.
-MrMcGuinty
I ran this against a Windows 2016 server and it returned an AccessMask of 1179819 for a Read permission on a share. This was a share with Everyone Read only being the only permission. The missing value exposed an issue with the nested loop that checks the accessmask and returns accessmaskinfo. It never reached the Unknown due to the line below, causing the Substring command in the line setting the $shareAccesInfo to fail with the second arg less than zero. I think the line below and the corresponding ending } should be removed.
if ($accessMask -match '2032127|1245631|1179817') {
also I added the following to the if-elseif section for accessmask
} elseif ($accessMask -eq 1179819) {
$accessMaskInfo = 'Read'
I hope I described the issue well enough.
Hello @Juanito99 ,
Great script! Exactly what I needed to enumerate shares and get the share permissions.
I wanted to correct the regular expression matching being done in the IF statement. You have:
if (($share.Name -notmatch '(?im)^[a-z]{1,1}\$') -and ($share.Name -notmatch '(?im)^[admin]{5,5}\$') -and ($share.Name -notmatch '(?im)^[ipc]{3,3}\$') -and ($share.Name -notmatch '(?im)^[print]{5,5}\$'))
Breaking them down, the first is:
(?im)^[a-z]{1,1}\$
The quantifier {1,1}
can be simplified to {1}
(?im)^[a-z]{1}\$
The last 3 are trying to match admin, ipc, and print.
(?im)^[admin]{5,5}\$
(?im)^[ipc]{3,3}\$
(?im)^[print]{5,5}\$
Using brackets will search for each character individually, not as a word. For example, if we just look at the search for admin:
(?im)^[admin]{5,5}\$
This search is looking for any 5-character combination of the letters a, d, m, i, and n. Along with admin, the following will also match:
aaaaa$
dainm$
MINAD$
MMNNA$
To perform a literal search of the characters/word, use the following:
(?im)^admin\$
(?im)^ipc\$
(?im)^print\$
To shorten the whole thing, you can combine all of these into one query by creating a group:
if ($share.Name -notmatch '(?im)^([a-z]{1}|admin|ipc|print)\$$')
Also added a second $ at the end to match end of string/line.
I was able to figure it out and added it to an onboarding script I use when scoping new AD based environments. This is very helpful and a great time saver. Thank you very much for this, and as to not be the guy that says "I figured it out" without leaving the solution, please see my added tidbits to allow for a call to AD to pull all active servers, export to list, and then run your code against all servers in the list, resulting in a subsequent CSV dump of all known shares, share permissions, and NTFS permissions across the AD Domain servers. Again, thank you very much for this.
Get Server Shares Permissions
..
Thank you @MrMcGuinty Very appreciated :-)
Sorry @rich-houk , I am presently not able to adjust the script. Hope I can find some time in the future.
Hello @Juanito99 ,
Great script! Exactly what I needed to enumerate shares and get the share permissions.
I wanted to correct the regular expression matching being done in the IF statement. You have:
if (($share.Name -notmatch '(?im)^[a-z]{1,1}\$') -and ($share.Name -notmatch '(?im)^[admin]{5,5}\$') -and ($share.Name -notmatch '(?im)^[ipc]{3,3}\$') -and ($share.Name -notmatch '(?im)^[print]{5,5}\$'))
Breaking them down, the first is:
(?im)^[a-z]{1,1}\$
The quantifier
{1,1}
can be simplified to{1}
(?im)^[a-z]{1}\$
The last 3 are trying to match admin, ipc, and print.
(?im)^[admin]{5,5}\$
(?im)^[ipc]{3,3}\$
(?im)^[print]{5,5}\$
Using brackets will search for each character individually, not as a word. For example, if we just look at the search for admin:
(?im)^[admin]{5,5}\$
This search is looking for any 5-character combination of the letters a, d, m, i, and n. Along with admin, the following will also match:
aaaaa$
dainm$
MINAD$
MMNNA$
To perform a literal search of the characters/word, use the following:
(?im)^admin\$
(?im)^ipc\$
(?im)^print\$
To shorten the whole thing, you can combine all of these into one query by creating a group:
if ($share.Name -notmatch '(?im)^([a-z]{1}|admin|ipc|print)\$$')
Also added a second $ at the end to match end of string/line.
@DHCook Great feedback! - Thank you :-)
How would I modify this to not exclude ANY permission holders, such as Administrators? My attempts at cutting those sections are resulting in the script producing no output.
This is a wonderful script. As I'm quite new to PowerShell, is there a way I could run this against multiple servers in a domain? I've used Invoke-Command with things like Get-WMIObject and Get-CIMInstance, but I'm not sure how I could run this script in something like a foreach loop. I'd love to be able to run this against the 2000+ servers we have across our clients to audit their existing share/ntfs security. Any help would be greatly appreciated. Again, excellent script.