Armaxis

Challenge Description

In the depths of the Frontier, Armaxis powers the enemy’s dominance, dispatching weapons to crush rebellion. Fortified and hidden, it controls vital supply chains. Yet, a flaw whispers of opportunity, a crack to expose its secrets and disrupt their p

Categoria: Web
Dificultad: Muy Fácil

Solution

Nos proporcionan el codigo de la aplicacion. Cuenta con 2 portales web diferentes.

Analizando el codigo identificamos el usuario admin.

challenge/database.js
      await runInsertUser(
        "admin@armaxis.htb",
        `${crypto.randomBytes(69).toString("hex")}`,
        "admin",
      );

Tambien podemos identificar que hay una falla donde es posible obtener RCE ne la linea 11 del codigo.

challenge/markdown.js
function parseMarkdown(content) {
    if (!content) return '';
    return md.render(
        content.replace(/\!\[.*?\]\((.*?)\)/g, (match, url) => {
            try {
                const fileContent = execSync(`curl -s ${url}`);
                const base64Content = Buffer.from(fileContent).toString('base64');
                return `<img src="data:image/*;base64,${base64Content}" alt="Embedded Image">`;
            } catch (err) {
                console.error(`Error fetching image from URL ${url}:`, err.message);
                return `<p>Error loading image: ${url}</p>`;
            }
        })
    );
}

Para acceder a esta funcion se requiere ser admin.

challenge/routes/index.js
router.post("/weapons/dispatch", authenticate, async (req, res) => {
  const { role } = req.user;
  if (role !== "admin") return res.status(403).send("Access denied.");

  const { name, price, note, dispatched_to } = req.body;
  if (!name || !price || !note || !dispatched_to) {
    return res.status(400).send("All fields are required.");
  }

  try {
    const parsedNote = parseMarkdown(note);

    await dispatchWeapon(name, price, parsedNote, dispatched_to);

    res.send("Weapon dispatched successfully.");
  } catch (err) {
    console.error("Error dispatching weapon:", err);
    res.status(500).send("Error dispatching weapon.");
  }
});

Para obtener acceso a la cuenta de admin es necesario reestablecer el password sin embargo solo tenemos acceso al correo test@email.htb. Pero en la siguiente parte del codigo se agrega el parametro email.

challenge/routes/index.js
router.post("/reset-password", async (req, res) => {
  const { token, newPassword, email } = req.body; // Added 'email' parameter
  if (!token || !newPassword || !email)
    return res.status(400).send("Token, email, and new password are required.");

Esto significa que podemos enviarnos un codigo al email test@email.htb y luego utilizarlo para cambiar el password del usuario admin.

Account Take Over

Primero registramos al usuario test@email.htb en la plataforma.

Nos enviamos un codigo para reestablecer el password.

Utilizamos el codigo pero con utilizando el correo admin@armaxis.htb.

Ahora es posible acceder al panel de administracion.

Remote Code Execution

Ahora que tenmos acceso podemos explotar la segunda vulnerabilidad. Para esto requerimos enviar nuestro payload en el apartado de Note pero tiene que hacer match con el regex que esta en el codigo.

content.replace(/\!\[.*?\]\((.*?)\)/g, (match, url)

Enviamos nuestro payload.

![](test;cat /flag.txt;)

Veremos que obtenemos la ejecucion correcta.

Por ultimo decodeamos en base64 la cadena o la descargamos directamente del navegador para obtener la flag.

┌──(root㉿kali)-[~]
└─# echo 'SFRCe200cmtkMHduX2J1Z3NfMW5fdGgzX3cxbGQhfQo=' | base64 -d  
HTB{m4rkd0wn_bugs_1n_th3_w1ld!}

Referencias

https://regexr.com/