October 14, 2016

In the past, I had found myself needing to do an audit on some network shares for any files that might contain passwords. Instead of doing manual searches on these shares, I decided that it might be more beneficial to create a PowerShell script that would provide a more automated approach. What I needed was a script that could be easily ran against various network share locations, searching for a particular string (e.g. "password"). Any file that was found to have this string within either its filename or the contents of the file would then have its full path added to the chosen output text file. For my audit, I was not interested in the passwords themselves, but more concerned with the existence of such password files.

For this particular script, we will be configuring it to accept input directly from the user while executing it via a command-line. By configuring these parameters, found in the following code snippet, you will be able to pass the Directory that you want to run a recursive search under, the text that you wish to search for, and the output file you wish to save your results to directly into the PowerShell script. This is extremely useful for scripts that you may run often, and with different parameters, as you will not have to directly modify the source code each time you wish to run it.

[CmdletBinding()]
Param (
    [Parameter(Mandatory=$True,Position=0)]
    [string]$Directory,

    [Parameter(Mandatory=$True,Position=1)]
    [string]$Text,

    [Parameter(Position=2)]
    [string]$Output
)

The next part of this script will be to define what file extensions we wish to perform our text search against into an Array. Feel free to add any additional file extensions that you might want to try and search against, but know that not all extensions work well with this method of searching.

$Extensions=@("TXT","XLS","CSV","DOC","RTF")

Now that we have the extensions that we wish to search for declared in an Array, with will need to loop through each of these extensions, prepending "*." so that we can search for any possible file with that particular file extension. The beginning of this loop will look like so.

ForEach ($Extension in $Extensions) {
    $File = "*." + $Extension

The next part of this loop will be to recursively get a list of all of the files located within the directory given as part of this script's parameters. The results of this code snippet will need to be piped over to the next step.
Get-ChildItem $Directory -Filter $File -Recurse -Force |

The previously obtained list of files will be piped into another loop. For this, we will utilize the ForEach-Object cmdlet, looping through each file. For ease of use, the beginning of this loop will create a progress bar that will show what file is currently being scanned. This will be most useful whenever you are running this script against a directory with numerous files and sub-directories.

Write-Progress -Activity "Scanning Files..." `
$_

The first search we will perform against the current file (via the loop) is to determine if the specified search string is contained within the contents of said file. If so, then the current file's path and filename will be added to the output file (specified in the script's parameters).

If (Get-Content $_.FullName | Select-String -Pattern $Text)
{
        Add-Content -path $Output -value $_.FullName
}

Next, we will scan the current file's filename and determine if the specified search string resides within it. For example, if you are running this script to search for the string "password," it will not only provide you with files that contain the string "password" within their contents, but also any files with "password" in their filename (e.g. MySecretPasswords.txt).

$WildCardText = "*" + $Text + "*"
If ($_.FullName -like $WildCardText)
{
       Add-Content -path $Output -value $_.FullName
}

When this script is all together, it will be the following.

#SearchForString $Directory $Text $Output
#Example:
#SearchForString "\\FileServer\Accounting" "password" "C:\PasswordFiles.txt"


#Define Parameters
[CmdletBinding()]
Param (
    [Parameter(Mandatory=$True,Position=0)]
    [string]$Directory,

    [Parameter(Mandatory=$True,Position=1)]
    [string]$Text,

    [Parameter(Position=2)]
    [string]$Output
)


#Define File Extensions to Audit
$Extensions=@("TXT","XLS","CSV","DOC","RTF")


#Loop through each Extension in our $Extensions Array
ForEach ($Extension in $Extensions) {
    $File = "*." + $Extension

    #Get all files in $Directory
    Get-ChildItem $Directory -Filter $File -Recurse -Force |
            
            #Loop through all files
            ForEach-Object {
                #Write our scan's progress to the progress bar (what file we're currently on)
                Write-Progress -Activity "Scanning Files..." `
                $_

                #If content of file contains $Text, write to $Output file
                If (Get-Content $_.FullName | Select-String -Pattern $Text)
                {
                Add-Content -path $Output -value $_.FullName
                }

                #If filename contains $Text, write to $Output file as well
                $WildCardText = "*" + $Text + "*"
                If ($_.FullName -like $WildCardText)
                {
                    Add-Content -path $Output -value $_.FullName
                }
            }
}

Running this script is very simple, as we have specified parameters which we can utilize in order to avoid having to modify the original PowerShell script each time we wish to run it. The following screenshot shows an example of what the command for running this script might look like.

Example of script execution.

As the script is being executed, you should see a progress bar that will display what file is currently being scanned.

The script's progress bar in action.

Once the script has finished, you should have all of your results stored within the specified output file. The contents of which might look like the following.

The results of your scan.

0 comments:

Post a Comment

Subscribe to RSS Feed Follow me on Twitter!