HackTheBox — Magical Palindrome
Assalamu Alaikum,
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:
- If you pass a number to it, it treats it as a length and makes an array with this length

- 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