HMAC Authentication via Scripting in Invicti Standard
Hash-based Message Authentication Code (HMAC) is used for both an integrity and an authenticity check based on symmetric cryptography.
The target web application’s client and server share a secret key and an application id that are used to calculate a hash code that signs and then verifies HTTP requests:
- Clients use this secret key and application id to sign every HTTP request sent to the server.
- The server then uses the same secret key and application id to verify that requests belong to that client and have not changed while being transmitted to the server (MiTM attack).
Invicti exposes its request object, which allows users to modify HTTP request headers using this scripting feature.
Postman, the API development platform, also has a similar feature that allows users to write pre-request scripts. If a Postman export file is imported into Invicti, pre-request scripts will be imported too.
Although it varies by implementation, most of HMAC implementations use the HTTP method, request path, query string, timestamp and payload data to calculate the signature. Invicti exposes all these properties in the scripting API.
Invicti’s scripting API provides SHA512 and SHA256 hash functions to enable you to calculate a request hash.
Sample Postman Pre-Request Script
A simple Postman pre-request script, such as the one defined below, can be used by Invicti to compose the HMAC header. This header will be added to all request headers sent by Invicti:
function getPath(url) {
var pathRegex = /.+?\:\/\/.+?(\/.+?)(?:#|\?|$)/;
var result = url.match(pathRegex);
return result && result.length > 1 ? result[1] : '';
}
function getQueryString(url) {
var arrSplit = url.split('?');
return arrSplit.length > 1 ? url.substring(url.indexOf('?')+1) : '';
}
function getAuthHeader(httpMethod, requestUrl, requestBody) {
var CLIENT_KEY = 'REPLACE_WITH_YOUR_CLIENT_KEY';
var SECRET_KEY = 'REPLACE_WITH_YOUR_SECRET_KEY';
var AUTH_TYPE = 'HMAC-SHA512';
var requestPath = getPath(requestUrl);
var queryString = getQueryString(requestUrl);
if (httpMethod == 'GET' || !requestBody) {
requestBody = '';
} else {
requestBody = JSON.stringify(requestBody);
}
var hashedPayload = CryptoJS.enc.Hex.stringify(CryptoJS.SHA512(requestBody));
var timestamp = new Date().toISOString().split('.')[0]+"Z";
var requestData = [httpMethod, requestPath, queryString, timestamp, hashedPayload].join("\n");
var hashedRequestData = CryptoJS.enc.Hex.stringify(CryptoJS.SHA512(requestData));
var hmacDigest = CryptoJS.enc.Hex.stringify(CryptoJS.HmacSHA512(hashedRequestData, SECRET_KEY));
var authHeader = AUTH_TYPE + ' timestamp=' + timestamp + ",
client=" + CLIENT_KEY + ', signature=' + hmacDigest;
return authHeader;
}
invicti.setEnvironmentVariable('hmacAuthHeader', getAuthHeader(request['method'],
request['url'], request['data']));
- In the example, between the lines 25-38,
the request method, path, query string
andtimestamp
values generate a payload. This payload is used to calculate the hash of the request. The secret key is used as the key of the SHA-512 hash function. - After calculating the hash, an authentication header is built in line 34-37 by concatenating the following items:
- The name of the hash function used
- The timestamp when the hash is calculated
- The client key provided by the server
- The output of the hash function
These values form the hmac authentication header. On line 41, this value is assigned to a Postman variable named hmacAuthHeader
. To use this variable as an authentication header, add an Authentication header to Invicti and set its value to ‘{{hmacAuthHeader}}’. Double curly braces means that this value is not constant. It is simply a placeholder that Invicti will find and replace.
For further information, see Configuring Header Authentication in Invicti Standard
How to configure HMAC Authentication via Scripting in Invicti Standard
- Open Invicti Standard.
- In the Start New Scan dialog, select Pre-Request Scripts.
- Select the Enabled checkbox.
- From the Presets drop-down, select HMAC.
- From the Authentication section, select Header.
- Add an Authorization header with the value: {{hmacAuthHeader}}. This is a placeholder whose value will be calculated from the pre-request script just before every request made from Invicti.