Cereal
Executive summary — Cereal is an end-to-end .NET exploitation chain: a forgotten
.gitrepository in production leaks the full source code, and the version history itself still holds a secret that a later commit ("Security fixes") tried to scrub. That secret makes it possible to forge valid JWTs, because the backend only validates the signature, never the issuer or the user's role. Once inside the API, an insecure JSON.NET deserialization is guarded by a string blacklist and a localhost-only restriction — both get bypassed by combining a custom application gadget (outside the blacklist) with an XSS in the Markdown library that an admin bot executes from inside the box itself. The result is a webshell dropped into the webroot and, from there, a classic jump to SYSTEM viaSeImpersonatePrivilegeand GodPotato.
| Platform | Hack The Box |
| Operating system | Windows (IIS 10.0) |
| Difficulty | Hard |
| Status | Retired |
| Target IP | 10.129.75.23 |
| Vhosts | cereal.htb (React SPA), source.cereal.htb (ASP.NET Core / source code) |
Attack map
[443] source.cereal.htb — publicly exposed .git repository
│ git-dumper -> full source code (ASP.NET Core + React)
▼
[GIT] commit history (the "Security fixes" commit redacted the key in HEAD)
│ git grep across EVERY revision -> JWT signing secret in plaintext
▼
[JWT] Startup.cs only validates the SIGNATURE (no issuer/audience/role)
│ forge a valid JWT for any "authenticated" user
▼
[443] POST /requests — JSON.NET TypeNameHandling.Auto + string blacklist
│ CUSTOM gadget DownloadHelper (not covered by the blacklist)
│ + XSS in react-marked-markdown (CVE-2020-26301) in another request
▼
[ADMIN BOT] browses /admin from localhost -> executes the XSS
│ triggers GET /requests/{id} (passes RestrictIP: it IS localhost)
│ deserializes -> DownloadHelper.Download() -> WebClient.DownloadFile()
▼
[RCE] ASPX webshell written into C:\inetpub\source\uploads\
▼
[sonny] (user.txt) — SeImpersonatePrivilege enabled
▼
[ROOT] GodPotato (DCOM/RPC token coercion) -> SYSTEM
1. Reconnaissance
Transparency note: the source documents that the machine was reset mid-exercise, moving from
10.129.75.16to10.129.75.23. This write-up uses the final IP and that instance's flags; the attack chain is identical, only the numeric requestids change.
sudo nmap -p- --min-rate 5000 -T4 -Pn -n 10.129.75.23
sudo nmap -sCV -p22,80,443 -Pn -n 10.129.75.23
22/tcp open ssh OpenSSH for_Windows_7.7 (protocol 2.0)
80/tcp open http Microsoft IIS httpd 10.0 -> redirect to https
443/tcp open ssl/http Microsoft IIS httpd 10.0
| ssl-cert: Subject: commonName=cereal.htb
| Subject Alternative Name: DNS:cereal.htb, DNS:source.cereal.htb
The TLS certificate's SAN field reveals two vhosts, so both are added to /etc/hosts:
echo "10.129.75.23 cereal.htb source.cereal.htb" | sudo tee -a /etc/hosts
https://cereal.htb/→ a React SPA ("Cereal"). Its JS reveals the API:POST /users/authenticate,GET/POST /requests, and an/adminroute.https://source.cereal.htb/→ ASP.NET (X-Powered-By: Sugar,X-AspNet-Version: 4.0.30319) serving a Compilation Error — a hint that this vhost exposes more than just the compiled app.
Resumen ejecutivo — Cereal es una cadena de explotación de aplicación .NET de principio a fin: un repositorio
.gitolvidado en producción filtra el código fuente completo, y el propio historial de versiones conserva un secreto que un commit posterior ("Security fixes") intentó borrar. Ese secreto permite forjar JWTs válidos porque el backend solo valida la firma, sin comprobar ni el emisor ni el rol del usuario. Dentro ya de la API, una deserialización insegura de JSON.NET está protegida por una blacklist de palabras y una restricción a localhost — ambas se rodean combinando un gadget propio de la aplicación (fuera de la blacklist) con un XSS en la librería de Markdown que un bot administrador ejecuta desde dentro de la propia máquina. El resultado es una webshell en el webroot y, de ahí, un salto a SYSTEM clásico víaSeImpersonatePrivilegey GodPotato.
| Plataforma | Hack The Box |
| Sistema operativo | Windows (IIS 10.0) |
| Dificultad | Hard |
| Estado | Retired |
| IP objetivo | 10.129.75.23 |
| Vhosts | cereal.htb (SPA React), source.cereal.htb (ASP.NET Core / código fuente) |
Mapa del ataque
[443] source.cereal.htb — repositorio .git expuesto publicamente
│ git-dumper -> codigo fuente completo (ASP.NET Core + React)
▼
[GIT] historial de commits ("Security fixes" redacto la clave en HEAD)
│ git grep en TODAS las revisiones -> clave de firma JWT en claro
▼
[JWT] Startup.cs solo valida la FIRMA (sin issuer/audience/rol)
│ forjar un JWT valido para cualquier "usuario" autenticado
▼
[443] POST /requests — JSON.NET TypeNameHandling.Auto + blacklist de strings
│ gadget PROPIO DownloadHelper (no esta en la blacklist)
│ + XSS en react-marked-markdown (CVE-2020-26301) en otra request
▼
[BOT ADMIN] navega /admin desde localhost -> ejecuta el XSS
│ dispara GET /requests/{id} (pasa RestrictIP: es localhost)
│ deserializa -> DownloadHelper.Download() -> WebClient.DownloadFile()
▼
[RCE] webshell ASPX escrita en C:\inetpub\source\uploads\
▼
[sonny] (user.txt) — SeImpersonatePrivilege habilitado
▼
[ROOT] GodPotato (coaccion de token via DCOM/RPC) -> SYSTEM
1. Reconocimiento
Nota de transparencia: la fuente documenta que la máquina se reinició a mitad del ejercicio, cambiando de
10.129.75.16a10.129.75.23. Este writeup usa la IP final y las flags de esa instancia; la cadena de ataque es idéntica, solo cambian losidnuméricos de las requests creadas.
sudo nmap -p- --min-rate 5000 -T4 -Pn -n 10.129.75.23
sudo nmap -sCV -p22,80,443 -Pn -n 10.129.75.23
22/tcp open ssh OpenSSH for_Windows_7.7 (protocol 2.0)
80/tcp open http Microsoft IIS httpd 10.0 -> redirect a https
443/tcp open ssl/http Microsoft IIS httpd 10.0
| ssl-cert: Subject: commonName=cereal.htb
| Subject Alternative Name: DNS:cereal.htb, DNS:source.cereal.htb
El certificado TLS revela dos vhosts en su campo SAN, así que se añaden ambos a /etc/hosts:
echo "10.129.75.23 cereal.htb source.cereal.htb" | sudo tee -a /etc/hosts
https://cereal.htb/→ una SPA en React ("Cereal"). Su JS revela la API:POST /users/authenticate,GET/POST /requests, y una ruta/admin.https://source.cereal.htb/→ ASP.NET (X-Powered-By: Sugar,X-AspNet-Version: 4.0.30319) sirviendo un Compilation Error — indicio de que este vhost expone algo más que la app compilada.
Root Access unlocks the content you can't see — everything else on the site is already open.
See Root Access plansNo account? Create one free then upgrade from your console.
Root Access desbloquea el contenido que no puedes ver — todo lo demás de la web ya está abierto.
Ver planes de Root Access¿Sin cuenta? Crea una gratis y luego mejora desde tu consola.