Wednesday, December 17, 2008

Windows Password Security - Part 1

What makes a secure password? How does Windows handle passwords? What points in this process are vulnerable? You would be surprised at the number of IT professionals who couldn't answer these kinds of questions. No matter what kind of security and monitoring your IT department has gone through the trouble of setting up, compromising the password system can bypass all of it. In many situations, an attack against an organization's password system can be completely undetectable.

In the first article of this series, we will take a look at the basics of password security as well as a few basic methods of attack. In the second article, we will focus on how Windows handles passwords and methods of attacking that process.



What makes a password secure?
  • The longer the password is the more secure it is
The first line of security for hacker attempting to guess a password is the sheer number of possible combinations. And just how many possible combinations is that? For our hypothetical case, we're going to simplify the math a bit. If we know the precise number of characters in the password then the formula looks like this:

(Number of possible characters) ^ (Length of the password)

Let's say our hypothetical password is made up of only uppercase letters and can be only one letter long. That gives us 26^1 or 26 possible password combinations. That wouldn't take us too long to guess. Now what if we allowed passwords with exactly three characters? That would leave us with 26^3 or 17,576 possible password combinations. Simply by forcing our users to remember 2 additional letters we increased the number of passwords our attacker would have to guess by a factor of 676! The lesson here is longer passwords are exponentially stronger passwords.

  • The more types of characters in a password the more secure it is
Okay, let's go back to our one character length passwords. This time, instead of just uppercase letters we are going to allow uppercase letters, lowercase letters, and numbers. That gives us 62^1 or 62 possible password combinations. Now what happens if we throw in a non-alphanumeric symbol into our password? That gives us 94^1 or 94 possible password combinations. Now let's go back to the 3 character long password example above and this time we're going to allow users to add non-alphanumeric symbols into their passwords. That gives us 94^3 or 830,584 possible password combinations. Adding as many types of characters into your passwords as possible makes them much harder to crack.

  • The more random a password is the more secure it is
Up until now, we've assumed the only way for an attacker to break a password is simply to try every possible combination of characters until they correctly guess the password. In reality, users have a difficult time remembering random passwords so they use common words in very predictable patterns. I would bet that at least half the users in your organnization use passwords in the form of [Dicationary Word][1 to 4 digit number]. Every time they are forced to change their password they simply increment the number and leave the rest of the password unchanged. This means that breaking a user's current or previous passwords could leave you a handfull of guesses away from breaking their future passwords after a forced password change.

Even the least sophisticated attacker is likely to try this avenue of attack first. The web is full of lists of word lists specifically geared towards breaking passwords. Many of the freely available password cracking programs are capible of taking in a list of dictionary words and trying permutations of each word until a password is cracked. Simply changing the letter case (PaSSwOrD instead of password) or adding numbers and symbols in the place of letters (p@ssw0rd instead of password) is no longer sufficient to stop an attack.

One possible defense is to urge your users to use passphrases instead of passwords. A password of, "My cat hates car rides!" is very difficult to crack using traditional methods. I would, however, caution your users to not use a passphrase that could easily be guessed by people that know them well. Also, avoid commonly used phrases.

  • The more secret a password is the more secure it is
You would think this point is pretty obvious, but you would be surprised at how many users write down their passwords on post-it notes, give them to colleagues, or give them to IT staff over the phone. Passwords should be known by only the user to which they belong. In the ideal situation, even IT staff would not know a user's password. This is as much for the safety of the IT staff as it is for password security. While IT staff have the ability to reset a user's password for administrative reasons, this leaves a log trail. In the event a user's account is compromised, the logs can prove the innocence of the IT staff. This is not possible when users provide their password to others.



Enforcing password policies

Wherever possible, you should enforce your company's password policies with technical controls. Where that is not possible you should set up a training program to make users aware of the policies, periodically audit compliance with those policies, and enforce consequences for breaking those policies. Active directory provides settings that control minimum password length as well as ensuring passwords meet a minimum complexity requirement. Unfortunately, active directory does not provide a means of ensuring passwords are not vulnerable to a dictionary based attack. There are several products that add this functionality if your organizations security needs warrant the expense. Ensuring that your users do not write down or share passwords requires constant user training, reminders, and most importantly support from management.

Saturday, June 21, 2008

Using PowerShell to Retrieve PSTs

