blog < /dev/random

Jeff McJunkin's thoughts on Penetration Testing, Systems Administration, and Network Defense

Category: Passwords

Step-by-step Implementation of Local Administrator Password Randomization Script

Since the documentation was a bit sparse on my script in my previous post, I thought I’d post clearer instructions, for those not as familiar with Group Policy. This post is going live with my guest Tech Segment on PaulDotCom today.


For this implementation guide, I assume you have an Active Directory domain and several clients to manage. You’ll also need to do your work from a machine with Group Policy Editor, and either the correct delegated permissions or Domain Admin privileges. If there are any instructions that are unclear, leave a comment and I’ll update the post.

1. Download script

Please download the randomize-local-admin.vbs script from my GitHub (right-click, Save Link As…) and save it your Desktop or another accessible location. You’ll need this shortly.

2. Create the Group Policy Object

Open up Group Policy Management Console, browse to the Group Policy Objects folder, then right-click on it and create a new Group Policy Object.

Name it something recognizable such as “Local Administrator Password Randomization”, then right-click and Edit it.

Now browse to Computer Configuration -> Policies -> Windows Settings and double-click on Startup. This is where we’ll set the script to run on boot.

Once the new window pops up, click Show Files to open the GPO’s directory and copy the VBScript (randomize-local-admin.vbs) inside. Make sure it has the right extension, or Windows won’t recognize it as a VBScript.

Now add the script to the Group Policy Object by clicking Add and selecting the script.

3. Create the WMI Filter (optional)

The intent of this script is to randomize local Administrator accounts on desktops and member servers, but domain controllers don’t have local accounts. So as to not randomize the builtin Domain Admin account, we’ll need to exclude DC’s, either via the Organization Units (OU’s) we target or by WMI Filters. If your Active Directory OU structure isn’t built with separate areas for Domain Controllers, or you want to link the entire domain, we can use a WMI Filter to exclude all machines classified as DC’s.

Under WMI Filters, right-click and click New. Right a name and description (“Exclude Domain Controllers” seems reasonable) and then click Add. You’ll need the following WMI Filter:

select * from Win32_OperatingSystem where ProductType <> “2”

4. Link the GPO to the proper OU’s

Now that we’ve created the GPO and its WMI Filter, we can link it to an Organizational Unit. First, though, you’ll need to associate the WMI filter if you created one. After clicking on the Group Policy Object, select the WMI filter from the lower side of the right pane, under WMI Filtering.

Right-click an existing OU which has systems you’d like to target and click “Link an Existing GPO…”. Select the GPO you just created, and it will take effect on the next reboot on all Computer objects in that OU. You can select other OU’s in the same way.

To make an acceptable level of overkill, this script creates 120-character passwords using the full ASCII character set (1-255).

Again, if you have any issues feel free to leave a comment or send me an email.

Creating a Network Boot Menu including Kon-Boot to Bypass Local Authentication

In a former post I referred to Kon-Boot, but didn’t go into much detail. Here, I’ll expand on my use of Kon-Boot and how to set it up for your own network. Specifically, to keep things as easy as possible I add it to my PXE menu, so that you’re simply a reboot and a few keystrokes away from logging on to an otherwise locked machine.

What is Kon-Boot?

Kon-Boot is a bootable shim which bypasses local account authentication on Windows machines. In other words, by booting into Kon-Boot (via floppy, CD, or over the network via PXE) you can bypass local passwords, such as for the built-in Administrator account.

As an aside, note that it cannot bypass domain authentication. This makes sense, as domain-joined machines contact domain controllers for domain user accounts, unless the client machine is offline and has cached credentials.

Kon-Boot is the reason I randomize the local Administrator password without disabling the account. For whatever reason, the author of Kon-Boot didn’t bypass enabled/disabled checks on local accounts, just their passwords.

Creating a PXE Boot Server

I’ll assume you already have a DHCP server on your network. The FOG Project, which I heartily recommend for anyone looking for a free Ghost replacement, has a wonderful page on setting DHCP options for many types of DHCP servers. The same options will apply for us — option 066 (“Next Server”) will be the IP address of the PXE server, and option 067 (“Boot File”) will be “pxelinux.0”. In fact, if FOG itself is interesting, they have great setup guides that will get a FOG menu installed on Ubuntu, to which you can simply add Kon-Boot as an additional option.

Next, you’ll need a trivial file transfer protocol (TFTP) server. For this tutorial, I’ll go through the setup of tftpd-hpa and syslinux on Ubuntu 12.04 Server. I’d recommend making this machine a VM, as the resources required are laughably low. I won’t, however, go into the installation of Ubuntu Server, as there are plenty of fantastic guides for that piece already. If you use the previous link, keep track of the IP address you statically assigned, or make a static DHCP reservation for the PXE server.

Once you’re logged in, there’s a few pieces of software to install.

apt-get install tftpd-hpa syslinux vim-nox openssh-server

