1. Home
  2. Docs
  3. Examples
  4. HTTP Password-based Authentication

HTTP Password-based Authentication

This example is currently a work in progress.

Accessing certain areas of a web application may require users to authenticate using their credentials. Therefore, to test an application area that is only available to authenticated users, FuzzLabs must perform authentication before testing the protected page/resource. During login, web applications most often expect to receive user credentials in the body of POST requests. In response to a successful authentication request, the web application returns a Session ID cookie which the web browser must submit with any subsequent requests when accessing protected resources.

This example demonstrates how to implement such an authentication mechanism in FuzzLabs, and discusses many other interesting and useful things.

Prerequisites

This example is the most advanced one out of all the authentication-related examples. It utilizes a lot more features to demonstrate what FuzzLabs is really capable of.

We assume the reader is already familiar with the following topics:

We recommend quickly reading through the following before jumping into the implementation of the example:

The example targets WebGoat. If you’d like to try the example exactly as it is on this page, we recommend installing WebGoat. The easiest way is to grab the Docker container. Please note, as WebGoat was written in Java, it is quite resource hungry. (Or, maybe FuzzLabs hit on a memory leak…?) Therefore, the test configuration shown in this example was somewhat optimized to trigger the vulnerability hopefully before WebGoat runs out of memory.

WebGoat Example

This example demonstrates quite a few features of FuzzLabs via the “Off-by-One Overflows” vulnerability of WebGoat.

The “Off-by-One Overflows” example of WebGoat requires a user to submit two forms. The first form requires the user to provide a first name, last name and a room number. The form on the second page shows a drop down list where the user can select a price plan. Starting from ground zero, the actual flow is:

  1. Logging in to WebGoat
  2. Submitting the first form
  3. Submitting the second form

If we analyze the application carefully, submitting the second request is not necessary to complete the flow. Therefore, we can run our test by only performing requests #1 and #3 above. These two requests are the ones this example is going to focus on.

Authentication Request

In this section we are going to discuss the implementation of a Unit template to authenticate to our target. Successful authentication requires the following:

  • Submitting a POST request to the appropriate resource with the credentials included in the request body
  • Using a Content-Type header in the request to let the server know the format of the request body
  • Using a Content-Length header to tell the server the size of the request body

Basic POST Request Template

We can start out by modifying the GET request we used in the previous examples or starting from scratch. As the first step, we are going to:

  1. Make sure the request uses the POST method
  2. Update the resource as appropriate for our target
  3. Create a Group to serve as a placeholder for the request body

A screenshot with the updated template is shown below.

Content-Type Header

Next, we add the Content-Type header to the request to tell the web server what kind of data to expect in the request body. In case of WebGoat, the expected content type for the authentication request is application/x-www-form-urlencoded.

Now that we have the Content-Type defined (Header.ContentType group in the above example), it is time to create the Content-Length header. The value of the header is the length of the request body in bytes.

Content-Length Header

The length of the request body may change, therefore we cannot use a hardcoded value for the Content-Length header. The length may change:

  • Based on the value of the username and password session variables we will define and refer to from the request body.
  • If we have any fields within the request body that we configured to be tested.

Therefore, we have to create the Content-Length header so that its value is calculated automatically, based on the value of the request body. The Sizer primitive can help with this. In the following video we show how to use the Sizer primitive to dynamically calculate the length of the request body.

You may have noticed that the video starts by adding a String primitive to the request body first. This was required because FuzzLabs refuses to work with empty Groups. Therefore, without adding this temporary primitive, we could not have shown the Sizer primitive in action using the Preview feature. We have also made a mistake by misplacing the Sizer primitive initially, which was clearly visible in the Preview. As we could see, the Preview feature can come in quite handy to quickly spot any issues.

At this point, the only thing left to have a simple authentication request is to complete request body.

Credentials

Instead of hardcoding credentials into the request, we define two session variables, one for the username and another for the password. The screenshot below shows an example of such session variables.

Next, we implement the request body that includes the credentials. As the Content-Type is application/x-www-form-urlencoded, we have to implement the body to match the below pattern.

username=${username}&password=${password}

We are going to use the Reference primitive to refer to the value of the session variables we have defined earlier. This can be seen below.

We are almost ready with our request. There is one important thing missing. If the username or password contained characters like & or = that would break the request body. For example, if we had the username mac&cheese and password password&s=, the request body generated by FuzzLabs would end up being:

username=mac&cheese&password=password&s=

As can be seen, despite providing valid credentials, the web application would receive the username “mac and the password password. The Content-Type (application/x-www-form-urlencoded) of the request tells us exactly what we have to do: we have to URL encode the username and password. To do that, we have to apply the “URL Encode” transform on both Reference primitives. This is shown below.

