Authentication in scanned applications¶
Authentication verification mechanism¶
Performs periodic verification of session validity using the configuration in JSON format.
The configuration contains an array of criteria for verifying the validity of the session.
The mandatory fields are request, responseConditions with the nested mandatory fields url and statusCode respectively.
Regardless of its type, the criterion is considered fulfilled if and only if all the specified conditions are met. The number of verification rounds affects the authentication decision as follows:
- the criterion is considered
PASSED⇔ authentication is considered failed if the criterion is not fulfilled N times in a row; - the criterion is considered
FAILED⇔ authentication is considered failed if the criterion is fulfilled N times in a row.
Configuration¶
| Type | Default value | Valid values | Description |
kind * |
|||
| string | not specified | "FAILED", "PASSED" |
Indicates whether the criterion is met - authentication passed or not |
request.url * |
|||
| string | not specified | The absolute URL of the criterion subject request | |
request.method |
|||
| string | GET |
"GET", "HEAD", "OPTIONS", "TRACE", "PUT", "DELETE", "POST", "PATCH", "CONNECT" |
The method of the criterion subject request |
request.headers |
|||
| object | not specified | The criterion subject request headers in the key-value format ("Content-Type": "application/json") |
|
request.body |
|||
| string | not specified | The body of the criterion subject request | |
responseConditions.statusCode * |
|||
| integer | not specified | The HTTP status of the criterion subject response. Not equal ⇒ criterion not met | |
responseConditions.body |
|||
| string | not specified | The regular expression for criterion subject response body matching. Unmatched regexp ⇒ criterion not met | |
responseConditions.headers |
|||
| object | not specified | The (name, regexp) pairs for criterion subject response header matching. Any unmatched ⇒ criterion not met |
|
interval |
|||
| string | "10s" |
Any number with the s suffix |
The time interval between criterion checks using seconds, e.g. "0.5s", "1s", "10s" |
rounds |
|||
| integer | 5 |
The number of criteria checks to ensure that authorization has failed | |
* Fields marked with “*” are required.
Configuration example¶
[
{
"kind": "PASSED",
"request": {
"url": "http://api.e-shop.com/profile"
},
"responseConditions": {
"statusCode": 200,
"headers": {
"Content-Type": "application/json"
}
},
"interval": "7s",
"rounds": 3
},
{
"kind": "FAILED",
"request": {
"url": "http://api.e-shop.com/"
},
"responseConditions": {
"statusCode": 200,
"body": ".*Unauthorized.*"
},
"interval": "1s",
"rounds": 7
},
{
"kind": "FAILED",
"request": {
"url": "http://api.e-shop.com/"
},
"responseConditions": {
"statusCode": 403
},
"interval": "1s",
"rounds": 7
},
{
"kind": "PASSED",
"request": {
"method": "POST",
"url": "http://api.e-shop.com/endpoint/",
"headers": {
"Content-Type": "application/json"
},
"body": "{\"data\": \"here\"}"
},
"responseConditions": {
"statusCode": 200
}
}
]
Updating authentication data with an HTTP request¶
Periodic refreshing of sessions is performed using the JSON configuration. This only works in conjunction with the authentication verification mechanism.
This configuration describes how to perform an HTTP request to refresh a session in any of its manifestations, and the way to configure new authorization parameters with updated data.
Configuration¶
| Type | Default value | Valid values | Description |
request.url * |
|||
| string | not specified | The absolute URL of the session-refresh endpoint. This field is mandatory | |
request.method |
|||
| string | "GET" |
"GET", "HEAD", "OPTIONS", "TRACE", "PUT", "DELETE", "POST", "PATCH", "CONNECT" |
The HTTP method of the session-refresh endpoint |
request.headers |
|||
| object | not specified | The "key": "value" pairs which specify additional headers for a session-refresh request |
|
request.body |
|||
| string | not specified | A string representation of the HTTP body needed for a session-refresh request | |
request.timeout |
|||
| string | "10s" |
Any number with the s suffix |
The timeout configuration for session-refresh request using seconds, e.g. "0.5s", "1s", "10s" |
responseExtractors * |
|||
| array | not specified | Describes how the endpoint response is processed for a session update. An array, each element of which describes a single strategy of extraction | |
responseExtractors[].extractor * |
|||
| string | not specified | Contains a regular expression in RE2 format, corresponding to the extracted data for the current element of the responseExtractors array. This field is mandatory for each element of the responseExtractors array. The regular expression searches for matches in the response body and headers in the format Header-Key: Header-Value. The search continues until the first match, after which it stops |
|
responseExtractors[].proxyParams |
|||
| object | not specified | a description of the hook which will be added after successful data extraction. Field is an object, which allows the cookie, header, httpAuth and jsonReplacer keys. This field is mutually exclusive with responseExtractors[].placeholderVariableName |
|
responseExtractors[].proxyParams.cookie |
|||
| object | not specified | Valid keys: schema, hostname, port, path, name |
|
responseExtractors[].proxyParams.header |
|||
| object | not specified | Valid keys: schema, hostname, port, path, name |
|
responseExtractors[].proxyParams.httpAuth |
|||
| object | not specified | Valid keys: schema, hostname, port, path, username |
|
responseExtractors[].proxyParams.jsonReplacer |
|||
| object | not specified | Valid keys: schema, hostname, port, path |
|
responseExtractors[].proxyParams.[cookie,header,httpAuth,jsonReplacer].schema |
|||
| string | from base URL | The schema (network protocol) used for authentication in the scanned application | |
responseExtractors[].proxyParams.[cookie,header,httpAuth,jsonReplacer].hostname |
|||
| string | from base URL | Hostname in any valid variant: domain (including with subdomains), IPv4 or IPv6 | |
responseExtractors[].proxyParams.[cookie,header,httpAuth].path |
|||
| string | from base URL | The path for authentication in the scanned application | |
responseExtractors[].proxyParams.[cookie,header,httpAuth,jsonReplacer].port |
|||
| string | from base URL | "0"–"65535" |
The port number for authentication in the scanned application |
responseExtractors[].proxyParams.[cookie,header].name * |
|||
| string | not specified | The name of the header or the cookie whose values will be replaced by the extracted data | |
responseExtractors[].proxyParams.httpAuth.username * |
|||
| string | not specified | Describes the username for HTTP Basic where the extracted data will be replaced by a password | |
responseExtractors[].proxyParams.jsonReplacer.path * |
|||
| string | from base URL | Describes the path to the JSON keys to change the values using the extracted data | |
responseExtractors[].placeholderVariableName |
|||
| string | not specified | The name of the key where the extracted data will be stored. This data will be used in the next session-refresh request in the relevant templated parts of the HTTP request. Use case: changing the refresh token after each session refresh. This field is mutually exclusive with responseExtractors[].proxyParams |
|
responseExtractors[].valueTransformationTemplate |
|||
| string | not specified | Describes the context corresponding to the {{ .Matched }} placeholder, the templated part of which is substituted for the extracted data. This context is displayed in the HTTP request to update the session in the placeholder corresponding to the responseExtractors[].placeholderVariableName value. Usage example: The extracted data should be used in the Authorization header, but the value is returned without the Bearer prefix. The context will look like Bearer {{ .Matched }} |
|
placeholdersInitValues |
|||
| object | not specified | Contains "key": "value"pairs which will be used in the template rendering of the request field of the HTTP request. All key-value pairs must be filled in with initial values which will be used during the first session-refresh request. For other session-refresh requests, values will be rewritten using the extracted data with the corresponding responseExtractors[].placeholderVariableName key |
|
dropHooksBeforeRefreshRequest |
|||
| boolean | false |
true, false |
Indicates whether to remove authentication data (proxy hooks) retrieved by the refresher before executing next HTTP request for a refresh |
* Fields marked with “*” are required.
Configuration examples¶
{
"request": {
"url": "http://example.com/login",
"method": "POST",
"body": "login=admin&password=secretpass"
},
"responseExtractors": [
{
"extractor": "Set-Cookie:.*session_token=(.*);",
"proxyParams": {
"cookie": {
"name": "session_token"
}
}
}
]
}
{
"request": {
"url": "http://api.example.com/refresh-with-token",
"method": "POST",
"body": "{\"authData\": {\"refreshToken\": \"{{ .RefreshToken }}\"}}"
},
"responseExtractors": [
{
"extractor": "{\"token\": \"(.*)\",}",
"proxyParams": {
"header": {
"name": "X-Auth",
"hostname": "api.example.com"
}
}
},
{
"extractor": "\"authData\": {\"refreshToken\": \"(.*)\"}",
"placeholderVariableName": "RefreshToken"
}
],
"placeholdersInitValues": {
"RefreshToken": "c2712990-ec19-414b-8be0-8a66e9271253"
}
}
{
"request": {
"url": "http://example.com/refresh-with-token",
"method": "POST",
"body": "{\"authData\": {\"refreshToken\": \"{{ .RefreshToken }}\"}}"
},
"responseExtractors": [
{
"extractor": "{\"token\": \"(.*)\"}",
"proxyParams": {
"header": {
"name": "Authorization"
}
},
"valueTransformationTemplate": "Bearer {{ .Matched }}"
},
{
"extractor": "\"authData\": {\"refreshToken\": \"(.*)\"}",
"placeholderVariableName": "RefreshToken"
}
],
"placeholdersInitValues": {
"RefreshToken": "c2712990-ec19-414b-8be0-8a66e9271253"
}
}
Updating authentication data with browser script¶
Periodic refreshing of sessions is performed using the JSON configuration and the browser script, recorded with Chrome DevTools Recorder. An entity called a browser authenticator executes a browser script, then transmits the Cookie and the browser's local storage status at the time of script completion to the scanner. The configuration file should describe how the received Cookie and local storage will be used in the updated authentication data. It only works in combination with the authentication verification mechanism. It is mutually exclusive with the mechanism for updating authentication data with an HTTP request.
Configuration¶
The configuration regulates the execution of the browser script and describes how to configure new authentication parameters with updated data.
| Type | Default value | Valid values | Description |
browserAuthenticatorName |
|||
| string | "fuchsia-browser-authenticator" |
Base name of the browser authenticator executable file. It is recommended to leave this field empty. The required value is set by default | |
loginScript |
|||
| object | not specified | An object which describes the browser script. When creating a scan via fuchsiactl, it is recommended not to fill in this field and use the --file=@browserAuthenticator:loginScript@/path/to/script.jsonScanning via the HTTP API is only possible with a key indicating the location of the file. When running via the dashboard, this field is filled in by uploading the script file in the parameters of the scanned target |
|
outputExtractors * |
|||
| array of objects | not specified | Describes how to handle new Cookie and local storage for session updates. This is an array, each element of which describes one single data extraction strategy | |
outputExtractors[].type * |
|||
| string | not specified | "TYPE_COOKIE""TYPE_LOCAL_STORAGE" |
Data source type |
outputExtractors[].selectors |
|||
| array of strings | not specified | An array of Cookie names or local storage keys that must be present to the browser authenticator after the browser script is executed. If the array is not empty, then if at least one of its elements is missing in the browser authenticator output, the authentication data update will be considered failed. Required if the outputExtractors[].extractSelectorsOnly |
|
outputExtractors[].extractSelectorsOnly |
|||
| boolean | false |
true, false |
A flag indicating whether to take all the data from the browser authenticator output or only those which matched the selectors. The true value is valid only if the outputExtractors[].selectors |
outputExtractors[].proxyParams |
|||
| object | depends on data source type | A description of the authentication mechanism that will be added after successful data extraction.
|
|
outputExtractors[].proxyParams.[cookie,header].name * |
|||
| string | not specified | The name of the header or the name of the cookie file, the values of which will be replaced by the extracted data | |
outputExtractors[].proxyParams.httpAuth.username * |
|||
| string | not specified | The username for basic HTTP authentication, for which the extracted data will be replaced with a password | |
outputExtractors[].proxyParams.jsonReplacer.path * |
|||
| string | not specified | Specifies the path for replacing values in the JSON bodies of outgoing scanner requests. It is applied only if the following conditions are met simultaneously:
|
|
responseExtractors[].valueTransformationTemplate |
|||
| string | not specified | It is supported only if the following conditions are met simultaneously:
go text/templateoutputExtractors[].proxyParamsThe keys of the pairs extracted from the local storage act as placeholders. For example, the token extracted by the key "authToken" must be inserted into the header as follows: Authorization: Bearer <token>Bearer: {{ .authToken }}outputExtractors[].proxyParams{"header": {"name": "Authorization"}} objectYou can use more than one placeholder. It is strongly recommended to use the {{ index . "some-name" }} form-” is a service character, therefore, in the Bearer: {{ .some-name }} |
|
* Fields marked with “*” are required.
Configuration examples¶
-
Retrieving all Cookie if there is at least one named “
token” among them:
-
Extracting a Cookie named "
token”, if present:
-
Extracting all Cookie. Extracting local storage and transferring it to browser modules. Extracting the values for the
token_secret_nameandtokenkeys from the local storage and passing them to theAuthorizationheader according to the template. Failure for the entire update if at least one value was not found:{ "output_extractors": [ { "type": "TYPE_COOKIE" }, { "type": "TYPE_LOCAL_STORAGE" }, { "type": "TYPE_LOCAL_STORAGE", "selectors": ["token_secret_name", "token"], "extractSelectorsOnly": true, "proxy_params": { "hostname": "example.com", "scheme": "https", "port": "443", "header": { "name": "Authorization" }, "value_transformation_template": "Bearer {{ .token_secret_name }}||{{ .token }}" } } ] }
Recording a browser script¶
Google Chrome browser is required to record the browser script. The sequence of actions is described in the Chrome Developer Documentation. In this section, it is specified in order to obtain the highest quality script recording.
The following is used as a demonstration example: http://juiceshop.stands.appsecuritytesting.fun/.
- Open the Google Chrome browser in incognito mode.

- Press “F12” to open Chrome Developer Tools → click “⋮” in the upper right corner → select “More Tools” → press “Recorder”.

- Press “Create a new recording”.

- Enter a name for the future script and press “Start recording”.

- Go to the authentication page, enter the required credentials, log in, and press “End recording”.

- Export the resulting record in JSON format.

The resulting file is a browser script required to update the scan authentication data.