Cracking WatchGuard passwords
Watchguard Firewall appliances offer the ability to manage policies per user. Several mechanisms can be used to authenticate users (Active Directory, LDAP, Radius, ..) including a local database called “Firebox database” (Firebox-DB). Based on the XML configuration file of the appliance (which includes the Firebox-DB accounts), I recently needed to evaluate the passwords strength defined by a customer. Unfortunately, the firebox passwords appeared to be encrypted or hashed and I couldn’t find any information about the algorithm used.
Sample hash
Hereunder is an excerpt of the XML configuration file, showing the definition of the user “john“. The password was set to “readwrite“, a deliberately simple choice for testing purposes.
<account> <id>john</id> <password>628427e87df42adc7e75d2dd5c14b170</password> <description/> <idle-timeout>1800</idle-timeout> <session-timeout>28800</session-timeout> [...SNIP...] </account>
The password protection algorithm
In order to find the protection algorithm, I finally extracted the wgagent binary file from the WatchGuard filesystem, then started to reverse engineer it. The hashing function was quickly located and was actually quite easy:
loc_8059031: mov eax, [ebp+var_C] mov [esp+8], eax mov eax, [ebp+arg_0] mov [esp+4], eax lea eax, [ebp+var_10E] mov [esp], eax call mysub_8058F91_to_utf16 shl [ebp+var_C], 1 mov eax, [ebp+var_C] mov [ebp+eax*2+var_10E], 0 mov edx, [ebp+var_C] lea eax, [ebp+var_10E] mov ecx, [ebp+arg_4] mov [esp+8], ecx mov [esp+4], edx mov [esp], eax call _MD4 add esp, 134h pop ebx pop ebp retn
The function simply converts the password to UTF-16 (in this case means: insert a null byte after each character of the password), and then sends it to the MD4() digest function.
Quick & dirty reproduction
(Monkey see monkey do…)
$ echo -n 'readwrite' | \ perl -e '$str=<STDIN>; for($i=0;$i<length($str);$i++) { \ print substr($str,$i,1) . "\x00"; \ }' | openssl dgst -md4 (stdin)= 628427e87df42adc7e75d2dd5c14b170
Now using oclHashcat
So far so good, we know the algorithm. The remaining question is, how to ask oclHashcat to manage the null byte insertions ?
After some discussion on #hashcat IRC channel, trying to explain that I needed to add a null byte after each character of the candidate password and to use MD4 algorithm, sir Hashcat him-self opened my mind:
<atom> aka unicode ? <st3n> yes :) <atom> which -m <st3n> MD4 <atom> then use -m 1000 <atom> NTLM <atom> its unicode version of md4 <st3n> OMG <atom> you're joking <st3n> LOL. So sorry :) I didn't realize that :) <atom> hehe <atom> np, have fun <st3n> cool, it works very well :) <atom> :)
Thank you atom :-) worked like a charm !
$ ./oclHashcat-plus64.bin -m 1000 -n 160 -u 1024 628427e87df42adc7e75d2dd5c14b170 ../wordlist/rockyou.txt oclHashcat-plus v0.14 by atom starting... Hashes: 1 total, 1 unique salts, 1 unique digests Bitmaps: 8 bits, 256 entries, 0x000000ff mask, 1024 bytes Rules: 1 Workload: 1024 loops, 160 accel Watchdog: Temperature abort trigger set to 90c Watchdog: Temperature retain trigger set to 80c Device #1: Tahiti, 2048MB, 800Mhz, 28MCU Device #2: Tahiti, 2048MB, 800Mhz, 28MCU Device #1: Kernel ./kernels/4098/m1000_a0.Tahiti_1084.4_1084.4 (VM).kernel (675476 bytes) Device #2: Kernel ./kernels/4098/m1000_a0.Tahiti_1084.4_1084.4 (VM).kernel (675476 bytes) Generated dictionary stats for ../wordlist/rockyou.txt: 139921497 bytes, 14344391 words, 14100049 keyspace 628427e87df42adc7e75d2dd5c14b170:readwrite Session.Name...: oclHashcat-plus Status.........: Cracked Input.Mode.....: File (../wordlist/rockyou.txt) Hash.Target....: 628427e87df42adc7e75d2dd5c14b170 Hash.Type......: NTLM Time.Started...: Thu Sep 19 16:08:39 2013 (2 secs) Speed.GPU.#1...: 25647.5k/s Speed.GPU.#2...: 0/s Speed.GPU.#*...: 25647.5k/s Recovered......: 1/1 (100.00%) Digests, 1/1 (100.00%) Salts Progress.......: 4587521/14100049 (32.54%) Rejected.......: 1/4587521 (0.00%) HWMon.GPU.#1...: 0% Util, 48c Temp, 20% Fan HWMon.GPU.#2...: 0% Util, 45c Temp, 20% Fan
Conclusion
As a conclusion, WatchGuard firewall appliances use the (good old) NTLM algorithm to protect the Firebox-DB passwords :-) This was verified against versions 11.6.3 and 11.7.4.
Please note: The Firebox database does not contain the management credentials (admin/status accounts). A copy of these passwords can however be found inside the file /etc/wg/configd-hash.xml (gzip compressed) but you don’t have access to that file. Thank you Corey for this valuable comment.
Enjoy,
© 2013 – 2015, foip. All rights reserved.
Trackbacks & Pingbacks
Comments are closed.
Hey foip,
That’s an interesting find there. Good job reversing the hashing algorithm.
However, I wanted to clarify a few things here that I didn’t think you really covered.
First, let’s be clear. The hashes/users you found in the configuration file are NOT the credentials to manage the security appliance. We do not store the management credentials for our appliance in the config file. The credentials you found are part of the optional local FireboxDB authentication feature, and I assume the user called “superuser” was one you made.
Our devices offer the ability for users to create policies (firewall, IPS, and application control policies) by username, not just by IP. To do this you have to setup authentication. In most installations, users choose to get our appliance to authenticate with their internal Active Directory, LDAP, or Radius server, in which case the login details are all stored on that authentication server (not in the config file). However, we also offer the local FireboxDB database, for small customers that don’t already have authentication servers. The users you manually setup in this local Firebox database are just users you can use in your policy creation. They do NOT have any privileged access to manage the security appliance itself. So the “superuser” in your example is not a user with superuser privileges on the XTM appliance itself. Rather it’s some user you created that you can set specific access policies for through the XTM appliance.
Next, in order for an attacker to even attempt to crack passwords, he’d have to get the hashes. These are stored in the full configuration file for the XTM security appliance, which already contains all the security policies and IP addresses for your network. This is a sensitive file that you’d obviously want to protect, and would typically be found on an administrator machine in your network. If an attacker already had access to the administrative machine that has your security appliance configuration files, you already have big problems.
Finally, hashing algorithms (other than the salt) are often public. It’s not the algorithm that needs to be protected it’s the hashes. Sure knowing what hashing algorithm is used means you can attempt to bruteforce hashes, but that applies to any hashing algorithm, and they we designed to be public standards. This is why you should protect hashes and also why you should apply password best practices. If you use long ( I recommend at least 12 characters), semi-random passwords, it would still take a long time to crack. In your example, you used a short (9 char) password that is very common in a password dictionary. If superuser had a strong password, like “Try ta cr@ck th1s Pl5!” or “dyD@4whd$1AEu32” knowing the hashing algorithm would not help much; cracking would take a long time.
All that said… I do still think we should update our hashing alg, and use a more random salt. So I am working with engineering to have that done.
Cheers,
Corey Nachreiner
Director of Security Strategy and Research
WatchGuard Technologies, Inc.
Hi, Corey.
Thank you very much for your comments. Indeed the use of “superuser” and “readwrite” was confusing. I chose “superuser” without special reason, and “readwrite” because I knew the hash.
I tried to fix the text to make it clear that we are not talking about the admin or status accounts.
I started this short reserch because I was simply doing a firewall review (ruleset, VPN config, …) for a customer. The customer was using Firebox-DB accounts for VPN authentication and then, I was curious to see how strong were the passwords.
I do not fully agree with you about the following
Please get a look at http://hashcat.net/oclhashcat-plus/ and compare the cracking speed between NTML and others. Using two GPU cards, I recovered half of the password list within one hour because it was NTLM (cracking speed: 12,700,000,000 tests/sec)
So yes, the hashes must be protected, but the algorithm is also very important.
Anyway, thank you again for your comments. Hope you appreciate my changes.
Hey foip,
Thanks for the updated post, I do appreciate it. And also, good reversing work. I actually really appreciate when responsible researchers look at our products, and share discoveries (though, feel free to contact us about them too).
My main issue with the original post was only that it might have given ppl the false impression that we are talking about the appliance’s management credentials in the configuration file. And as we agree, that is not the case.
I do take your point, that some hashing algorithms are better than others, as in more computationally complex and thus longer to brute-force. I also agree the NTLM is showing its age. That said, I still think if you use a sufficiently strong password, it would still take a longer time (as in years) to crack that password. More specifically, an eight character NLTM password is dead (cracked in 5 hours on a good rig); A nine character password is doable in weeks; but once you get to 11 or 12 characters, then it still takes a long time (this all assumes you are using some complexity to avoid dictionary attacks).
Anyway, though I don’t think this issue is to risk to our customers today (assuming they protect their config and use strong password), Engineer is now looking into replacing the hash function for the FireboxDB passwords.
So thanks for sharing the research.