Solved

Powershell Script to Retrieve Filtered Remote Share Information

Posted on 2013-11-08
18
608 Views
Last Modified: 2013-11-19
History - I've been learning PowerShell for a few months now so I'm still a novice. Our environment is a Windows 2003 Mixed Mode. We can use PS 2.0 for our scripting. I use PowerGui and the "Quest.ActiveRoles.ADManagement" snapin.

Why ask my question - I'm tasked with identifying all shares where the "everyone" group has rights on the share. I need to identify those shares and perms and remove them.

Question - I want the remote share information from servers/workstations but I need to filter the results to only return the server name, share name, share path, and permissions for only the "Everyone" group. Additionally I only want results for the "Type" of "0" or which from my research is the "Disk Drive". Can my current script be modified to filter this information or will I need to take another approach?

I've seen various scripts on here that get some information but not all. I'm currently using "srvcheck.exe" from the "Windows Resource Kit" to obtain this information. I'm open to any PowerShell solution.

My Script Details:

I will attach the file I'm working with now so you can see the results I get. I changed the file extension to ".txt" from ".ps1" to be able to upload it. I'm using a list of servers that I read in.

Below is the output I'm currently getting. In this example the "Remit1", "Remit2", "Cannon2" etc. are all print queues and I don't want to see those shares and permissions.

.:| ServerName Share Permissions Review |:.
________________________________________________
 
 
***** Please remove all permissions for the EVERYONE group in each share as applicable. *****
 
Shares exempt to this include all PRINT shares and the IPC$ share.
 
\\ServerName\Documents
            BUILTIN\Power Users       Full Control
            BUILTIN\Administrators       Full Control
                Everyone              Read


\\ServerName\Images
            BUILTIN\Power Users       Full Control
            BUILTIN\Administrators       Full Control
                Everyone              Full Control

 \\ServerName\print$
            BUILTIN\Power Users       Full Control
            BUILTIN\Administrators       Full Control
            Everyone              Read


\\ServerName\Remit1
            BUILTIN\Power Users       Full Control
            BUILTIN\Administrators       Full Control
            Everyone              Full Control

\\ServerName\Remit2
            BUILTIN\Power Users       Full Control
            BUILTIN\Administrators       Full Control
            Everyone              Full Control

\\ServerName\Canon2
            BUILTIN\Power Users       Full Control
            BUILTIN\Administrators       Full Control
            Everyone              Full Control

\\ServerName\Cannon1
            BUILTIN\Power Users       Full Control
            BUILTIN\Administrators       Full Control
            Everyone              Full Control

Here's what I'd like to see:


.:| ServerName Share Permissions Review |:.
________________________________________________
 
 
***** Please remove all permissions for the EVERYONE group in each share as applicable. *****
 
Shares exempt to this include all PRINT shares and the IPC$ share.
 
 \\ServerName\Documents
            Everyone              Read


\\ServerName\Images
            Everyone              Full Control




Thanks for any input.
Get-Server-Share-Permissions.txt
0
Comment
Question by:Lobsterguy
  • 11
  • 7
18 Comments
 
LVL 39

Expert Comment

by:footech
Comment Utility
An easy way to see the shares of the type you want is
Get-WmiObject  Win32_Share -filter "type = 0"

I've mostly avoided setting any type of security through PS as I find it a pain.  I know this doesn't answer your question but I have to ask why would you want to remove those share permissions?  If you have any choice in the matter, I'd say it's much better to leave those and do your securing of the resources through NTFS permissions.
0
 

Author Comment

by:Lobsterguy
Comment Utility
Our CIPP dictates we are not allowed to have any share or NTFS permission set to "Everyone". I don't see where having it on the share is a problem if it isn't granted on the NTFS permissions. But, I'm not to argue the point. I'm just to find a solution. I'll give your solution a try. Thanks.
0
 
LVL 39

Expert Comment

