Support
Scans

Custom Security Checks via Scripting

This document is for:
Invicti Standard, Invicti Enterprise On-Premises, Invicti Enterprise On-Demand

The Custom Security Checks feature in Invicti Enterprise lets you enhance its vulnerability detection capabilities by writing scripts. These scripts can define attack patterns, analyze HTTP responses, and identify potential vulnerabilities. Custom Security Checks can be classified into four categories:

For further information, refer to Working with Custom Scripts for Security Checks.

Active Security Checks

Active security checks in Invicti Enterprise allow you to define custom attack patterns. These patterns are injected into parameters identified by the crawler, with each attack pattern generating an HTTP request for each discovered parameter. You can also filter which types of parameters the attack pattern targets, such as choosing to attack only JSON parameters while excluding querystring or POST body parameters.

Once the Invicti attacker sends the request and receives the response, you can analyze whether the HTTP response is vulnerable and if the injected attack pattern triggered a vulnerability.

Here is a sample script:

var attacks = [
 {
   
id: '8613F6DB-9AD2-4E45-9B8F-308C810FF7DB',
   
name: 'My New Pattern',
   
attack: '%27AND+1%3dcast(0x5f21403264696c656d6d61+as+varchar(8000))+or+%271%27%3d%27',
   
attackUsage: AttackUsages.Json + AttackUsages.Xml
 }
];

function analyze(context, response) {
 
if (response.Body.indexOf('iNj3Ct3D') > -1) {
   
return new Vulnerability(VulnerabilityType.PossibleSqlInjection);
 }
}

The first line of the script defines an array called attacks which contains the attack pattern objects. The attack patterns may have the following properties defined:

  • id (required): This is a unique identifier in GUID format. You can generate them using Online GUID Generator.
  • name (required): This is the name of the pattern. It is displayed in the Scan Policy Editor.
  • attack (required): This is the attack pattern that is injected into the parameters.
  • attackUsage: This is the type of the parameter into which the attack will be injected. You can combine multiple values using the addition symbol. See the AttackUsages enumeration in the API docs. It defaults to AttackUsages.QueryPost (querystring and post parameters).
  • attackEncoded: This is a boolean property that denotes if the attack is already encoded, and therefore does not need to be encoded according to the current parameter context (for example, URL encode, XML encode). It defaults to false.

The second line of the script contains the analyze function that is executed for every response to the attack request made during the scan. You can conduct your analysis within this method and choose to return a new Vulnerability instance. The function has two parameters: context and response:

  • The context variable contains information about the active attack context, such as the vulnerable Parameter and the Request instance.
  • The response variable represents the HTTP response that was returned from the web server in response to the attack request that contained the attack pattern.

Passive Security Checks

Passive security checks do not issue any extra HTTP requests during scans. For each HTTP request that the crawler has discovered, you can write passive security check scripts to analyze the response. If the response contains any vulnerable information, this will enable you to detect a new vulnerability.

Here is a sample script:

var attacks = [
 {
   
id: '0652A43B-6B73-4CF5-9A49-397AA73DEBE6',
   
name: 'My New Pattern',
 }
];

function analyze(context, response) {
 
if (response.Body.indexOf('java.io.FileNotFoundException:') > -1) {
   
return new Vulnerability(VulnerabilityType.ProgrammingErrorMessages);
 }
}

The analyze function is executed against each HTTP response that the crawler has received. The function takes two parameters: context and response:

  • The context variable contains information about current passive analysis context, for example whether the scan is currently in the ReCrawl phase, or the IdentificationSource of the request.
  • The response variable represents the HTTP response returned from the web server to the crawling request.

Singular Security Checks

These checks are executed once for each scan. You are able to analyze the response of the Target URL that scan has started and raise vulnerabilities.

Here is a sample script:

var attacks = [
 {
   
id: 'F4A90B2C-CB27-4849-88AF-DE27DEEF58BA',
   
name: 'My New Pattern',
 }
];