Practically every company is going to be involved in a law suit at some point or another. As an IT professional, it's usually our job to help comply with an order to produce copies of email when our company gets sued. In a perfect world, all your employee's email resides in one place and can easily be exported and produced. Back on Earth, employees store their email in a multitude of locations (Exchange servers, local PST files, network PST files, blackberries, etc.) forcing you to exhaustively search all of them for email. Such was the case with my company last month when we received a list of forty or so employees who's email had to be produced. Archiving email from an exchange mailbox is a pretty easy task and doesn't require the employee's cooperation. Archiving PSTs stored on laptops, desktops, and network storage locations is another matter all together. To make the process easier, I decided to write a PowerShell script to automate as much of the process as possible.

Since all I had to start with was a list of employee names, I decided to store all my employee names and search locations in a CSV file. Each line in the CSV file would have the employee's name, their user name, their computer's admin share path, their home folder path, and finally their profile path. A sample CSV might look like this:

"Name", "UserName", "Computer", "Home", "Profile"
"John Doe", "JDoe", "\\Desktop-JDoe\c$", "\\FileServer\Home\JDoe", "FileServer\Profile\JDoe"

Once we create our CSV, we can import it into a PowerShell CSV object. The import looks like this:


Now that we have all of our users and all the network locations we need to search saved into a usable format, we can start writing our PowerShell script. The script itself simply takes in a network location, recursively scans that location for any PST files, adds them to a list, and then attempts to copy those files to a local directory named for the user. If the copy fails, if the PST is locked because that user has Outlook open, or if a search path is unavailable because a user has turned their computer off, then we want to write the skipped PSTs and unavailable search paths to a text file so we can manually track them down later. The quick and dirty version of my script looked like this:
#movePST.ps1
param( $userName, $searchPath, $errorLog )

