Microsoft introduced a handy security cmdlet in PowerShell 4;
the
Get-FileHash cmdlet is very useful for validating the integrity of a file
provided you know the hash value of the ‘known good’ version. A hash is
essentially a sequence numbers and letters that are calculated using a function,
such as SHA256 or SHA384 using (in this case) a file as input.
As an example, let’s say that I build a software
application, widget.exe. I run the SHA384 hashing function on it and come up
with 38A519CE7. (A real value would be much longer.) If even a single bit
changes in widget.exe, the hash value would change the next time the was
calculated. I post my widget.exe program on my web site and I also include a
note saying that the SHA384 has is 38A519CE7.
Assuming you trust me as a source for software, you download
my program and compute the hash value of widget.exe using the SHA384 algorithm.
If the value you calculated is not 38A519CE7, then something is amiss. Maybe I
posted a new build of widget.exe and did not update the new hash value. Maybe
it was corrupted during download. Or, maybe someone modified my program and
included hostile code.
Calculating a hash value and checking it against a
known-good value is a simple, easy way to verify the integrity of a file,
whether the file is a simple text file, spreadsheet, script, executable, or
binary. By themselves, security experts will tell you that they are not a 100% perfectly
secure solution. After all, if I can modify your software, I can also try and
find where you keep your ‘known good’ hashes, recalculate the hash value, and
modify your list of known good hashes.
Is the Get-FileHash command available to you? Using the
$PSVersionTable variable in PowerShell and make sure you are running at least
v4.0. A word of caution, though, you may have scripts written that will only
work with earlier versions of PowerShell, so do your homework before updating
to new versions of PowerShell.
Let’s go through an example. I have a file in the c:\temp
folder called Get-IthicosSystemInfo.PS1. I want be able to detect if changes
have occurred that I did not make. I’m going to use the SHA384 hash algorithm
since it is a newer, modern, and more secure algorithm. If you do not specify
the -algorithm option, then Get-FileHash will use SHA256. If the file hash will
be calculated on other operating system platforms, make sure that the other
platforms support the hash you will choose. I would type this command at the
PowerShell command prompt:
Get-FileHash .\Get-IthicosSystemInfo.ps1 -Algorithm sha384
The Get-FileHash cmdlet will return the hash algorithm used,
hash calculated, and the file path. The hash value is actually too wide, so I’ll
do a little bit of PowerShell magic to set the hash information as a variable:
$filehash = Get-FileHash .\Get-IthicosSystemInfo.ps1
-Algorithm sha384
Then I can just type $filehash.hash, like so:
PS C:\temp> $filehash.hash
6D5F36A23562A304C8FFFFB5E4B0F829C64DDABD61ADEFE938BD25C250362CEA8C3352A6360457FFAA1BD594D7CE852E
Awesome! I’m almost done. Now, I’ll take that hash code,
copy it and paste it in to a JimsHashCodeKnownGoodValues.txt file and save it
to the C:\temp folder with the script. Hurray! My script is protected and I can
sleep well at night.
Some of you are probably saying to yourself, “Self, if an
intruder can get to the temp folder and modify the script, well, the ‘known-good’
values file is right there next to the script...” You would be correct. I
should store my known-good hash values in a different place. Of course, I need
to apply restrictive NTFS permissions on to my script so that only a small
group of trusted admins can edit it. And, if the script is edited, a new hash
value needs to be calculated.
At some point in the future, if I want to validate that they
script has not been modified, I’ll simply run the Get-FileHash command again
using the same hashing algorithm. If the hash value is the same, the file has
not been modified.
Using hashes to verify file integrity should never be the
only security tool in your arsenal but they can provide you with an additional
layer of security for validating file integrity. In another article, I’ll
discuss digitally signing code and how that can provide you with a higher level
of assurance.
Labels: PowerShell, scripting, security