NATAS 11 and Reverse Engineering XOR Encryption

Learning more about server side security

Matthew Barber
4 min readNov 14, 2016

Recently I’ve been stepping into the realms of basic system security, and a good infrastructure friend of mine introduced me to http://overthewire.org/wargames/ — specifically the NATAS games.

NATAS is based around the basics of server side security, no SSH access just simple username and password to access the next section.

The early ones are pretty simple:

  • NATAS 0 hides the password in the source code
  • NATAS 1 is the same but we need to use view-source: in the browser as right click is disabled
  • NATAS 2 gives us a tracking pixel at /files/, so we simply hit that endpoint and voila — files.
  • NATAS3 gives us a clue with ‘Google won’t help’ in the source code. So we hit /robots.txt and see there is a ‘hidden’ endpoint /s3cr3t/
  • NATAS4 is fun, we need to modify the request header, namely the referer header to come from a different location. Bosh.
  • NATAS 5 we update a cookie value for ‘loggedin’ to 1
  • NATAS 6 has source code that includes another file — luckily we can hit that file directly.
  • NATAS 7 includes a target page given a URL, luckily the target page is a file — so we can just target the password file directly.
  • NATAS 8 gives us the code that encrypts the secret string, luckily we can reverse engineer this directly (as all those PHP functions have opposite equivalents).
  • NATAS 9 is using PHP’s passthru function with a grep command — and a variable we can access. Therefore we can simply inject the *nix command we want “; cat /etc/natas_webpass/natas10;” — Bosh
  • NATAS 10 is the same again but with some more intense validation, luckily grep can be used with a wild card — to return everything so “.* /etc/natas_webpass/natas11” solves that nicely

Which brings us on to NATAS11.

We’re presented with this code:

NATAS 11 XOR Encryption

Where to begin, where to begin.

In cryptography a simple XOR cipher is a type of additive cipher, that operates according to the rules:

  • A XOR 0 = A
  • A XOR A = 0
  • (A XOR B) XOR C = A (B XOR C)

This is according to wiki, and there is a great example: https://en.wikipedia.org/wiki/XOR_cipher

What we’re interested in here is:

“In any of these ciphers, the XOR operator is vulnerable to a known-plaintext attack, since — plaintext XOR ciphertext = key.”

We can see from the code that there is a default used for plain text:

array(
"showpassword"=>"no",
"bgcolor"=>"#ffffff"
);

We can also see that this default encrypted key is saved to our cookie:

ClVLIh4ASCsCBE8lAxMacFMZV2hdVVotEhhUJQNVAmhSEV4sFxFeaAw=

Remember plaintext xor ciphertext = key

So.

Decrypt Version 1

If we set the key to the default plain text, and pass in our base64_decoded cookie and, therefore encrypted key, as the argument we can hopefully get back the xor_encrypt $key.

This echo’s back:

qw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jq

Which if we extract ‘qw8J’ and replace the $key in the xor_encrypt function with this, we should get back the default value right?

Lo and behold

Decrypt Version 2

Now all we need to do is pass to the xor_encrypt function, the array we want to encrypt as a json string, and bingo — our new encrypted value (we can base64 encode into our cookie value).

If you recall from the first image — right up there at the top — the function loadData is used initially on page load to get the “data” key value pair from the cookie — if the data exists in the cookie, it decrypts and uses this, else it uses the default value — does some processing — then adds or updates the key value pair “data” cookie.

So, if we override the cookie “data” with our encrypted and base64 encoded key — we should get back the result we want.

Decrypt Final.

And bosh.

Job done.

--

--