function analyze(response) {
 
if (response.Headers['Server'].indexOf('Apache') > -1) {
   
return new Vulnerability(VulnerabilityType.ApacheIdentified);
  }
}

The analyze function is executed against the HTTP response of the request to the Target URL. The function takes a single parameter, response. The response variable represents the HTTP response returned from the web server in response to the Target URL request.

Per-Directory Security Checks

These checks are very similar to Active Security Checks, but they work once for all directories (URL segments). Generally, you should write Per-Directory Security Checks if you want to check for the existence of certain files in the directories of the target web application, for example resources that are not linked anywhere on the web application.

Here is a sample script:

var attacks = [
 {
   
id: '5664f8d7-11b1-4c4b-a3d7-513e5b45771b',
   
name: 'web.config detection',
   
attack: 'web.config',
 }
];

function analyze(context, response) {
 
if (response.Body.indexOf('<connectionStrings>') > -1) {
   
return new Vulnerability(VulnerabilityType.WebConfigIdentified);
 }
}

The attacks array and analyze function work very similar to Active Security Checks. The only difference is that the attackUsage value of the attack patterns defaults to AttackUsages.FullUrl. This is required to ensure the attacker appends the attack patterns to the end of each directory URL.

Helper Functions

The Custom Checks JavaScript environment includes the following helper functions.

netsparker.request

The netsparker.request function helps you create HTTP requests. There are two overloads to this function, and you can either add a string parameter or a Request parameter to this function. The function returns a Response instance containing the HTTP response information that has been retrieved.

// The following makes a GET request to the specified URL
var res = netsparker.request('http://example.com/page.htm');

// The following makes a POST request, sets a parameter and a header
var request = new Request('http://example.com/action');
request.Parameters.Add(
new Parameter('foo', 'bar', ParameterType.Post));
request.Headers.Add(
'X-CustomHeader', 'quux');
var res = netsparker.request(request);

netsparker.rawRequest

Although netsparker.request helps us to create an HTTP request through its properties and method, it is also possible to craft an HTTP request or use a raw HTTP request through netspaker.rawRequest method. This gives more control over the request we created. For example, it is possible to send non-rfc compliant HTTP requests which is not possible while using netsparker.request.

var raw =  `GET /artist.php?id=test HTTP/1.1

Host: php.testsparker.com

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9

Accept-Encoding: gzip, deflate

Accept-Language: en-US,en;q=0.9

`;

var response = netsparker.requestRaw("http://php.testsparker.com/", raw, false);

If you send a GET or HEAD request meaning a bodiless request, you must ensure that there is a single empty line after the HTTP headers.

logUI

The logUI function logs a message to the Logs panel in Netsparker Standard.

logUI('Hello World!');

log

The log function logs a message to the scan log file (nstrace.csv). The log message severity is Information. So, in order to be able to see this message in the log file, set logging options to Information level.

log('Performing the HTTP request.');

logInfo

The logInfo function logs a message to scan log file (nstrace.csv). The log message severity is Information. So, in order to be able to see this message in the log file, set logging options to Information level.

logInfo('Performing the HTTP request.');

logWarn

This logWarn function logs a message to the scan log file (nstrace.csv). The log message severity is Warning. So, in order to be able to see this message in the log file, set logging options to Warning level.

logWarn('Looks like the server is taking too long to respond.');

logError

This logError function logs a message to the scan log file (nstrace.csv). The log message severity is Error. So, in order to be able to see this message in the log file, set logging options to Error level.

logError('An unexpected error has occurred.');

Sample Scripts (Cookbook)

Here are some sample scripts you may use. More will be added later.

How can I add Custom Fields to a Vulnerability?

var vulnerability = new Vulnerability(VulnerabilityType.PossibleSqlInjection);
vulnerability.CustomFields.Add(
'Foo', 'Bar');