Now that we have a fully functional authentication request, lets seen what we can do in case we wanted to test the username and password inputs too.

You can download the JSON object of the above authentication request template from HERE. Then, you can copy-paste the JSON object into the editor by clicking on View > View Code in the editor menu. However, if you are new to FuzzLabs, we recommend creating this template manually.

Testing Credentials

This step is optional and is not required to successfully complete this example.

We have created the authentication request to be able to customize the user credentials on a per-target basis within the Job Configuration. However, testing the username and password inputs during the test requires a slight modification to the Unit template. We can use the Switch primitive to assign multiple primitives to a single field within the template, where the first child of the Switch primitive is the default value. The value of the remaining children is the value that the Switch primitive will produce when being mutated.

As per the above, in the place of the username and/or password, we create a Switch primitive with two primitives as its children: the first child is the Reference primitive to refer to the default value and the next one is a mutable String primitive. This setup is shown below.

If we take a look at the Preview of the Unit we can see that this time FuzzLabs is going to generate over four thousand test cases. Looking at some of the test cases using the Preview feature we can see the username and password fields being changed.

The above example also highlights one potential issue with our configuration: only the Reference primitives have URL encoding enabled. As a result, mutations generated for the username and password fields by the String primitives will not be URL encoded, thus likely not producing the desired behavior. The best way to handle this is to remove the URL encoding from the Reference primitives and configure the Switch primitives with the URL encode transform enabled.

The Authenticated Request

Our second request looks like as illustrated by the curl command below.

curl 'http://localhost:8080/WebGoat/attack?Screen=736032128&menu=600' \
-H 'Connection: close' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-H 'Cookie: JSESSIONID=97D426E965D834CCBE3DD44379286EDE' \
--data-raw 'first_name=john&last_name=doe&room_no=101&price_plan=$9.99 - 24 hours&SUBMIT=Accept Terms'

A quick way to start implementing the Unit template for the request is by making a copy (File > Save as) of the authentication request and making the necessary changes to the copy. This way we can save ourselves the trouble of creating everything from scratch.

A possible implementation of the Unit template is shown below.

You can download the JSON object of the above request template from HERE . Then, you can copy-paste the JSON object into the editor by clicking on View > View Code in the editor menu. However, if you are new to FuzzLabs, we recommend creating this template manually.

There are a few important things to discuss related to the above template:

  • We are cheating a bit (spoiler alert!): we have set some form fields non-mutable. This is because it is the room number input field that triggers the simulated vulnerability. Therefore, the Unit template was optimized to keep the test run short and get to the result quickly.
  • We have not fully parsed the query parameters. Instead, we have used a single String primitive to represent all the query parameters. This approach is acceptable as long as we are not interested in testing any of the query parameters.
  • We have created an additional header to send the Session ID to the web application via a Cookie. The session variable we refer to using the Reference primitive has been defined with an empty value. We are going to use Response Processing Rules within the Flow template to extract the session ID into the session variable.
  • We used the Switch primitive and two children to represent the room number parameter in the request body. The two children, one being a String primitive, the other a Number, represent the same numeric value initially: 101. However, the mutation algorithms of these primitive generate values specific to the type of fields they represent. For example, if we used a single String primitive, as its algorithms operate with strings, it would not generate mutations related to numeric values such as integer underflows and overflows. Therefore, we represent the numeric value using two primitives to combine their algorithms.

Test Flow

The way the HTTP protocol was implemented regarding connection handling, we have two options to implement the test Flow within FuzzLabs:

  • We disconnect and reconnect after each request, or
  • We send all the requests over the same connection

The first option requires that we tell the web server to close the connection after each request by sending a “Connection” header with the value “close”. If we decide to go with the second options, the value of the “Connection” header should be “keep-alive” for all requests, except for the last one in the flow.

To keep things simple, this example implements a test flow where we disconnect and reconnect after every request. Accordingly, all requests include a “Connection” header with the value “close”.

The table below summarizes the basic flow.

# Action Unit Template Notes
1 Connect N/A Connect to the target under test
2 Send Authentication Request Send the request to log in
3 Receive N/A The receive action has two Response Processing Rules assigned:

  1. Check if authentication was successful – if not, terminate the job
  2. Extract Session ID into a session variable (SessionID) so the request at #6 can access it
4 Disconnect N/A
5 Connect N/A Connect to the target under test
6 Send The Authenticated Request Submit the protected form
7 Receive N/A Please note, this action will be replaced by a Callback later as we are going to implement advanced response processing.
8 Disconnect N/A

Assuming you are already familiar with creating a Flow template and setting up basic Response Processing Rules, the Flow actions #1 through #6 are not going to be discussed further. What is definitely worth discussing in more detail is action #7 though.

To be continued…

Was this article helpful to you? Yes No