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 via Scripting feature allows you to extend Invicti Standard’s vulnerability detection capabilities. It works by allowing you to write scripts that provide attack patterns, analyze HTTP responses, and detect potential vulnerabilities.

You can create custom security checks in the four categories:

  1. Active
  2. Passive
  3. Singular
  4. Per-Directory

To see the custom script documentation, see Custom Scripting API Docs.

Active Security Checks

Active security checks in Invicti allow you to define the attack patterns. The Invicti attacker will then inject these attack patterns into parameters discovered by the crawler. Each attack pattern you have provided will result in an HTTP request for each parameter discovered by the crawler. You have the option to filter the type of parameters that the attack pattern will be injected, for example you may elect to attack only JSON parameters but not querystring or POST body parameters.

After the Invicti attacker carries out the request and receives a response, you will be able to determine whether the HTTP response is vulnerable, and whether the injected attack pattern caused 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 current 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.

invicti.request

The invicti.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 = invicti.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 = invicti.request(request);

invicti.rawRequest

Although invicti.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 invicti.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 = invicti.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 Invicti 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 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.

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');

Invicti Help Center

Our Support team is ready to provide you with technical help.

Go to Help Center This will redirect you to the ticketing system.