This will install the TFTP server, syslinux (think of it as GRUB for PXE), a minimal version of vim to edit text files, and an SSH server. We’ll also need to create the directory structure and copy over some of the syslinux files to the TFTP root directory.

mkdir /var/lib/tftpboot/pxelinux.cfg

cp /usr/lib/syslinux/memdisk /var/lib/tftpboot # used to boot a floppy image

cp /usr/lib/syslinux/pxelinux.0 /var/lib/tftpboot # the PXE boot file

cp /usr/lib/syslinux/vesamenu.c32 /var/lib/tftpboot # for the PXE menu

You’ll also have a choice between setting a root password and a fair number of sudo commands. For the purposes of this post, I’ll recommend setting a strong password (as an example, this password generator site is xkcd-approved!) for root.

sudo passwd # Enter your user password, then enter a strong password for root, twice

Next, we’ll install the free version of Kon-Boot. Earlier this year, the author came out with a new paid version, but maintained the original version for free download. The major restriction is the free version (v1.1) doesn’t support 64-bit Windows systems, while the paid version (v2.0) does. Go to the Kon-Boot download page, download from the first mirror, and save the zip locally. Inside you’ll find (password is “kon-boot”), and in that you’ll find FD0-konboot-v1.1-2in1.img. Save it to another location locally, such as your desktop.

If you don’t already have it installed, you’ll also need a program to copy the Kon-Boot floppy image over to the PXE server. I recommend installing WinSCP (skip the “sponsored” version if you prefer) for those on a Windows platform.

Use your PXE server’s address instead

Copy the FD0-konboot-v1.1-2in1.img file to the /var/lib/tftpboot directory.

Now you’ll need to write the pxelinux configuration file at /var/lib/tftpboot/pxelinux.cfg/default. You can either use the command below, or a text editor like vim or nano to write the text below:

echo -n ”

prompt 0
DEFAULT vesamenu.c32
timeout 50

label local
localboot 0
MENU LABEL Boot from hard disk
Boot from the local hard drive.
If you are unsure, select this option.

label Kon-Boot
kernel memdisk
append initrd=FD0-konboot-v1.1-2in1.img
MENU LABEL Kon-Boot Floppy Image
Kon-Boot will bypass local authentication for
local administrative purposes.

” > /var/lib/tftpboot/pxelinux.cfg/default

If you’ve set up your DHCP server options as mentioned before, you should now be able to boot a client to the network and see the menu we’ve created. You may have to press a specific key during boot or change your BIOS options. For VMware virtual machines, pressing F12 during boot attempts a PXE boot.

Booting into Kon-Boot will take a few moments showing a fancy startup image, and then boot into Windows.

Kon-Boot Startup

Screenshot from paid version (v2.0)

Now that you’re inside Windows, you can log in as the local Administrator account (or any other local account) without worrying about the password. You can leave the password field blank, or type in any particular password you want. It makes no difference, as the password check is more-or-less replaced with “return true”. Whereas before you’d see this:

Failed Login

Now you’ll be able to log on and take any actions you wish.

Successful Login

What do you think? As I don’t have need for remote access to computers without using domain privileges, I see this as a useful way to log in to infected or suspicious machines locally. In terms of return on investment, I’ve been extremely happy with further customizing my PXE boot menu with SpinRite (drive recovery), Recovery is Possible (live Linux over PXE!), and even Memtest86+.

What to do with the local Administrator account?

After my last post with the local Administrator randomization script got some attention from John Strand (@strandjs), Tim Medin (@timmedin), and Tim Tomes (@LaNMaSteR53), I realized the issue what to do with local Administrator accounts was considerably more complicated. Here’s my attempt to map out the different possibilities.

As background, be sure you know that resetting a local Administrator (or bypassing it entirely) is trivial given physical access to a machine (via NT Password Reset, Kon-Boot, or similar utilities). Offline registry attacks assume there’s no drive encryption in place. The two types of attackers I’m assuming below are external (as in a penetration tester or malicious hacker) and internal, as in employees or contractors. I assume the external attackers don’t have physical access to each machine in the domain, as that would defeat any of the recommendations below.

