External Command Authentication

Overview

If you have your own script to perform authentication to your application, HawkScan can use that script to authenticate. For example, a bash script that runs a curl command to your authentication server.

To support this type of authentication, HawkScan supports externally supplying authorization scripts with the authentication.externalCommand configuration.

The authentication section of the stackhawk.yml will have 3 parts:

  1. Logged in/out indicators
    • How HawkScan checks it is logged in throughout the scan.
  2. Auth(N)
    • Using authentication.externalCommand to tell HawkScan the command to run.
  3. Test Path
    • How HawkScan sees if it successfully logged in

Make sure your file has all 3 of these parts filled out.

YAML for Eternal Command Credentials

Running shell script:

stackhawk.yml

app:
  applicationId: xxXXXXXX-xXXX-xxXX-XXxX-xXXxxXXXXxXX
  env: Test
  host: ${APP_HOST:http://localhost:3000}
  authentication:
    # Paths that HawkScan checks to see if it is still logged in during the scan
    loggedInIndicator: "HTTP.*2[0-9][0-9]\\s*O[kK](\\s*)|HTTP.*3[0-9][0-9].*" # Change me
    loggedOutIndicator: "HTTP.*4[0-9][0-9](\\s*)Unauthorized.*" # Change me
    # Auth(N) External Command - this example will result in 2 cookies based upon the specified shell script.
    externalCommand:
      # Command to run process, in this case a shell script.
      command: "sh"
      # Optional list of parameters that will be added to the specified command.
      parameters:
        - "-c"
        - "./multi-cookie.sh"
    # A path that can only be seen when successfully logged in. HawkScan will check this path to see if log in was successful.
    testPath:
      path: /mysettings
      success: ".*200.*"
      requestMethod: GET

YAML Sections in Detail

Injecting Authorization with .externalCommand

The first half of your authentication section in your stackhawk.yml will be to tell HawkScan you are using an externally supplied command.

The .comamnd should be the first arguement of the command you wish to run e.g. sh or python.

The .parameters section is an optional list of parameters to add to the command. In this case it specifies what shell script to run.

stackhawk.yml

app:
  applicationId: xxXXXXXX-xXXX-xxXX-XXxX-xXXxxXXXXxXX
  env: Test
  host: ${APP_HOST:http://localhost:3000}
  authentication:
    loggedInIndicator: "\\QLog out\\E"
    loggedOutIndicator: "\\QLog in\\E"
    externalCommand:
      # Command to run process, in this case a shell script.
      command: "sh"
      # Optional list of parameters that will be added to the specified command.
      parameters:
        - "-c"
        - "./multi-cookie.sh"
    testPath:
      path: /authenticated/path
      success: '.*200.*'

Expected Output From External Command

External command authentication does not require an additional authorization type. The command will be automatically re-run when HawkScan determines the user is logged out.

HawkScan will inject headers and/or cookies specified in the output of the external command. To specify authentication tokens the output must conform to this standard.

{
  "headers" :
    [
        {"header1Name" : "header1Value" },
        {"header2Name" : "header2Value" }
    ],
  "cookies" : 
  [
        {"cookie1Name" : "cookie1Value" },
        {"cookie1Name" : "cookie2Value" }
  ]
}

It can be a combination of headers and cookies or just one or the other. With an array of tokens with name/value pairs.

Test Paths and Logged In/Out Indicators

No matter what type of Authorization/Authentication your app is using, HawkScan requires .testPath, .loggedInIndicator and .loggedOutIndicator.

Test Path:

A testPath configuration needs to be provided to verify HawkScan authenticated its session correctly before scanning the application. The testPath configuration also provides requestMethod and requestBody options to support alternate HTTP request verbs, such as POST or PUT. The default action is GET.

Your testPath should be a path that HawkScan can only access when successfully logged in. This could be a path like “/dashboard” or “/accountdetails”

stackhawk.yml

app:
  applicationId: xxXXXXXX-xXXX-xxXX-XXxX-xXXxxXXXXxXX
  env: Test
  host: ${APP_HOST:http://localhost:3000}
  authentication:
    loggedInIndicator: "\\QLog out\\E"
    loggedOutIndicator: "\\QLog in\\E"
    testPath:
      path: /login-multi-check
      success: ".*200.*"
      requestMethod: GET

Logged In/Out Indicators

Throughout the scan, HawkScan will check to see if it is still logged in by the .loggedInIndicator and .loggedOutIndicator. These are regex strings to match against http responses from requests in the web application.

A .loggedInIndicator could be a “Log Out” or “Sign Out” button a user would see if logged in. An example of a .loggedOutIndicator would be a “Log In” button on the sign-in page. These can also leverage http status codes from the response.

stackhawk.yml

app:
  applicationId: xxXXXXXX-xXXX-xxXX-XXxX-xXXxxXXXXxXX
  env: Test
  host: ${APP_HOST:http://localhost:3000}
  authentication:
    loggedInIndicator: "HTTP.*2[0-9][0-9]\\s*O[kK](\\s*)|HTTP.*3[0-9][0-9].*"
    loggedOutIndicator: "HTTP.*4[0-9][0-9](\\s*)Unauthorized.*"
    testPath:
      path: /authenticated/path
      success: '.*200.*'

In the above complete configuration we are specifying running bash -c ./multi-cookie.sh to authenticate a user.

The following is the bash script for multi-cookie.sh.

Example Bash Script For stackhawk.yml

#!/bin/bash

# Request login (XLOGINID) and session (JSESSIONID) cookies from server
curl -k  -c  cookie-jar.txt https://localhost:9000/login-code
# Set local JSESSIONID variable to the JSESSIONID cookie
JSESSIONID=$(awk 'match($0, /JSESSIONID.*/){print substr($0, RSTART + 11, RLENGTH)}' cookie-jar.txt )
# Set local XLOGINID variable to the XLOGINID cookie
XLOGINID=$(awk 'match($0, /XLOGINID.*/){print substr($0, RSTART + 9, RLENGTH)}' cookie-jar.txt)
# Request page with XLOGINID and JSESSIONID cookies and extract the _csrf token
CSRF=$(curl -k  -b  cookie-jar.txt \
    https://localhost:9000/login-form-multi | awk 'match($0,/_csrf".*/) { print substr($0, RSTART+14, RLENGTH -17)}')
# Log into the mutli cooke endpoint using XLOGINID and JSESSIONID cookies and username/password
curl -v -k  \
  -d "_csrf=${CSRF}&loginCode=${XLOGINID}&username=user&password=password&remember=on"  \
  -b  cookie-jar.txt \
  -H  "Content-Type: application/x-www-form-urlencoded" \
  "https://localhost:9000/login-form-multi"

echo "{  \"cookies\" : [{ \"JSESSIONID\" : \"${JSESSIONID}\", \"XLOGINID\" : \"${XLOGINID}\"}] }"

This will output:

{
  "cookies" : 
  [
        {"JSESSIONID" : "CDDC53E08070E78BF0A8C8F240B2157E" },
        {"XLOGINID" : "a30c2167-87c4-4905-9554-66e58a64289c" }
  ]
}

The two cookies will be injected into every request HawkScan makes and then call the test path.

Authorized GET Request to /login-multi-check

GET /login-multi-check HTTP/1.1
Host: localhost:9000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/114.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Cookie: JSESSIONID=CDDC53E08070E78BF0A8C8F240B2157E; XLOGINID=a30c2167-87c4-4905-9554-66e58a64289c