Flag: hkcert22{mistakes-off-the-page}
Vulnerability:
In line 139 of google2fa.php
, the verify_key
function:
if (self::oath_hotp($binarySeed, $ts) == $key)
The issue is caused by type confusion in PHP and a loose comparison operator is used (==
).
When true
is provided as the OTP ($key
) “<whatever string from oath_hotp>" == true
must evaluate to true
.
This bypasses the OTP check and the flag is returned.
Exploit: Send a POST
request to login.php
with the payload:
{
"username": "admin",
"password": "admin",
"otp1": true,
"otp2": true,
"otp3": true
}
Side note: I originally thought there was a problem with the SHA1 function used in the OTP generation function and I looked for hash collision. However this is not a crypto challenge, so this idea was discarded.
Flag: hkcert22{offici4l-s4uces-st4ted-it-is-n0t-secure}
Vulnerability: The IV is reused.
const iv = crypto.createHash('sha256').update('myHashedIV').digest();
Exploit: Perform a two-time-pad attack (flag_enc XOR ciphertext XOR plaintext
):
(Credit to: https://meowmeowxw.gitlab.io/ctf/utctf-2020-crypto/ - he provided the critical clue to approach and solve this question.)
# these two pairs of I/O are provided in official.js
plaintext = b"My treasure is buried behind Carl's Jr. on Telegraph."
ciphertext = bytes.fromhex("31b9e00aafcd3f7edbd394dc2cb05e7aca8b6bf01fae094a15979062bf190f4d8b0f32ca1a1a6aace3a6efc64b4f15f64a02d9b128")
flag = "hkcert22{<<REDACTED>>}" # this is what we need to find out
flag_enc = bytes.fromhex("14aba31bafdc6c3fd5ce979a2ca0172cd3d471a10eed0e5c508d8a32eb3f0a128e5c6c8323452abcf8e5bcf74d5602f445")
def xor(s1, s2):
return bytes(x ^ y for x, y in zip(s1, s2))
# these two pairs of I/O are provided in official.js
plaintext = b"My treasure is buried behind Carl's Jr. on Telegraph."
ciphertext = bytes.fromhex("31b9e00aafcd3f7edbd394dc2cb05e7aca8b6bf01fae094a15979062bf190f4d8b0f32ca1a1a6aace3a6efc64b4f15f64a02d9b128")
flag = "hkcert22{<<REDACTED>>}" # this is what we need to find out
flag_enc = bytes.fromhex("14aba31bafdc6c3fd5ce979a2ca0172cd3d471a10eed0e5c508d8a32eb3f0a128e5c6c8323452abcf8e5bcf74d5602f445")
flag = xor(xor(flag_enc, ciphertext), payload)
print(flag)