Foil the Plot
Description
CTF: Whitehacks 2022
Author: Chun
Difficulty: Hard
APOCALYPSE activated a sleeper cell for a suicide bombing but the target location is not known.....
Experts from CSIT have discovered the attacker-controlled server that was used to send a secret message to the sleeper cell. The server is protected with a password that is at least 40 chars long! The server does not store the password but to our good fortune, a weakness has been discovered in the way it performs the authentication.
It validates the password by performing the following steps:
- Split the 40 char password into 2 equally-sized segments
- Check that the segments are not identical
- Generate the SHA-256 digests of both segments
- Check that the last 5 bytes of both digests are identical
Your task is to gain authentication to the server, decipher the message and determine the target location before it's too late!
Challenge Access:
http://challenges1.whitehacks.xyz:28800 (opens in a new tab)
http://challenges2.whitehacks.xyz:28800 (opens in a new tab)
Enter the flag as WH2022{ID_postal code}
Eg. WH2022{s@m_pl3_123456}
Solution
Pwned by @skytect (opens in a new tab)
After visiting the site, one encounters a sign in page that requires a password.
- Split the 40 char password into 2 equally-sized segments
- Check that the segments are not identical
- Generate the SHA-256 digests of both segments
- Check that the last 5 bytes of both digests are identical
Looking at this, we can probably generate a working password by brute-force by finding a valid hash collision. Here's the script I used:
from hashlib import sha256
from itertools import product
from string import ascii_lowercase
endings = {}
for i, s in enumerate(product(ascii_lowercase, repeat = 20)):
s = ''.join(s)
h = sha256(s.encode()).hexdigest()
ending = h[-10:]
if ending in endings.keys():
print(s, h)
print(endings[ending][0], endings[ending][1])
break
else:
endings[ending] = (s, h)
if i % 1000000 == 0:
print(f'Checked until {s}')
It can yield a match within 2 seconds on my computer:
aaaaaaaaaaaaaaachlhe acfaaf03622106a652c4d7a3b7d5703161c0ea0fbe15a7fc75f31fa68ebcad86
aaaaaaaaaaaaaaacgxur 957c4c3f3435548089a5f70d76a7331a2a47773e138d55e4c00bf7a68ebcad86
If we use the password aaaaaaaaaaaaaaachlheaaaaaaaaaaaaaaacgxur
, we're able to
get past the authentication page.
On the site, we find the string:
UExBSU5URVhUIDw9PT4gKEFFUy1DQkMsIFNIQS0yNTYoMXN0IHNlZ21lbnQpLCBTSEEtMjU2KDJuZCBzZWdtZW50KSkgPD09PiBDSVBIRVJURVhU
After decoding it from Base64, we get:
PLAINTEXT <==> (AES-CBC, SHA-256(1st segment), SHA-256(2nd segment)) <==> CIPHERTEXT
This gives us a clue on how to deal with the other Base64 string hidden on the site:
W4+OWR0rcN2cclkxSIWJBC0pYQMFZXbePsW+GrJFj6gfRNV1lXy6y3hUKhI8M2Tulm4RW9RZnWKlNt/ZpTfaB82Irx5wnYdg4kilZIDzAB9HNk+5hnqgqam/uhqbixIbOT8OxeRsQZ8pd16qMg+v/A==
First, let's generate the SHA-256 hashes of our passcode's components:
aaaaaaaaaaaaaaachlhe acfaaf03622106a652c4d7a3b7d5703161c0ea0fbe15a7fc75f31fa68ebcad86
aaaaaaaaaaaaaaacgxur 957c4c3f3435548089a5f70d76a7331a2a47773e138d55e4c00bf7a68ebcad86
Then, we can use the following values to attempt to decrypt the AES-CBC on CyberChef (opens in a new tab):
Key: acfaaf03622106a652c4d7a3b7d5703161c0ea0fbe15a7fc75f31fa68ebcad86
IV : 957c4c3f3435548089a5f70d76a7331 (only the first half since an IV is 16 bytes)
Output:
[ID: h@$h_c011i?i0n] It is a tiger. It is also a leopard. It is the route to a chilling glimpse of hell.
We've now gotten the first part of the flag: h@$h_c011i?i0n
.
The back portion gives us a hint to where the target location is.
It is a tiger. It is also a leopard. It is the route to a chilling glimpse of hell.
If you google the string, you would find Haw Par Villa, for which the postal
code is 118628
.
When we try those together, it works!
WH2022{h@$h_c011i$i0n_118628}