HackTheBox – Mission Impossible

In this write-up we will be visiting the Mission Impossible challenge from HackTheBox.

Your mission, should you chose to accept it, is to decrypt the provided intercepted email, and follow the rabbit hole.


We start our journey by reading the message file found in the ZIP-archive we downloaded from HackTheBox. Inside the message file we find an encrypted message in what seems to be a hexadecimal string. Usually, when I have an encrypted string and no hints to go by, I initiate my decryption efforts by checking for repeating-key XOR encryption.

Using the tool xortool we identify that the most probably key, should the contents by encrypted with repeating-key XOR encryption, has a length of 17 bytes.

Using xortool once again, we identify 8 potential keys of 17 bytes in length, that yields mostly printable characters in the decrypted output. Decrypting the file contents with the first key, ‘(1ss,0nim5*s6!b)e‘, we obtain the following message:

.gen1 X12te-H
B l*w i6 a s &r t (e6sag  we 7 c iv defro( oure$s6eteK.-B4w - d &r<ptei1 wi1h yo07 5ri3a1e k y
f*7 #ur1h r i+stru&1i*nsk
O
T-is w,)lebeet-e l$st m 6s$geew  tr$nsmi1ev,a  m$il.eIn o7!e7 t* ,ncr ase *0rese&u7ityi
al)em ss$g s (,nclu!,n" t-eeoneebelo2l 2il) 'e t7asmi11e! t* 1he .PI r$1h r 1h$n e(ail.HOT-e .P. wi)l ma.  6ur  1he (essa"  ,s  n&ryp1ed p7*p rl< 'efo7e up)*a!in" 1o p7even1eb$d !a1a
mthate+e7d .l ich nbac- resa<sethi6 isnb1 6ec0r , b0t wh$1 !oe6 -e k+ow?)kH
.ouec$n a&cesse1h,s .P. byePOST,+geanee+cry5ted ( s6ag  ,n t-e fo7( >"m s6ageg: "e+&r<pt d.str,ng"}HOt* "j"k Ma.e su7  <oued*n'teforg 1 1o -e= en&ode ,1.H

OI# yo0 nee!et* s n! an<one $em ss$g , r memb 7 1ha1  ver< age+1sb p0b)ic .ey
,6 gGE.-$bleg as 2 l). ~)H

.ood )0c. o0tethe7e
-e.1u0
O
O---h BEG.. .EC.E. EN.RYPT.. .ES.A.E -h--
'$c|36&2va9a b60bu&1}91#3!375t1c3f' 9$04rav625#e08cuq1q18#4q1b5|b70d} 9tf1&5pce5v65eb#qf#5dr3wf8dqbd06!!4}43 1 d27!29d9$|btdfw6v549&f745w}a|08q5wab1 9f1c&r5!ccw4r55dt1f65qr1qa9 0$89cwf2fcwuc&7es4|447qfdbeu#0rb0#2&a90 44faqt5!4e'7 d0c}42c0$q5w05u5tfd3$892auH
h--h .ND .ECRE.eE.CR.P.ED .ESSA.. h--h
O
T-is m 6s$geew,ll 6elf-! s1ru&tein t0 se&*n!s.k.k..

Looking at the two highlighted lines, it would appear as if the lines were to say “BEGIN … ENCRYPTED MESSAGE” and “END … ENCRYPTED MESSAGE”. Thus our key is not quite there yet, but modifying the key until we see such strings in the message, we arrive at the following key:

m1ssi0nimposs!ble

Considering the name of the challenge, this key seems very much correct. The message now yields the following:

Agent X121 -
Below is a secret message we received from our asset KT-B42 - decrypt it with your private key
for further instructions.

This will be the last message we transmit via email. In order to increase our security,
all messages (including the one below) will be trasmitted to the API rather than email.
The API will make sure the message is encrypted properly before uploading to prevent bad data
(that nerd Bleichenbacher says this isn't secure, but what does he know?).
You can access this API by POSTing an encrypted message in the form {"message": "encrypted_string"}
to "/". Make sure you don't forget to hex encode it.

If you need to send anyone a message, remember that every agents' public key
is "GET-able" as well. ;)

Good luck out there
- X100

---- BEGIN SECRET ENCRYPTED MESSAGE ----
bac936c23a9aeb60b0c1891f3d37511c3fbe9a047a3625fe08c041418f441b59b70d8e91f1c55ce5365ebf4ff5d732f8d4bd06dd4843e1ed27d29d9a9b1df263549cf74528a908452ab1e9f1cc75dcc24755d11f654714a9e0a89c2f2fc20cc7e6494474fdbe0f07b0f2ca90e44fa415d4eb7ed0c842c0a45205051fd3a892a0
---- END SECRET ENCRYPTED MESSAGE ----

This message will self-destruct in 10 seconds......

According to the message, we should be able to send encrypted messages to an API using HTTP POST requests. Furthermore, these requests should make sure that the messages are properly encrypted in order to stop data corruption. Let us examine what is meant by that.

As shown in the illustration above, when sending the secret encrypted message from the message that we decrypted, we receive a successful response and the API seems to have accepted our message.

However, when sending the same message with the character ‘1’ appended to the end of it, we receive an error response stating that the message we sent contained invalid padding. The message further suggests that we can retrieve the public key for every agent using HTTP GET requests.

Using our supposed agent-name, X121, as stated in the start of the decrypted message, we were able to retrieve a public key from the API. With these things out of the way, let us consider what we have to do in this challenge.

The decrypted message mentions a person named Bleichenbacher. Interestingly, a Swiss cryptographer named Daniel Bleichenbacher was the first person to demonstrate a practical example of the adaptive chosen-ciphertext attack. Bleichenbacher’s demonstration targeted RSA encryption with PKCS#1 padding, which should make sense for us consider we have access to a public key, effectively guiding us to think that the implementation we have to attack is a public-key cryptosystem such as RSA.

I found the following implementation of a Bleichenbacher attack by user alexandru-dinu on GitHub:

Before we can continue, we need to derive the modulus, n, and the public key exponent, e, from our public key. These are vital parts of the attack demonstrated by Bleichenbacher.

Once we have these, we can go ahead and modify the Bleichenbacher attack implementation to fit our explicit needs.

As shown in the above illustration(s), we need to modify the line where the script derives a public key, and replace it with the constants that we have derived from our own public key.

We furthermore have to change the chosen ciphertext for our attack in the main function, and replace the call to prepare with a call to unhexlify. This is because the prepare call converts the plaintext message into ciphertext in preparation for the chosen-ciphertext attack. However, since our message is already an encrypted chosen-ciphertext, we simply need to convert it from a hexadecimal string representation to a byte representation.

Finally, we have to modify the oracle function which is the key of this attack. The original implementation, as seen in the illustration above, perform local verification of the padding and therefore does not suit our case, in which the verification occurs remotely.

Thus we must change the function to perform an HTTP POST request towards the verification service. Notice that the Bleichenbacher attack, also known as the million message attack, might require a lot of attempts and thus might take a long time to execute. Because of this, I have wrapped the HTTP POST request in a loop, such that if the remote HackTheBox instance closes or runs out, we can simply launch a new instance and specify a new port.

Without further ado, let us run the script and execute the attack.

And there you have it – the challenge has been solved!

Leave a Reply