All Collections
Authenticated Scanning
Authenticating HawkScan to applications using login forms
Authenticating HawkScan to applications using login forms

How to authenticate HawkScans to applications by sending a form-encoded POST with Anti-CSRF token

Anthony Stinn avatar
Written by Anthony Stinn
Updated over a week ago

Overview

HawkScan's usernamePassword configuration includes a FORM type option which submits credentials via form-encoded POST to the target application.

Configuring form authentication may also involve:


Procedure

Step 1: Determine whether an Anti-CSRF parameter is in place

Login forms often include an Anti Cross Site Request Forgery (ACSRF) parameter to safeguard against intruders making form submissions in place of the intended client.

A common method for CSRF protection is a synchronizer token -- a unique known only to you and the server that corresponds to a unique session or render of the page. The server uses this value to verify that you (the client) are the person who submitted this form (not an intruder). If a ASCRF token is in place, you'll need the scanner to obtain and submit its value alongside your login credentials.

To find this value, use your browser's developer tools (e.g., right click-->Inspect in Chrome) and find the hidden parameter on the login form.

For instance, in the javaspringvulny application, the ACSRF parameter is input type="hidden" name="_csrf" value="e8fb0107-cc4c-42dd-bf1b-3d548a3629f6:

<form action="/login" method="post"><input type="hidden" name="_csrf" value="e8fb0107-cc4c-42dd-bf1b-3d548a3629f6">
<div class="form-group">
<label for="username">Username</label>
<input type="text" class="form-control" name="username" id="username" aria-describedby="usernameHelp" placeholder="Enter Username" autocomplete="off" style=[...]">
<small id="usernameHelp" class="form-text text-muted">The username of your search account.</small>
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" class="form-control" id="password" name="password" placeholder="Password" autocomplete="off" style=[...]>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>

Note that the value for the _csrf parameter is unique to your session.

Note the name of this value -- you'll be configuring it in app.antiCsrfParam (in addition to the usernamePassword configuration).

Step 2: Determine the login fields

Also in the form HTML above are the input type fields which correspond to the credential types that you'll configure in usernamePassword.usernameField and usernamePassword.passwordField. Note these values in your login form HTML.

In the above example, these fields are username (name="username") and password (name="password").

Step 3: Validate which AuthZ mechanism is in place

Cookies are a common means of authorization (AuthZ) in a form login context, though other means are possible as well (notably, tokens).

With developer tools on, log into your application and note the authorization values in the network traffic between the browser and the application.

In the case of javaspringvulny, the AuthZ mechanism is the JSESSIONID cookie that can be seen in the Set-Cookie header in the response to a successful login:

Note the name of the cookie(s) returned -- you'll configure these later.

Step 4: Determine a test path

Identify a path in the application that can only be accessed while authenticated.

Then, determine how to identify a successful request (for instance, the application returns an HTTP 200 OK status code when receiving a GET to the page which includes the AuthZ mechanism).

In javaspringvulny's case, the /search page requires authentication, and will return a 200 OK if authenticated (or a 302 redirect to the /login page if not authenticated).

You'll configure either the success or fail field with a regex value that matches what you're looking for in a response from the application.

Step 5: Configure the scanner

Now that you've obtained the various login components, it's time to configure them in stackhawk.yml.

Here's how they all slot into the form auth configuration for javaspringvulny:

app:
applicationId: ${APP_ID:dacc7d3e-babc-47d2-b040-ab117ab04526}
env: ${APP_ENV:dev}
host: ${APP_HOST:https://localhost:9000}
antiCsrfParam: "_csrf"
authentication:
loggedInIndicator: "\\QSign Out\\E"
loggedOutIndicator: ".*Location:.*/login.*"
usernamePassword:
type: FORM
loginPath: /login
loginPagePath: /login
usernameField: username
passwordField: password
scanUsername: ${USERNAME}
scanPassword: ${PASSWORD}
cookieAuthorization:
cookieNames:
- "JSESSIONID"
testPath:
path: /search
success: "HTTP.*200.*"

When the scanner is run with the above configuration, the follow occurs in sequence:

  1. Visit the /login page with a GET and obtain the _csrf token value (from the loginPagePath config)

  2. Perform a form-encoded POST to the /login page containing:

    1. _csrf=(value obtained from the initial loginPagePath GET)

    2. username=(username value passed to the scanner as the environment variable USERNAME)

    3. password=(password value passed to the scanner as the environment variable PASSWORD)

  3. Visit the /search page using the default method (GET); send the JSESSIONID cookie value in the Cookie header (Cookie: JSESSIONID=<value>)

    1. if an HTTP 200 (OK) message is found in the login response headers or body, proceed with the scan

    2. if no string in the response headers or body matches the success value, terminate the scan with an authentication error

  4. Proceed with scanning the application

    1. monitor the state of JSESSIONID throughout

    2. if loggedInIndicator / loggedOutIndicator indicate that the scanner is logged out, re-authenticate with the application then proceed with the scan

Note: See Environment Variable Runtime Overrides for details on injecting credentials or other configuration values at runtime.


Auth Request Structure

Relevant request headers:

The login request will include this header:

content-type: application/x-www-form-urlencoded

Request body examples:

The POST body will be comprised of the values you've configured. For instance:

No AntiCsrfParam / no additional params:

<username_field>=<password>&<password_field>=<pasword>

AntiCsrfParam configured / no additional params:

<csrf_token_name>=<csrf_token_value>&<username_field>=<username>&<password_field>=<password>

AntiCsrfParam configured / additional params configured:

(additional param config):

otherParams:
- name: "remember_me"
val: "true"

Resulting POST body:

<csrf_token_name>=<csrf_token_value>&<username_field>=<username>&<password_field>=<password>&remember_me=true


Additional Information

Form Auth Demo:

Scanning the javaspringvulny application using form-encoded authentication:

Authenticated Scanning Primer

For a general overview on the concepts mentioned above, see Getting Started Guide: Authenticated Scanning.

Different Form Types

Not all login forms generate form-encoded POST's. For instance, your login form(s) may utilize JSON payload (content-type: application/json) instead. In the application/json scenario, you may be able to either:

Did this answer your question?