Custom Attacks Part 1: Laying down the foundations
Welcome back to the 17th iteration of this blog series. In this series, we’re growing our cybersecurity knowledge starting from the very basics using the overthewire.org challenges as a guide. First, I’d like to thank everyone for their feedback based on the last post! I’ll do my best to implement it and as always, more feedback is always welcome.
In today’s challenges, we’ll explore a method of exploiting code and go on to write our first password cracker. We’re going to use a mix of python and bash for our programs so I suggest you do some basic learning of the two languages to get the most benefit. Let’s get started!
For our next Leviathan challenge, we have a binary that reads files which sounds very similar to cat and strings:

It runs as leviathan3 but when we try to read the password file, it seems that it does some kind of permission check:

Running it through ltrace we can see that it first checks our actual user ID access level before passing the file name to cat:

In the bandit challenges we had come across file names that made it difficult to read them with commands like cat. In those challenges, we used escape characters to have the program ignore the “bad” characters in the file name. Fortunately for us, we can actually use that to our advantage and that is exactly what we’ll do here:

This worked because printfile takes the program name properly to check its access but then makes the mistake of passing the filename without our original modifiers of quotes to cat. Since system is essentially running a command through terminal just as we would, the “;” in bash serves to separate commands so that you can pass multiple commands to execute consecutively. In this case, system makes cat execute on “test” and then executes bash separately. Now that we are leviathan3, we can read its password:

We don’t have to logout here but we’ll just swap to leviathan3’s home directory. Notice how we’re still using the leviathan2 environment variables and so navigating to “~” doesn’t take us to leviathan3’s directory. Let’s run this binary and see:

Once again because the environmental variables are still leviathan2’s, even though we’re using a shell with leviathan3’s permissions, we haven’t logged into leviathan3. Since the level3 binary is executable by leviathan3 the group and not leviathan3 the user, we need to actually log in properly to execute it:

This looks like another password chechk type binary like the one we encountered for leviathan1. We’ll try the same solution we used there:

Very much like the first time:

Using ltrace has made things especially easy for figuring out the passwords to these binaries, but what if this program was written better so as not to actually store the password in clear text? In fact, most security standards require that passwords not be stored in the clear either to check against or to for simple storage to avoid this exact issue.
Secure login should hash a password and store the hash instead. Since hashing is a oneway trip, it’s exteremely difficult to decode if you’re using a unique and complex password. To make it even more secure (which is the current standard), the hash is salted and thus nullifies most attempts against cracking the hash even if it’s a bad password.
Imagine that instead of comparing our password input to “snlprintf”, the program compared it to: 660f2f897588846765686763e982d4a1 (the md5 hash of “snlprinf”). It would be much more difficult and complex to guess the password. Well what if we pass the hash that it’s comparing to as the password?
You’re on to something here because this is an actual attack that used to work on kerberos authentication. It was called “pass the hash” but has since been patched. In our case, passing the hash wouldn’t work either because the program wouldn’t be passing a string to the comparison function. It would first hash the password we give it and then compare that hash to the hash that it has stored as the correct password. In that case, passing 660f2f897588846765686763e982d4a1 as the password would cause the program (the secure version) to interpret it as a55962f77ea02020fb54e06ce08ad46c, which is the hash of the hash of snlprintf.
We’ve discussed hash collisions before and that’s also a major reason behind the standard of salting hashes.
So then does storing hash passwords a foolproof method for password security? The short answer is no, because we can use password crackers to just keep guessing passwords until the right one just works.
I hope you enjoyed this next layer of password security and stay tuned for part 2 where we’ll actually build our very own customized password guessing tool.