Skip to content

Hacking Insomnia (HTB Challenge)

Initial thoughts

We are presented with a website that has a few pages, index, sign up, and login. The source code of the application is written in PHP, and uses Firebase, CodeIgniter, and SQLite3.

Insomia Signup Page

Upon signing up with admin:admin credentials, there is a basic page with no other actions to perform.

We should search the codebase for any references to flag.

php
public function index()
    {
        $token = (string) $_COOKIE["token"] ?? null;
        $flag = file_get_contents(APPPATH . "/../flag.txt");
        if (isset($token)) {
            $key = (string) getenv("JWT_SECRET");
            $jwt_decode = JWT::decode($token, new Key($key, "HS256"));
            $username = $jwt_decode->username;
            if ($username == "administrator") { 
                return view("ProfilePage", [
                    "username" => $username,
                    "content" => $flag,
                ]);
            } else {
                $content = "Haven't seen you for a while";
                return view("ProfilePage", [
                    "username" => $username,
                    "content" => $content,
                ]);
            }
        }
    }

HMM...

How can we access the administrator account? Let's look at the login code.

Understanding The Authentication Flow

The login request is a json object with a username and password field.

json
{
  "username": "admin",
  "password": "admin"
}

The login Function

php
public function login()
    {
        $db = db_connect();
        $json_data = request()->getJSON(true);
        if (!count($json_data) == 2) { 
            return $this->respond("Please provide username and password", 404);
        }
        $query = $db->table("users")->getWhere($json_data, 1, 0);
        $result = $query->getRowArray();
        if (!$result) {
            return $this->respond("User not found", 404);
        } else {
          // ... omited for brevity
            $payload = [
                "iat" => $iat,
                "exp" => $exp,
                "username" => $result["username"],
            ];
            $token = JWT::encode($payload, $key, "HS256");

            $response = [
                "message" => "Login Succesful",
                "token" => $token,
            ];
            return $this->respond($response, 200);
        }
    }

Vulnerability detected

There isn't a strong check for username and password, rather the server only makes sure there are two keys in the data sent by the server.

Exploiting The Vulnerability

We can try to send an different second key in our json login object, so that the requirement for two keys is met. We can see in the source code that the User database has two columns: username and password. By modifying the request to contain two username keys with the value of the account we want to log into, we may be able to trick the server into viewing our login attempt as valid, without using a password.

By using Burpsuite to modify the login request, we will see that this method returns a response indicating a valid login.

Insomnia Burpsuite

JSON Code
json
{
  "username": "administrator",
  "username": "administrator"
}

Getting The Flag

In Burpsuite, we can go to the login page, turn on intercepts, and try to log in with administrator:password. Once we intercept the request, we will replace the initial json with our "malicious" json. Finally, we can turn off intercepts and browse the site normally.

🎉 We got our flag!

Insomnia Flag