HackTheBox Signing Factory Challenge
Explore the basics of cybersecurity in the Signing Factory Challenge on Hack The Box. This medium-level Challenge introduces encryption reversal and file handling concepts in a clear and accessible way, perfect for beginners.
https://app.hackthebox.com/challenges/641
Description#
After studying about vulnerabilities on signing servers, a group of researchers gathered one night and comitted into creating a modern and more secure way of signing tokens for authentication. They are certain that their product is ready for distribution and want to do a last security audit before publicizing their work. They provided you with access to the server. Is their way of signing messages the solution to all previous attacks?
Exploitation#
#!/usr/bin/python3
from base64 import b64decode, b64encode
from pwn import *
from sympy import mod_inverse, factorint
import hashlib,string,random,re
golden_ratio = 2654435761
admin = "System_Administrator"
def get_process():
try:
host, port = sys.argv[1].split(':')
return remote(host, int(port))
except IndexError:
print(f'Usage: python {sys.argv[0]} <ip:port>')
exit(1)
def extract_base64_token(response):
match = re.search(r"Your session token is b'([A-Za-z0-9+/=]+)'", response)
if match:
return match.group(1)
else:
raise ValueError("Failed to extract Base64 token from response")
def parse_e_n_from_response(response):
match = re.search(r"\(e,N\) = \((\d+),\s*(\d+)\)", response)
if match:
return int(match.group(1)), int(match.group(2))
else:
raise ValueError("Failed to parse e and n from response")
def calculate_h_n_from_equations(equations):
equation_re = re.compile(r"equation\(unknown, (\d+), (\d+)\) = (\d+)")
unknowns = []
for match in equation_re.finditer(equations):
rnd = int(match.group(1))
equation_output = int(match.group(3))
inverse_rnd = mod_inverse(rnd, golden_ratio)
unknown = (equation_output * inverse_rnd) % golden_ratio
unknowns.append(unknown)
h_n = 1
for unknown in unknowns:
h_n *= unknown
return h_n
def hash_username(username):
numeric_username = int(username.encode().hex(), 16)
h = hash_var(numeric_username)
return int(h)
def hash_var(key):
return (((key % golden_ratio) * golden_ratio) >> 32)
def reverse_hash_var(hashed):
shifted_value = hashed << 32
for candidate in range(golden_ratio):
if (((candidate % golden_ratio) * golden_ratio) >> 32) == hashed:
return candidate
return None
def numeric_to_username(numeric_username):
hex_string = format(numeric_username, "x")
if len(hex_string) % 2 != 0:
hex_string = "0" + hex_string
return bytes.fromhex(hex_string).decode("utf-8")
def reverse_hash_username(hashed_value):
numeric_username = reverse_hash_var(hashed_value)
return numeric_to_username(numeric_username)
def get_auth_token(username, d, n):
numeric_username = int(username.encode().hex(), 16)
h = hash_var(numeric_username)
auth = pow(int(h), d, n)
return b64encode(str(auth).encode()).decode()
def get_signature_and_public_key(p, plaintext):
p.sendline(b"0")
p.recvuntil(b"Enter a username: ")
p.sendline(plaintext.encode())
response = p.recvuntil(b"[+] Option >> ").decode()
token_base64 = extract_base64_token(response)
p.sendline(b"2")
equations = p.recvuntil(b"Enter the hash(N): ").decode()
h_n = calculate_h_n_from_equations(equations)
p.sendline(str(h_n).encode())
response = p.recv().decode()
e, n = parse_e_n_from_response(response)
auth = int(b64decode(token_base64).decode())
return auth, e, n
def get_flag(p, auth_token):
p.sendline(b"1")
p.recvuntil(b"Enter your username: ")
p.sendline(admin.encode())
p.recvuntil(b"Enter your authentication token: ")
p.sendline(auth_token.encode())
response = p.recvline().decode()
return response
def prepare_auth_token(forged_signature):
auth_token = b64encode(str(forged_signature).encode()).decode()
return auth_token
def is_alphanumeric_latin(s):
latin_alphanumeric = set(string.ascii_letters + string.digits)
return all(char in latin_alphanumeric for char in s)
def main():
p = get_process()
factors = factorint(hash_username(admin))
ciphers = []
for factor in factors:
i = 1
numeric_username = reverse_hash_var(factor)
while True:
try:
uname = numeric_to_username(numeric_username)
if not is_alphanumeric_latin(uname):
raise
break
except:
numeric_username = numeric_username + (golden_ratio * i)
i += 1
cipher, e, n = get_signature_and_public_key(p, uname)
ciphers.append(cipher)
forged_signature = 1
for cipher in ciphers:
forged_signature = (forged_signature * cipher) % n
auth_token = prepare_auth_token(forged_signature)
response = get_flag(p, auth_token)
print(f"Server response: {response}")
p.close()
if __name__ == "__main__":
main()
Summary#
The Signing Factory Challenge on Hack The Box is a medium-level cryptography challenge that focuses on forging valid authentication tokens through numerical hashing and modular arithmetic. Participants analyze public key equations, reverse engineer hashing functions, and exploit properties of RSA to craft valid tokens for administrator access. This challenge is ideal for intermediate users looking to deepen their understanding of modular arithmetic, hashing reversals, and RSA cryptography in a cybersecurity context.