function copyPST ( $sourcePST ) {
if(!$sourcePST.exists){ $sourcePST.fullname | Out-File $errorLog -Append; return $null }
$error.clear()
Write-Host "Copying " $sourcePST.fullname
Copy-Item -Path $sourcePST.fullname -Destination ($objDestination.fullname + "\" + $counter + $sourcePST.name) -Force
if($error -ne $null){ $sourcePST.fullname | Out-File $errorLog -Append; $error.clear(); return $null }
}

#Check inputs and look for errors
if(!$userName -or !$searchPath -or !$errorLog) {Write-Host "Missing input"; return $null}
$objDestination = get-item ("C:\PSTs\" + $userName)
if(!$objDestination.exists) {Write-Host "Destination folder has not been created: " $objDestination; return $null}
$counter = 1

#record invalid / unreachable search paths
$objSearchPath = Get-Item $searchPath -ErrorAction SilentlyContinue
if($objSearchPath -eq $null){ $SearchPath.toString() | Out-File $errorLog -Append; return $null }

#Look for PSTs and store them in an array
Write-Host "Searching" $userName
$arrayPSTs = Get-ChildItem $objSearchPath -Recurse -Force -Include *.pst -ErrorAction SilentlyContinue
foreach($objPST in $arrayPSTs) {
copyPST($objPST)
$counter += 1
}

The first function actually copies the PST once it's identified. In some situations, the user might have multiple PSTs on their computer with the same name. To solve this, we create a counter, add that number to the beginning of each PST's file name, and increment the counter with each PST we found. If the PST copy fails, the name of the PST is appended to our error log.

The main block of code first does some basic testing of inputs to make sure everything is correctly specified. Once that's taken care of, the script checks the search path. If the path is unavailable (maybe because the user turned off their computer when they weren't supposed t0), then we append that search path to our error log and move on. The last little block of code recursively searches through the search path and sends every PST file to the copyPST funtion to be archived.

Now that we have our script and our CSV containing all our locations, it's time to actually perform the search. Since the script cannot copy PST files that are open inside Outlook, we had to make sure that everyone went home with their computers turned on and Outlook closed. Then we're all ready to start the scan. This example code would search through every entry in our CSV and search each person's computer for PSTs:

foreach ($user in $csv) {./movePSTs.ps1 -userName $user.Name -searchPath $user.Computer -errorLog ./error.txt}

To search the profile and home paths, you would run the same code but substitute $user.Home and $user.Profile for the $user.Computer parameter. If all goes well, you wind up with a folder containing all the CSVs organized by name. Any errors show up in the error.txt file and can be archived later.

One final note: Depending on the industry you're in, your company may have to frequently produce emails. If this might be a possibility, make sure you take that into account when you come up with IT policies regarding email and PSTs. You should also spend some more time figuring out the best ways to archive email and which of those steps you can automate with PowerShell. The last piece of the puzzle is training your users on what to expect when you perform an email archive. Their cooperation makes the process much easier. Happy litigating!

Saturday, June 14, 2008

Setting up a DMZ in ESX 3.5

One of the strongest selling points for using ESX as a lab environment is the ability to quickly create and modify network configurations to replicate practically any network layout you wish. What would take a few hours in a lab running network cable and configuring switches and routers can be done inside ESX with a few clicks of the mouse. For today's post, I will walk you through the basic steps of creating a DMZ inside your ESX server. Since this is a lab environment only, our focus will be on creating a functioning DMZ rather than worrying about security.

The first step, as in any network setup, is planning. I know I generally like to dive right into any new project and start creating, but this is one instance where a few minutes of planning will save you hours of headaches later down the line. I use the same spreadsheet to track IP address assignments in my lab environment that I use in my production environment. Write down each IP address range you plan on using and it's specific use and method of assignment (static or DHCP). I generally allocate the first 10 IP addresses to routers, switches, and other networking devices. I reserve addresses 10-30 for statically assigned servers. I usually create a DHCP zone that assigns the 100-200 address range. Lastly, I reserve 90-99 for any special devices that I have statically assigned via DHCP lease reservations. The result should look something like this:


On a separate sheet, record any statically assigned IP addresses, the host they belong to, and any notes that might be helpful. This makes it easy to tell at a glance which static IP addresses are free when you start adding servers. Make sure you and anyone else making changes to your lab environment keep the worksheet updated. All this planning may seem like overkill at first, but your test lab can quickly become too complicated to keep everything in your head.



Now that we have a blueprint for our DMZ, we're ready to decide what devices we need. A physical DMZ requires at least some network cables, a router, a switch, and a server to access. Our virtual DMZ will have the same components. ESX will provide our virtual switch as well as handling any cabling that needs to be done. You have a couple of choices when it comes to the router you wish to use. A Windows Server 2003 virtual machine set up with the routing and remote access service will suffice for the most basic routing needs. My personal preference is the Astaro Security Gateway appliance available from Astaro. They offer a free personal use license that supports up to ten clients. The ease of use and the list of features is pretty astounding for a free product. The specifics of installing the Astaro virtual appliance are beyond the scope of this article, but the download includes detailed instructions for installing the virtual appliance on ESX.

Now that we have a plan laid out for our virtual network and we have the router selected, it's time to start creating the switches and network connections inside ESX that will form our DMZ. Start up the VMware Infrastructure Client and log into your ESX machine. Highlight your ESX server on the left side of the screen and select the "Configuration" tab. You should be presented with your current ESX network layout that looks roughly like this:

If you're new to using virtualization, the network configuration can be a little confusing at first. ESX displays your virtual network setup so you can think of it just like a physical network. The left hand side shows all the virtual machines connected to your virtual network. The vertical grey bar represents the virtual network switch connecting all those virtual machines together. The right hand side shows any physical adapters that allow your virtual network to connect to outside networks. As you can see in our current configuration, I have virtual network called LAN with a half dozen virtual machines connected. The LAN network has a single physical network card attached to allow those virtual machines access to the outside world. For our purposes, we will assume that your initial network looks similar to mine and that the virtual machines in your existing virtual network can access the internet.

Now we're going to create the virtual network for our DMZ. Click on the "Add Networking" link. The next dialogue box asks you what type of network connection you wish to add. We want a new virtual switch to attach our virtual machines so we're going to select "Virtual Machine" and click "Next". The next dialogue box asks you whether you want to create a new virtual switch or connect to one of your current virtual switches. We'll leave the default "Create a virtual switch" option selected. ESX automatically adds any unassigned physical network adapters to your new switch. Make sure you clear any of the check boxes since our DMZ will only be connected to the outside network via our router. Take a look at the preview to be sure your new virtual network is set up the way you wish.


In the next dialogue box, give your new virtual network a name. We'll call ours DMZ. Leave the VLAN option blank and click "Next". We're now back at the configuration tab. Once ESX finishes creating our new virtual network, we should have something like this:

Our old LAN network is displayed on top with the newly created DMZ network just below it. We're almost finished. We've created the DMZ virtual network, but we still have to add our router and some virtual machines. The specific steps for installing your router depend on which type you selected. Regardless of what you decided to use as your router, you will need to make sure your router virtual machine has at least two virtual network cards. Your router will need at least one network adapter in the DMZ network and one network adapter that has access to the internet to function propertly. Once you finish installing your router, you can start adding virtual machines to your DMZ network. Once you add a virtual machine or two, go back to the configuration tab for your ESX server. If everything went to plan, you should see your router and the virtual machines you added under the DMZ virtual network.

One final note. We created this virtual DMZ with functionality instead of security in mind. The purpose of a true DMZ is to allow some of your servers greater access to the internet while keeping the rest of the network secure. This separation limits the damage in the event someone is able to breach one of the servers in your DMZ. In our virtual environment, our DMZ servers run on the same ESX hardware as the rest of our virtual servers so the same level of isolation is not created. This virtual DMZ is perfect for a lab environment, but further attention to security should be paid before using your virtual DMZ in any kind of production environment.

Wednesday, June 11, 2008

Remotely Launching Goto Assist with PsTools

Like many IT departments, remote assistance using Goto Assist or another similar product is a cornerstone of our support infrastructure. Goto Assist in particular is extremely versatile as it works through most firewalls and can be launched by sending the client an email containing a link or by having them go to a customized web page and typing in a code. Even with the various built-in options for initiating a remote assistance session with Goto Assist, I still find situations where it's more desirable to remotely launch a session without any user intervention at all. Assuming the client computer is a member of our domain and we can actively contact that computer over the network, you can accomplish this task using the PsExec command included with PsTools. If you haven't gotten familiar with the PsTools suite, I highly recommend you check them out. They are invaluable for managing remote workstations in a windows domain.

PsExec allows you to remotely execute a command on a domain member workstation. To launch the Goto Assist session, we're going to remotely launch internet explorer and tell it to open the URL associated with our Goto Assist session. Here's an example:

psexec \\ClientComputerName -u DOMAIN\User -i "C:\Program Files\Internet Explorer\iexplore.exe" http://www.google.com

Replace ClientComputerName with the name of the workstation you wish to connect to. If you're authenticating with a domain account, use the DOMAIN\User format for the -u switch. You can use a local account that exists on the client computer simply by using that name with the -u switch. This example launches Google's web site, but you can replace that URL with the link to your Goto Assist session. The -i switch forces the application to launch in interactive mode so the user can see the window.

There are a few security issues to keep in mind. You will want to ensure the user account you use to launch Internet Explorer has only the minimum permissions required since the IE process will run with all the permissions that user possesses. If, for example, we ran this command and input an account that had local administrative rights on the client computer, anything the client did with that IE window after we launched it would also have full administrative rights. We have a local user account on all our workstations I use to launch Goto Assist since it needs no special administrative permissions. We could also purposely launch IE using a local administrative account for the purposes of allowing the user to install a new ActiveX control. Just be sure to define your security policies for this procedure ahead of time and stick to them.

Monday, June 9, 2008

PowerShell Script to Compute Folder Sizes

I would like to preface this post with a disclaimer. While I have a few languages under my belt, I'm fairly new to PowerShell. Most of my posts on this topic will simply be scripts that I've created or modified for my own purposes. Feel free to use any of them for whatever purpose you choose.

I created this function as part of a larger script I'm writing that archives old users in Active Directory. I needed a way to report the profile size of the archived user and flag large profiles for closer inspection to save on disk space. This code is a modified version of a script I found on Z@RAYS. I'll talk more about the specific changes I made a bit later.

function folderSize ( [string] $folderPath )
{
if($folderPath)
{
#Initialize everything
$totalSize = 0
$folderRoot = Get-ChildItem $folderPath

#Total the subfolder sizes
foreach($folder in $folderRoot)
{
if($folder.mode -match "d")
{
#Retrieve the folder size and add it to the running total
$fsz=((Get-ChildItem $folder.fullname -Recurse -Force | Measure-Object length -sum).sum)
$totalSize = $totalSize + $fsz
}
}

#Add the size of items in the folder root
$filesize=(($folderRoot.fullname | Measure-Object length -Sum).sum)

#Convert to GB and format to 2 decimal places
$totalSize = ($totalSize + $filesize)/1GB
$totalSize = "{0:N2}" -f $totalSize
return $totalSize
}
}
The first section of code initializes our running total to zero and creates an object representing the root folder who's size we want. The second section recurses through each sub folder and adds the size of that sub folder to our running total. Now that we've got the sub folder size, the next section adds the size of any files that happen to be stored in our folder's root. The last section converts the total size to GB and truncates the result to two decimal places before returning the total size.

The primary change I made from the code found on Z@RAYS is in the rounding of our folder size. The original code formatted each sub folder's size into GB with two decimal places before adding it to the total. I found that in situations with large numbers of sub folders, this could introduce a significant rounding error. Saving the formatting for last eliminated that problem. I also wanted my result in GB instead of MB, but this code can easily be modified to return the result in any unit you choose.

Friday, June 6, 2008

Cheap VMware ESX Server - Part 2

The parts arrived from newegg this week. As with any computer assembly, the first step is to lay everything out and take an inventory to see if anything is missing. Here's the stack of parts laid out on the kitchen table.


The next step was to prepare the drawer with some ventilation. I decided to try a single 80mm intake fan mounted onto the back of the drawer with an intake hole cut through the thin cardboard on the back of the ikea cabinet. The fan is mounted on the back of the drawer so it sticks out through the back of the cabinet when the drawer is closed. This ensures you are drawing in cold outside air. I held the fan to the back of the drawer and used a pencil to mark the screw locations and the air hole. A dremel with the drill and routing tools worked fairly well to finish the wood working. Here's a few pictures of the finished drawer with the 80mm fan mounted in back.


Now comes the fun part; putting everything together. I tried to keep the heat-producing components along a straight line between the front of the drawer, which I plan to leave cracked for heat exhaust, and the intake fan at the rear of the cabinet to provide optimum air flow. I added a temporary CD-ROM for the OS installation. While the motherboard has onboard SATA ports, you will need to be sure to connect your hard drives to the SAS ports or the ESX installer won't be able to locate the disks.


Once everything is in place, temporarily connect a VGA cable and a keyboard for the initial setup. Unless you have a power button to use, carefully use a screwdriver to short the two power pins on the front panel to power on the server. I like to boot into BIOS first to give everything a quick look over and change any settings. At a minimum, ensure the motherboard correctly identifies your processor type and memory quantity. If not, you may need to flash the BIOS. I also set the BIOS to default to power on after a power loss. This means if the power goes out for some reason, the system will start right back up. Now is also a good time to set the temp and fan speed warnings so your server won't overheat and damage itself inside the drawer. Once everything in BIOS checks out, boot to the SAS RAID manager and create your array. Be sure to make it bootable. Boot to the ESX installation CD and verify the installer can see the local drive.

Now that ESX is installed, your lab server is ready to go!

On a final note, the single intake fan wasn't enough to keep the drawer cool. I noticed that the intake fan wasn't running at full speed while connected to the motherboard, so I attached it directly to the power supply using an adapter. This helped a little, but still not enough as the ambient temp inside the drawer was peaking at 110 F under idle conditions. In the mean time, I'm going to run the server with the drawer cracked a few inches. I'm hoping to add another fan this weekend to solve the problem.

Cheap VMware ESX Server - Part 1

Sunday, June 1, 2008

Cheap VMware ESX Server

With the release of VMware's ESX 3.5, a very cheap but extremely powerful test server can be had for around a thousand dollars. I was in need of an ESX server to host at least 8-10 virtual servers as a training tool for my MCSE exams. Having been inspired by an article on building a linux cluster in an Ikea Helmer cabinet, I decided to build my server into an Ikea Malm cabinet.

The most difficult item to find is going to be the motherboard. ESX 3.5 only supports SATA hard disks on controllers that also support SAS drives. Newegg only had a few boards to choose from and they're all in the $300 - $400 range. I went with the quad core instead of a dual core because the price difference was fairly insignificant. As with most virtual hosts, the physical memory decides how many virtual machines you can host. I needed at least 8-10 VMs, so I maxed out the motherboard with 8GB of RAM. The pair of SATA disks allows for a RAID 1 configuration. This isn't strictly necessary for a lab environment, but it doesn't hurt. If you wanted to cut some costs on the hardware, select a dual core processor, only buy 4GB of RAM, and ditch one of the hard disks. Here's the shopping list from Newegg:

Asus P5BV-E/SAS Motherboard $310
G.Skill 4GB (2x2GB) DDR2 Memory (x2) $170
Apevia 500W Power Supply $40
Western Digital 500GB SATA2 Hard Disk (x2) $110
Intel Xeon X3220 Quad Core 2.4GHz $235

That brings the hardware total to $1145 excluding shipping. The Malm cabinet ran me another $80. Ikea had plenty of other cheaper cabinets that would fit the bill, but this one better matched my room's decor. Either way, it's a lot cheaper than a server case and it has room for my socks. I will post more details and some pics once I get the server up and running.

Cheap VMware ESX Server - Part 2