by:footech
Comment Utility
I would probably just call net share commands to set the permissions.  Run net help share for the syntax.  Otherwise you may be able to set them through WMI calls, but would be much more painful to code, IMO.
0
 

Author Comment

by:Lobsterguy
Comment Utility
I'm not trying to set the permissions, I'm just wanting to view them.
0
 
LVL 39

Accepted Solution

by:
footech earned 500 total points
Comment Utility
From the first part of your question I thought you needed to remove them as well.

If you don't mind, here's a little general advice.  A good tack when writing scripts is to make it useable/extensible for other purposes.  So although your purpose here may be to just create a report, if along the way you collect the information in a form that can later be used for other purposes, you will be saving yourself some time in the long run.  I think of the flow kind of like this:
- information gathering (and maybe storage)
    - reporting
    - operations

If you combine the information gathering and reporting such that all you're outputting is formatted text, the script becomes fairly single-purpose, and it will take more work to rework it to do something else.  Said another way, once you convert all the objects in PowerShell to text strings, you've lost a lot of the value.

With that said, I put together the following to gather information about shares.  The only concessions to formatting are the Select-Object to order the properties, and the Format-Table at the end.  You could just as easily export this to a .CSV file which would allow you import it again for further operations, or create a formatted report from the info.  There are a couple commented-out lines at 20 and 49 that you can use (choose one or the other, the one at 20 shows how line 21 would need to be modified - sorry if I'm pointing out something that is very obvious to you) to filter the results so that they only include ones for "Everyone".  You could expand the filter for various names, paths, etc. if needed.  It reads in a list of machines to query from a file "serverlist.txt" that you would supply.
$typehash = @{
    0 = "Allow"
    1 = "Deny"
    }

$permhash = @{
    1179817 = "Read"
    1245631 = "Change"
    2032127 = "Full Control"
    }

$servers = Get-Content serverlist.txt

@(foreach ($server in $servers)
{
    $shareInfo = @(Get-WmiObject Win32_Share -ComputerName $server -filter "type = 0" | Select Name,Path)
    @(foreach ($share in $shareInfo)
    {
        $shareACL = (Get-WmiObject Win32_LogicalShareSecuritySetting -ComputerName $server -filter "name = '$($share.name)'").GetSecurityDescriptor().Descriptor.DACL
#        $shareACL | Where {$_.Trustee.Name -eq "Everyone"} | ForEach `
        $shareACL | ForEach `
        {
            $user = If ($_.Trustee.Domain)
                    { $_.Trustee.Domain, $_.Trustee.Name -join "\" }
                    Else
                    { $_.Trustee.Name }
            $type = switch ($_.AceType)
                    {
                        0 { $typehash[0]; break }
                        1 { $typehash[1]; break}
                    }
            $perm = switch ($_.AccessMask)
                    {
                        1179817 { $permhash[1179817]; break }
                        1245631 { $permhash[1245631]; break }
                        2032127 { $permhash[2032127]; break }
                    }
            New-Object PsObject -Property @{
                    Server = $server
                    ShareName = $share.name
                    Path = $share.path
                    UserOrGroup = $user
                    Type = $type
                    Permission = $perm
                    }
        }
    }) | Sort Server,ShareName,UserOrGroup
}) |
# Where {$_.UserOrGroup -eq "Everyone"} |
 Select Server,ShareName,Path,UserOrGroup,Type,Permission | ft -auto

Open in new window

0
 

Author Comment

by:Lobsterguy
Comment Utility
Just to clarify...I do need to remove them when all is said and done. I first have to contact the server owners and inform them of the shares that don't meet compliance and give them time to research if it is going to break a process that may be using that access once removed. Once I have the okay from them I will be able to remove the permissions.

You stated, "if along the way you collect the information in a form that can later be used for other purposes". I'm in agreement with you. I'm just not proficient enough to know how to do that or that it is even an option. How would you have written this keeping it extensible for other uses?

Thank you for your feedback. I'll give the script a try.
0
 

Author Comment

by:Lobsterguy
Comment Utility
Would you mind breaking down the script and explain what each line is doing?
1) It looks like you are using two hash tables to store the "Type" and "Permission" values.
2) Then you read in the list of servers.
3) For each server you set $shareInfo to gather the Name and Path of the drive type "0".
4) Then it looks like you are retrieving the permissons on line 19 but this is when it starts getting fuzzy for me and I can't seem to follow along with what you are doing.

Where would I put in a command to export the values into a CSV file or text file?  When I type the following it exports to a text file okay but I can't figure out how to export to a csv file.

|Out-File c:\results.txt

Thanks again for all your feedback.
0
 

Author Comment

by:Lobsterguy
Comment Utility
I think I'm starting to understand what you mean by collecting the data and then being able to use it later for other purposes. After reviewing your script you're storing the data we are collecting in various hash tables and arrays which you then call to later to retrieve the data. Whereas I was not storing the data I was just outputting it to a text file as I retrieved the data initially. Your script makes more logical sense as you clearly stated.

The last part of the code where you display the results really has me baffled as to how the text is displaying on the screen. You create a new-object PSObject but I don't see how it is displaying on the console window. I'm used to seeing a simple variable like "$varName" or write-host "Text variable etc". Could you fill in the gap on this?
0
 
LVL 39

Expert Comment

by:footech
Comment Utility
Responding to your first post...

What I posted is already written with that in mind.
All it does is gather information (with a little ordering thrown in).  If you were to remove the "ft -auto" at the end of the script and substitute
Export-CSV shareinfo.csv -notype
it would generate a .CSV file.  Then if you later ran the command
Import-CSV shareinfo.csv
you would have the exact same information available to you as if you had just run the script again.

Responding to your second post...

1)  Yes, I didn't have to use the hash tables of course, but it laid out the translations well.
2) and 3)  Correct.
4)  I'm just populating the $user, $type, and $perm variables, so that I can then create a new object with properties based on that info.  That's kind of the key here - I'm creating an object and sending it down the pipeline instead of just a bunch of strings.
0
Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

 
LVL 39

Expert Comment

by:footech
Comment Utility
When you use New-Object, it passes the object created to the pipeline.  You could leave out the Sort and Select statements at the end and still see the data.  PowerShell uses some default output rules - I don't know if I could explain it well.  If you read up on Out-Default, Format-List, and Format-Table I think you would get the picture.

Edit:  BTW it's probably worth mentioning that if I hadn't surrounded the foreach statements with array notation ("@()"), I wouldn't have been able to then pipe the output to the Sort-Object or Select-Object commands.  This is because the foreach statement doesn't send output to the pipeline.  This is different from the ForEach-Object cmdlet (which has an alias "foreach"), which does pass output to the pipeline.
0
 

Author Comment

by:Lobsterguy
Comment Utility
Thank you for the explanations.
0
 

Author Closing Comment

by:Lobsterguy
Comment Utility
Not only did you help to solve my issue but you also helped to explain the pieces I didn't understand. I appreciate the thoroughness of your responses and willingness to help educate.
0
 

Author Comment

by:Lobsterguy
Comment Utility
The last part I need to setup is to store all the share information for each server in its own file. Would it be better to import that information from one master .csv file containing all the servers and then filter out the individual servers from that? Or what method would you recommend?

Each server has an owner and I have to email them the shares with the everyone group that needs to be addressed. My thought was to list all the shares violating this permission setting  and just email the text document to them. I'm certainly open to other suggestions.
0
 
LVL 39

Expert Comment

by:footech
Comment Utility
Two options:
1)  Pipe the results from line 47 to Export-CSV using a filename based on the server (I'm omitting any Sort or Select just to make the example simpler, you can add them as desired).
    }) | Export-CSV shareinfo-$server.csv -notype

Open in new window

Be aware that with the export here nothing is sent down the pipeline, so the pipe on line 48, and lines 49 and 50 could no longer be used.

2)  If you sent all the results to one master file, then you could use the following to then generate sub-files from it.
# with PS 3.0
# not efficient because of opening and closing files repeatedly, but simple code
Import-CSV shareinfo.csv | ForEach { $_ | Export-CSV "shareinfo-$($_.server).csv" -notype -append }

# or
# doesn't require PS 3.0
$servers = Get-Content serverlist.txt  #could generate the list of servers from shareinfo.csv, but if we already have the list this is simpler
$data = Import-CSV shareinfo.csv 
foreach ($server in $servers)
{ $data | Where {$_.server -eq $server } | Export-CSV "shareinfo-$server.csv" -notype }

Open in new window

0
 

Author Comment

by:Lobsterguy
Comment Utility
Thank you. I'll have to with option #2 since we are using PS2.
0
 

Author Comment

by:Lobsterguy
Comment Utility
I keep getting the following errors when I run the script. My code is at the bottom.

Currently processing shares for ALBADSDCP001P.
ForEach-Object : Cannot convert 'System.Management.ManagementBaseObject[]' to the type 'System.Management.Aut
omation.ScriptBlock' required by parameter 'Process'. Specified method is not supported.
At R:\SysAdmin\PowerShell\Scripts\AD\Share_Information\View_Perms_for_Everyone.ps1:23 char:69
+         $shareACL | Where {$_.Trustee.Name -eq "Everyone"} | ForEach <<<<  `
    + CategoryInfo          : InvalidArgument: (:) [ForEach-Object], ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgument,Microsoft.PowerShell.Commands.ForEachObjectCommand
 
ForEach-Object : Cannot convert 'System.Management.ManagementBaseObject[]' to the type 'System.Management.Aut
omation.ScriptBlock' required by parameter 'Process'. Specified method is not supported.
At R:\SysAdmin\PowerShell\Scripts\AD\Share_Information\View_Perms_for_Everyone.ps1:23 char:69
+         $shareACL | Where {$_.Trustee.Name -eq "Everyone"} | ForEach <<<<  `
    + CategoryInfo          : InvalidArgument: (:) [ForEach-Object], ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgument,Microsoft.PowerShell.Commands.ForEachObjectCommand


Code-->

cd "R:\SysAdmin\PowerShell\Scripts\AD\Share_Information"
cls
$typehash = @{
    0 = "Allow"
    1 = "Deny"
    }

$permhash = @{
    1179817 = "Read"
    1245631 = "Change"
    2032127 = "Full Control"
    }

$servers = Get-Content "Everyone_ServerList.txt"

@(foreach ($server in $servers)
{
	Write-Host "Currently processing shares for $server."
    $shareInfo = @(Get-WmiObject Win32_Share -ComputerName $server -filter "type = 0" | Select Name,Path)
    @(foreach ($share in $shareInfo)
    {
        $shareACL = (Get-WmiObject Win32_LogicalShareSecuritySetting -ComputerName $server -filter "name = '$($share.name)'").GetSecurityDescriptor().Descriptor.DACL
        $shareACL | Where {$_.Trustee.Name -eq "Everyone"} | ForEach `
        $shareACL | ForEach `
        {
            $user = If ($_.Trustee.Domain)
                    { $_.Trustee.Domain, $_.Trustee.Name -join "\" }
                    Else
                    { $_.Trustee.Name }
            $type = switch ($_.AceType)
                    {
                        0 { $typehash[0]; break }
                        1 { $typehash[1]; break}
                    }
            $perm = switch ($_.AccessMask)
                    {
                        1179817 { $permhash[1179817]; break }
                        1245631 { $permhash[1245631]; break }
                        2032127 { $permhash[2032127]; break }
                    }
            New-Object PsObject -Property @{
                    Server = $server
                    ShareName = $share.name
                    Path = $share.path
                    UserOrGroup = $user
                    Type = $type
                    Permission = $perm
                    }
        }
    }) | Sort Server,ShareName,UserOrGroup
}) |
 #Where {$_.UserOrGroup -eq "Everyone"} |
 Select Server,ShareName,Path,UserOrGroup,Type,Permission | ft -auto
 
 
 #Report
 # with PS 3.0
# not efficient because of opening and closing files repeatedly, but simple code
#Import-CSV shareinfo.csv | ForEach { $_ | Export-CSV "shareinfo-$($_.server).csv" -notype -append }

# or
# doesn't require PS 3.0
$servers = Get-Content serverlist.txt  #could generate the list of servers from shareinfo.csv, but if we already have the list this is simpler
$data = Import-CSV shareinfo.csv 
foreach ($server in $servers)
{ $data | Where {$_.server -eq $server } | Export-CSV "shareinfo-$server.csv" -notype }

Open in new window

0
 
LVL 39

Expert Comment

by:footech
Comment Utility
The error came from uncommenting line 23 without then deleting the following line.
Also, you hadn't made a change to export the info to a master .CSV, so there would be an error when generating the per-server reports.  I made both changes below.
cd "R:\SysAdmin\PowerShell\Scripts\AD\Share_Information"
cls
$typehash = @{
    0 = "Allow"
    1 = "Deny"
    }

$permhash = @{
    1179817 = "Read"
    1245631 = "Change"
    2032127 = "Full Control"
    }

$servers = Get-Content "Everyone_ServerList.txt"

@(foreach ($server in $servers)
{
	Write-Host "Currently processing shares for $server."
    $shareInfo = @(Get-WmiObject Win32_Share -ComputerName $server -filter "type = 0" | Select Name,Path)
    @(foreach ($share in $shareInfo)
    {
        $shareACL = (Get-WmiObject Win32_LogicalShareSecuritySetting -ComputerName $server -filter "name = '$($share.name)'").GetSecurityDescriptor().Descriptor.DACL
        $shareACL | Where {$_.Trustee.Name -eq "Everyone"} | ForEach `
        {
            $user = If ($_.Trustee.Domain)
                    { $_.Trustee.Domain, $_.Trustee.Name -join "\" }
                    Else
                    { $_.Trustee.Name }
            $type = switch ($_.AceType)
                    {
                        0 { $typehash[0]; break }
                        1 { $typehash[1]; break}
                    }
            $perm = switch ($_.AccessMask)
                    {
                        1179817 { $permhash[1179817]; break }
                        1245631 { $permhash[1245631]; break }
                        2032127 { $permhash[2032127]; break }
                    }
            New-Object PsObject -Property @{
                    Server = $server
                    ShareName = $share.name
                    Path = $share.path
                    UserOrGroup = $user
                    Type = $type
                    Permission = $perm
                    }
        }
    }) | Sort Server,ShareName,UserOrGroup
}) |
 Select Server,ShareName,Path,UserOrGroup,Type,Permission |
 Export-CSV shareinfo.csv -notype
 
 
 #Report

$data = Import-CSV shareinfo.csv 
foreach ($server in $servers)
{ $data | Where {$_.server -eq $server } | Export-CSV "shareinfo-$server.csv" -notype }

Open in new window

0
 

Author Comment

by:Lobsterguy
Comment Utility
Thank you. I will compare my code to yours to learn what I missed.
0

Featured Post

Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

Join & Write a Comment

This script checks a path to see if a folder exists. If the folder does exist you will get output "The folder has previously been created. No action taken" If not it will create the folder. Then adds one user modify permission to the folder. It …
In this previous article (https://oddytee.wordpress.com/2016/05/05/provision-new-office-365-user-and-mailbox-from-exchange-hybrid-via-powershell/), we made basic license assignments to users in O365. When I say basic, the method is the simplest way …
Internet Business Fax to Email Made Easy - With eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, fr…
This video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Items…

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

9 Experts available now in Live!

Get 1:1 Help Now