← Back to list

HackTheBox — Magical Palindrome

Assalamu Alaikum,

Muhammad Alshlqany · 2025-11-18 17:15 · 5 claps · 2.8 min read
#htb #hackthebox #palindrome #magical-palindrome #ctf-writeup
Open on Medium ↗

HackTheBox — Magical Palindrome

Assalamu Alaikum,

In this write-up, I will walk through my solution for the “Magical Palindrome” challenge from HackTheBox. challenge: https://app.hackthebox.com/challenges/Magical%2520Palindrome

This is a white box challenge; you can download the source code and read its

index.mjs:

import {serve} from '@hono/node-server';
import {serveStatic} from '@hono/node-server/serve-static';
import {Hono} from 'hono';
import {readFileSync} from 'fs';

const flag = readFileSync('/flag.txt', 'utf8').trim();

const IsPalinDrome = (string) => {
 if (string.length < 1000) {
  return 'Tootus Shortus';
 }

 for (const i of Array(string.length).keys()) {
  const original = string[i];
  const reverse = string[string.length - i - 1];

  if (original !== reverse || typeof original !== 'string') {
   return 'Notter Palindromer!!';
  }
 }

 return null;
}

const app = new Hono();

app.get('/', serveStatic({root: '.'}));

app.post('/', async (c) => {
 const {palindrome} = await c.req.json();
 const error = IsPalinDrome(palindrome);
 if (error) {
  c.status(400);
  return c.text(error);
 }
 return c.text(`Hii Harry!!! ${flag}`);
});

app.port = 3000;

serve(app);

After reading this file, we found that we need to send a palindrome value with a length ≥ 1000, so let’s do this directly

But it’s not that easy. I got a response code **413 Request Entity Too Large. **This is because nginx refuses bodies larger than 75 bytes due to client_max_body_size 75; in nginx.conf So even though the backend allows large palindromes, nginx blocks them first.

So we need a way to bypass this, so I decided to reread the code and search for any vulnerable parts of the code while debugging it locally, and I realized that there is no type check for palindrome, so I tested the following payload:

{
  "palindrome":{
      "length":1000
  }
}

and this allows me to bypass the string length check

Now the server is in line for (i of Array(string.length).keys())will create an array with 1000 and get the keys [0…999]

string[i] & string[string.length — 0-1] Both are undefined (equals), but the server has another condition of both being a type of string

After a few minutes of thinking, I decided to see how the **Array()** function works and found the following:

  1. If you pass a number to it, it treats it as a length and makes an array with this length

  1. And if you passed a string, it makes an array with length 1 and has this string

So if our object has a length value as a string, the server will create an array with length 1, and the loop will iterate only 1 time with i = 0 because array keys will return only[0]

Now we should also add both 0and Length-1 Having the same string value for our object to be like this

{
  "palindrome":{
    "length":"1000",
    "0":"c",
    "999":"c"
  }
}

And after sending the request, i got the

Contact

email: moalshlkany@gmail.com LinkedIn: https://www.linkedin.com/in/muhammad-alshlqany/


메타데이터
post_id
e4f5fe718cab
slug
hackthebox-magical-palindrome-e4f5fe718cab
url
https://medium.com/@alshlqany/hackthebox-magical-palindrome-e4f5fe718cab
canonical_url
https://medium.com/@alshlqany/hackthebox-magical-palindrome-e4f5fe718cab
author_url
https://medium.com/@alshlqany
status
ok
fetched_at
2026-07-17 14:10:40