Official EasterBunny Discussion

I am able to see some requests but not the actual application:
check

Here is the process I am trying to perform, as I understand it:

I am using ngrok to forward all traffic from my local EastBunny application running on localhost:1337 to the live instance that HTB gave me.

My goal is to send a request to the instance with the correct IP and authSecret. To do so, I must use ‘x-forwarded-port’ correctly.

Am I on the right track?

The downloadable files are just for source code review and so you can run a local instance for testing if you want.

So you want to analyze the source code and find the vulnerability that you can then exploit on the live instance

so ngrok really wont help?

the only reason to use ngrok is if your doing something that requires the server sending your attacking machine data but that machine doesn’t have an address that is reachable from outside your local network

1 Like

i have to use ngrok i cant forward 80 or 443 to my local server ISP block so i have to use ngrok to bypass. you only need to host is the XSS javascript file:
to change the host or the header i just changed it in the burp request, however you can also do it with curl

I was never able to get ngrok to work because it had an anti-fraud page that caused problems with the exploit chain. But if anyone else is having problems where they don’t want to pop a hole in their firewall, you can use LocalXpose which works like ngrok but doesn’t display the anti-fraud page. I was able to use it for this challenge.

I solved it, but I am curious if there is a way to have the content we need to serve be on a different port than 80 and I just missed it.

For those looking for a tunnel without the anti-fraud page, localhost.run worked for me. localxpose, ngrok and a few others did not.

1 Like

Super late reply, but for anyone else who might stumble upon this:
There is. Note that the regex pattern “.*:” is greedy, so when used in the context of removing a match with pattern “.*:”, an input like “a:b:c” will give an output like “a:b”. The suffix appended after the regex replace can be parsed out by being treated as an HTTP parameter.

edit: accidental italics

There is. Note that the regex pattern “.*:” is greedy, so when used in the context of removing a match with pattern “.*:”, an input like “a:b:c” will give an output like “a:b”. The suffix appended after the regex replace can be parsed out by being treated as an HTTP parameter.

You’re not wrong regarding the regex, but it doesn’t work for solving this challenge. The entry is partially keyed off of the data that the regex is being applied to, and that data will always be set to a very specific value by the other visitor. If you modify the header in the manner you’re suggesting, the other visitor’s request will miss instead of hit and foil your attempts. Correct me if I’m wrong, but I was literally just trying that exact thing before realizing this was the case and falling back to the default port like everyone else.

Good eye, though.

Correct!
Apologies. I thought I remembered testing for this and getting it to work, but upon revisiting it seems I was wrong.

For anyone not wanting to mess around with ngrok and sites like that, webhook.site is a lot easier to setup :slight_smile:

Had this problem again.

Error [ERR_REQUIRE_ESM]: require() of ES Module /app/node_modules/sqlite-async/sqlite-async.js from /app/utils/database.js not supported.

Can someone from staff fix this or at least tell me if im doing something wrong?

Hi change the database.js file to the below :+1:

const sqlite3 = require(“sqlite3”);

class Database {
constructor(db_file) {
this.db_file = db_file;
this.db = undefined;
}

async connect() {
    this.db = new sqlite3.Database(this.db_file);
}

async migrate() {
    return new Promise((resolve, reject) => {
        this.db.exec(`
            DROP TABLE IF EXISTS messages;

            CREATE TABLE IF NOT EXISTS messages (
                id         INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
                message   VARCHAR(300) NOT NULL,
                hidden    INTEGER NOT NULL
            );

            INSERT INTO messages (id, message, hidden) VALUES
              (1, "Dear Easter Bunny,\nPlease could I have the biggest easter egg you have?\n\nThank you\nGeorge", 0),
              (2, "Dear Easter Bunny,\nCould I have 3 chocolate bars and 2 easter eggs please!\nYours sincerely, Katie", 0),
              (3, "Dear Easter Bunny, Santa's better than you! HTB{f4k3_fl4g_f0r_t3st1ng}", 1),
              (4, "Hello Easter Bunny,\n\nCan I have a PlayStation 5 and a chocolate chick??", 0),
              (5, "Dear Easter Bunny,\nOne chocolate and marshmallow bunny please\n\nLove from Milly", 0),
              (6, "Dear Easter Bunny,\n\nHow are you? I'm fine please may I have 31 chocolate bunnies\n\nThank you\nBeth", 0);
            `, (error) => {
            if (error) {
                reject(error);
            } else {
                resolve();
            }
        });
    });
}

async getMessage(id) {
    return new Promise((resolve, reject) => {
        this.db.get("SELECT * FROM messages WHERE id = ?", [id], (error, row) => {
            if (error) {
                reject(error);
            } else {
                resolve(row);
            }
        });
    });
}

async getMessageCount() {
    return new Promise((resolve, reject) => {
        this.db.get("SELECT COUNT(*) as count FROM messages", (error, row) => {
            if (error) {
                reject(error);
            } else {
                resolve(row.count);
            }
        });
    });
}

async insertMessage(message) {
    return new Promise((resolve, reject) => {
        this.db.run("INSERT INTO messages (message, hidden) VALUES (?, ?)", [message, 0], function (error) {
            if (error) {
                reject(error);
            } else {
                resolve({ lastID: this.lastID });
            }
        });
    });
}

}

module.exports = Database;

For anyone with this error:

Error [ERR_REQUIRE_ESM]: require() of ES Module /app/node_modules/sqlite-async/sqlite-async.js from /app/utils/database.js not supported.

Just modify package.json and change:

"sqlite-async": "^1.1.2"

to

"sqlite-async": "1.1.2"

Looks like version 1.1.4 moved to ESM and they didn’t make that a major version number change. So telling npm to only install 1.1.2 instead of any patch >= 1.1.2 gets it running again.

5 Likes

Hello everyone! I tried different things but I can’t get any to work, can anyone DM me for help?

I’ve been trying to solve this challenge but it seems that i am unable to do cache poisoning I’ve tried using burp suite and also curl but none seem to work id appreciate any help at this point

I could really need a hint I am pretty sure the vulneribality is in X-Forworded-host and post it talk me all day for this little info about it help!!!

Hey everyone,

I am trying to manipulate the <base href="[injected-host]:[port]/static/" /> tag, but it seems the X-Forwarded-Port is not behaving. I cannot seem to force the port to change from the challenge’s port.

I have injected X-Forwarded-Port, as per the provided code (routes.js) on line 18:
${req.headers["x-forwarded-port"] ?? 80

but the response pays it no mind:

If anyone is able to point out my error, please, enlighten me!

Thank you so much, spent a LOT of time troubleshooting my exploit without realizing I should use something other than ngrok

the target cannot access your machine through localhost (or a private ip for that matter), you will need to use a service such as localhost.run to create a tunnel to your internal network and serve the payload

1 Like