In order of least to most secure, here are the basic options I see:

  1. Standardized local Administrator password on all domain-joined machines. While convenient, this is a horrible idea security-wise. Brief physical access to any domain-joined machine to acquire the hashes gives Administrator access to all machines in the domain via passing the hash. Though this is exactly what I’m trying to combat, it’s a likely situation in many shops. Some will mitigate this slightly by having a different desktop password than the server login, but that doesn’t help for long. At some point, a Domain Administrator will be logged on to a desktop, and stealing his/her token will result in Domain Admin privileges. Please, please don’t choose this option.
  2. Standardized on a local Administrator password, but also set SeDenyNetworkLogonRight on that account. Make sure to still set a reasonable length (15+ characters) password on that account. In this situation, any employee who was told this password (say, a remote laptop user) could then abuse that privilege on any machine he/she can get physical access to until the password is changed. I’ve been to many places where the local Administrator “break-glass” password is fairly common knowledge among end users. I urge you to not choose this option, either.
  3. Individualized (not randomized) local Administrator passwords. Set SeDenyNetworkLogonRight for the local Administrator as in #2, but also include individual passwords for each machine. This prevents a single password having rights throughout the domain, but adds complexity. I don’t know of any shops going this route, but it seems reasonable.
  4. Randomized local Administrator passwords. Setting SeDenyNetworkLogonRight should be unnecessary, but is a harmless additional precaution. This was the focus of my previous blog article. In order to use the account at this point, you’ll need to either reset the password using NT Password Reset (or similar), or bypass it entirely using Kon-Boot. Do note that this is the same method an attacker would use to get local Administrator privileges. Disabling the account is optional, but precludes Kon-Boot (which bypasses the password, but respects whether or not an account is enabled). The biggest downside I’ve experienced thus far is the lack of a way to help a remote (i.e., not domain-connected) user who needs administrative access to their machine.

Do you need to access machines remotely using the local Administrator account? Since we’re discussing domain-joined Windows machines, the use cases for this requirement are small. The two situations I see this need are machines that aren’t connected to the domain (assuming Domain Admin credentials aren’t cached, which is a topic for a different blog post), and accessing machines that are infected or untrusted (as the domain token could be stolen and re-used elsewhere).

If so, be careful! This is where most people get into trouble. Standardizing on a local Administrator password means that anyone with brief physical access to any one of those machines can use those same credentials (without cracking the password hash, even) on all machines in the network. If this is both scary and new information, look up “Pass the Hash” attacks.

If you’re still sure you need remote access to machines using the local Administrator accounts, you’ll need to ensure the same password isn’t used across all machines in your domain. In other words, we’ll need to make those passwords individualized to each machine. These individualized passwords can be created using the output of a hashing algorithm seeded with some unique identifier of the machine together with a secret padding. If we can guarantee the padding isn’t disclosed, we’ll have a fairly secure password. The output of the SHA-1 algorithm is 160 bits, expressed as 40 hexadecimal characters. Plugging that output into Jason Fossen’s password complexity spreadsheet gives us an output of 1,157,804,805,602.22 years to crack an average password of that length directly, with 1,000 machines each generating 200,000 hashes per second. Needless to say, an attacker would be far better off trying to discover the method used to create the passwords (including the secret padding) than to attack each password individually.

The biggest concern for individualized passwords is setting them. My preferred approach, Group Policy, would show the secret padding, as it would have to be in the script. Accordingly, we’ll need to push out the individualized passwords from a trusted computer, setting the passwords on each remote machine. Unless I get requests otherwise, I’ll leave the actual individualized password script as an exercise for the reader.

Randomizing the Local Administrator Account Password

UPDATE: Upon further discussion with information security professionals, I’ve expanded on the subject of local Administrator accounts here.

As systems administrators, we sometimes need access to a given machine without domain credentials. But, in all honesty, how often do we really need access in this fashion? In a proper environment Most of the rationale behind “standardizing” on a local Administrator password I’ve seen has been to support other bad practices, like giving out the password to end-users to solve a one-time or letting service accounts run as a named user.

Below I’ve included a sample VBScript to randomize the local Administrator password. If you don’t use the local account in any day-to-day work, you may as well not leave this gaping security hole out there. Try placing this script in a Group Policy machine startup script. Just copy-paste the full code into a new Notepad instance, click save, then put “password.vbs” INCLUDING quotes into the path. This is necessary to retain the non-default extension (as otherwise Notepad puts the standard .txt extension on the file). Remember the path, then add it to an existing Group Policy Object or create a new one. Once you’ve opened the GPO, the full path is Computer Configuration -> Policies -> Windows Settings -> Scripts -> Startup. Click Add, Browse, point to the script, and press OK on the two screens. Close the GPO, apply it to a test OU, and you’re well on your way! If you have any issues you can always back out of the changes.

' A simple script used to randomize the local Administrator account password
' and disable/enable the account
' Written by Jeff McJunkin (@jeffmcjunkin,
' May be reused without permission, as long as the original source is attributed

Set WshNetwork = WScript.CreateObject("WScript.Network")
strComputer = WshNetwork.ComputerName

strComputer = "."
Set objUser = GetObject("WinNT://" & strComputer & "/Administrator,user")

intHighNumber = 255
intLowNumber = 1


For i= 1 to 120
	intNumber = Int((intHighNumber - intLowNumber + 1) * Rnd + intLowNumber)
	password = password & Chr(intNumber)

objUser.SetPassword password

' If you use something like Kon-Boot instead of NT Password Reset,
' it can be useful to leave the account enabled. In that case,
' set the following line to False

objUser.AccountDisabled = True