cURL: Using curl to Test Authentication on a Website

cURL is an incredibly useful tool. This article is going to focus on using it to POST authentication data to a website, such as a pfSense or Joomla instance. I’ll be using those two as examples because I have both on hand and they use CSRF tokens for security. Hopefully the information on how to get into those two will help with testing other CMS or web based management systems.


I find Joomla to be the more complicated of the two examples I’ll cover, so let’s start with pfSense.

Let’s start by gathering the info we’ll need. First we need the names of the fields for the sign in form. Inspect Element in a web browser, or cURL’ing the page and finding the login form work easily.

Using inspect element to find the sign in field names for pfSense to use for our cuRL POST
Finding the field names for pfSense

From that we know that we need to populate usernamefld and passwordfld, and the name of the login button. But if we make a post with just that it will be rejected.

curl -k -X POST \
     --data-urlencode "login=Login" \
     --data-urlencode "usernamefld=username" \
     --data-urlencode "passwordfld=password" \

While valid, doesn’t have everything that is needed. Somehow we need to have a valid CSRF token, which is tied to cookies. Thankfully, cURL let’s us save the cookies from a session to a file, which can then be read from. So we can get the CSRF and save the cookies from that session to a file, and then use both in our POST.

curl -L -k --cookie-jar /tmp/cookies.txt https://domain.tld/ \
     | grep "name='__csrf_magic'" | sed 's/.*value="\(.*\)".*/\1/' > /tmp/csrf.txt

-L means follow redirects, -k means ignore invalid cert, –cookie-jar means save the cookies for this session to a file. The grep and sed commands make it so that only the CSRF gets saved to the file. Now we can put that all together in our POST.

curl -i -s -k --cookie /tmp/cookies.txt --cookie-jar /tmp/cookies.txt \
     --data-urlencode "login=Login" \
     --data-urlencode "usernamefld=$username" \
     --data-urlencode "passwordfld=$password" \
     --data-urlencode "__csrf_magic=$(cat /tmp/csrf.txt)" \

-i and -s decrease the amount of output to just the response headers, –cookie tells cURL which cookies file to use. If you get back “302 Moved”, then your authentication request was successful.


When it comes to using cURL to authenticate, Joomla is similar to pfSense, but not the same. The fields we need to provide information for are username, passwd, option, return, CSRF, and task. return doesn’t change each attempt like CSRF, but it can be different across Joomla instances. To avoid making extra GET requests, we can save the result of our first GET to a variable and get the CSRF and return values from there:

body=$(curl --silent --location --cookie-jar /tmp/cookies.txt http://domain.tld/administrator/index.php)

csrf=$(echo "$body" | grep "csrf.token" | sed 's/.*csrf.token":"\(.*\)".*/\1/' | sed 's/".*//')
return=$(echo "$body" | grep "return" | sed 's/.*value="\(.*\)".*/\1/')

Now that we have all the values and cookies we need, we can construct our POST.

curl --silent --output /dev/null --write-out "%{http_code}" \
     --request POST --cookie /tmp/cookies.txt --cookie-jar /tmp/cookies.txt \
     --user-agent "$(user_agent)" \
     --data-urlencode "username=$username" \
     --data-urlencode "passwd=$password" \
     --data-urlencode "option=com_login" \
     --data-urlencode "return=$return" \
     --data-urlencode "$csrf=1" \
     --data-urlencode "task=login" \

And if you get a 303 response, then you are successfully authenticated. A 200 means that your CSRF or creds are invalid. To figure out which, remove the –output and –write-out flags.

About: Bailey Kasin

I build virtual environments and challenges for Cybersecurity students to complete as a way to gain experience before graduating and entering the workforce.

Leave a Reply

Your email address will not be published. Required fields are marked *