Hauntmart

Personal Rating: Medium

This challenge was about a SSRF with a filter bypass to create a privileged user at an api endpoint.

  • At first glance I could see that the flag is copied to /flag in the dockerfile. The file entrypoint.sh is loaded, which sets up a database like so:

DROP DATABASE IF EXISTS hauntmart;
CREATE DATABASE hauntmart;
CREATE TABLE hauntmart.users (
    id INTEGER PRIMARY KEY AUTO_INCREMENT,
    username varchar(255) NOT NULL UNIQUE,
    password varchar(255) NOT NULL,
    role varchar(255) NOT NULL DEFAULT 'user'
);

CREATE TABLE hauntmart.products (
    id INTEGER PRIMARY KEY AUTO_INCREMENT,
    name varchar(255) NOT NULL,
    price varchar(255) NOT NULL,
    description TEXT NOT NULL
);

CREATE USER 'xclow3n'@'localhost' IDENTIFIED BY 'xclow3n';
GRANT SELECT, INSERT, UPDATE ON hauntmart.users TO 'xclow3n'@'localhost';
GRANT SELECT, INSERT, UPDATE ON hauntmart.products TO 'xclow3n'@'localhost';

FLUSH PRIVILEGES;
  • The file web_hauntmart/challenge/application/blueprints/routes.py is interesting. It contains route definitions for web and api endpoints. At the web endpoint /home the flag is defined as flag=current_app.config['FLAG'] with the template index.html

  • For /home and /product it seems like you need to be authenticated

  • The /register API seems interesting too. You can possibly register a user from an unauthenticated standpoint:

  • On the live website I could register an account immediately and access the site.

  • Under Sell Product it seems like you can send data to the server. This site really stands out, it says that you can send a manual url which will be visited by the admins. My first Idea is to host a javascript that triggers another request to me, containing the admin cookie.

  • The idea of reflected blind XSS did not work as I could not find a working injection. But what we state in the url field is indeed accessed by the server, which is interesting.

  • This is written in the index.html:

  • This code in util.py might also be interesting as it seems to download what we give it in the manual url field under certain circumstances:

  • This might be the way in. I found out before that /api is prepended to the url of api calls. so we should be able to directly access /api/addAdmin. Here is the code from routes.py that shows that:

  • Trying to access it shows a 403, which is expected because of @isFromLocalhost:

  • Lets check the isFromLocalhost function; Maybe we can bypass that. It is defined in util.py:

Well, we have a chance to perform a localhost request. Here:

Last updated