Creating a WAYPOINTS template

From your Nova Security account, it is easy to define a WAYPOINTS template. It is also equipped with a powerful real-time JSON & YAML validator, converter and editor.

To create your template, navigate to /scanners/waypoints/templates/new.

Defining your first template

Last week, the developer operations team created an internal report about a full-read Server-Side Request Forgery (CWE-918) that was found in one of their code-bases.

The security issue got resolved but since the same underlying code got used for other web apps in your organisation, you were tasked to look for any other affected systems.

I know, quite chaotic but luckily you got WAYPOINTS to do the job seamlessly. So no worries, I will help you until you’ve found every possible vulnerable web application.

We are going to create a WAYPOINTS template that should match all the conditions mentioned in the following report:

Report Title

Full-read Server-Side Request Forgery on REDACTED

Severity

Critical

CWE ID

CWE-918 - Server-Side Request Forgery (SSRF)

Status

Critical

Report Info

Any external user is able to reach internal-only resources or make external HTTP requests on behalf of the server. The file:/// protocol seems also to be supported opening up the possibility to read local files.

Proof of Concept:

proof-of-concept.txt
GET /api/documents/document-loader?document_URI=http://localhost:8080
Host: {HOST}
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36

Template

Metadata

Let’s first start off by giving our template a name, assign a severity & CWE Id and categorize it by tagging the template.

Template Name

The template name (with property template.metadata.name) field is used to, well, specify a name for your template. This field is also later used to help identify your template in your vulnerability report and support ticket(s).

In this case, you could set the name to SSRF Check.

Template Severity

Next up, we got the template severity. You can assign a corresponding severity to each of your templates. This will reflect in your vulnerability reports and support tickets.

In this example, we’ve already determined that the severity is Critical.

Template Common Weakness (CWE) ID

You can also assign a corresponding CWE ID to your template. This will be used in your vulnerability reports and support tickets as well but also help Nova Security Scanner provide you mitigation steps that you can follow.

This template is for a Server-Side Request Forgery, which corresponds to CWE ID CWE-918 - Server-Side Request Forgery (SSRF).

Template Description

The template description is to provide more information about your template. It is later also reflected in your (exported) vulnerability reports and any assigned support tickets.

In this example, you can set the report description as the template description:

Report Info

Any external user is able to reach internal-only resources or make external HTTP requests on behalf of the server. The file:/// protocol seems also to be supported opening up the possibility to read local files.

Template Tags

Template tags are a way to help you categorize your templates. This can be helpful in case you need to batch several templates together and run all of them at once against a list of hosts.

You can assign any type of tag that would help you categorize your template. In this case, I’ve used SSRF and private as I’m building my own collection of private templates as well.

You can specify up to 5 separate template tags. The “DEFAULT” template tag is reserved.

Request

Here’s where we define our template’s request to instruct WAYPOINTS on what to do.

Request HTTP Method

We can set the HTTP Method to any supported method. By default it is set to GET.

Our proof of concept requires us to send a GET HTTP request, this means that you can leave the option as it is.

Request Path

In the path field, we can set the URL path that we want to hit. The {PATH} and {CANARY_TOKEN} positional argument are also supported.

Our example requires us to set the template’s path to /api/documents/document-loader?document_URI=http://localhost:8080.

You can set up to 5 separate URI paths at once for WAYPOINTS to make requests to. The positional {PATH} and {CANARY_TOKEN} arguments are also supported to adopt the URI path from the list of live hosts up on launching a WAYPOINTS scan or to inject your own OAST Server’s canary token in your request.

Request Headers

We can also instruct WAYPOINTS to send HTTP request headers with our requests.

Our example only requires us to send the User-Agent request header, this is probably to evade certain web application firewall rules that block requests coming from clients with an unrecognized/unfamiliar user agent (basically, bots).

You can set the field to: User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36;;.

You must separate each request header with a double semi-colon character (”;;”) if you want to specify multiple request headers.

Request Body

The request body field is used to instruct WAYPOINTS to send any type of request body with each HTTP requests.

WAYPOINTS is capable of parsing & validating response bodies before sending HTTP requests to ensure the server receives them correctly. Make sure to set a Content-Type in the request headers field.

Matchers

Here’s where we define our template’s matchers to instruct WAYPOINTS on what conditions it must meet before flagging a result as vulnerable.

The Matchers section consists of a Matcher Operator, a Match Type and a Match Value.

In our example, our HTTP response must meet 2 conditions before we can allow WAYPOINTS to mark a host as a valid vulnerability.

1

Condition 1

Our HTTP response must have a 200 OK status code.

2

Condition 2

We know that each affected resource has an internal app running that’s only accessible internally. We can set a rule to match against the following keywords Internal developer app portal.

This would also confirm that we have access to internal-only resources from outside of the network.

Matcher Operator

The Matcher Operator is used to specify whether we’re looking for all the conditions or only 1 of them.

AND Matcher Operator:

You can set the Operator to either AND to make sure WAYPOINTS matches against every single matcher specified

OR Matcher Operator:

Additionally, you can set it to OR and flag any host as vulnerable as soon as one condition is met.

In our example, we’d need to set it to AND. We want to match against the 200 OK status code AND we also want to make sure the keywords are present in the HTTP response.

Matchers Types

Matcher Types are a way to instruct WAYPOINTS on what response part we want our value to match against.

At the time, there are 5 Matcher Types:

  • Status Code
  • Content Type
  • Content Length
  • Word
  • Regex Pattern

Let’s briefly explore all of the supported options:

Status Code:

The Status Code Matcher Type is to match against a specific status code.

If you want to match against responses that return a 200 OK status code, your Matcher Value must be set to 200.

In some cases, you’d want to match against a range of status codes (for example to match a server-side redirect).

In that case, WAYPOINTS also supports wildcards. To match against a redirect, you could set the Matcher Value to 3XX or 3** to match against status codes ranging from 300 to 399.

Content Type:

The Content Type Matcher Type is used to match against a specific HTTP response content type.

If you only want to match against HTTP responses that return a HTML web page, you could set your Matcher Value to text/html.

In some cases, you’d find yourself in a situation where you’d need to match against several content types.

In that case whoever, WAYPOINTS also supports regex patterns. To match against an XML content type, you could set the Matcher Value to (application|text)\/xml.

Content Length:

The Content Length Matcher Type is used to match against a (specific) response content length.

In case you need to match against a content length that is equal to 1 337, you could easily set your Matcher Value to be equal to 1337.

In some situations, you aren’t going to be exactly knowing the specific content length of a response content length as several factors could play in.

And as you of course also want to make sure to mitigate false negatives as much as possible, you’d want to set a more flexible value.

In that case, you can specify a greater than or less than symbol. WAYPOINTS supports both of these if given in the correct format.

To match against any response with a content length greater than 1 337, simply set your Matcher Value to >1337.

The same applies to the opposite. Set your Matcher Value to <1337 and it would match any response content length that is less than 1 337.

Word:

The Word Matcher Type is used to match against a specific keyword in the response body.

Regex Pattern:

The Regex Pattern Matcher Type is used to match against a specific regex pattern in the response body.

In our example, we only have to make sure we set the Status Code to 200 and specify an additonal Word matcher that is set to Internal developer app portal to limit false positives.

Negative Matchers

Negative Matches or Inverted Matches are also supported. Turn on Negative Match next to your matcher to invert your condition.

Validator

This is where we define our template’s validator to instruct WAYPOINTS on what client-side conditions it must meet before flagging a result as vulnerable.

Complete JSON Template

template.json

{
	"metadata": {
		"name": "SSRF Check",
		"description": "Any external user is able to reach internal-only resources or make external HTTP requests on behalf of the server. The \"file:///\" protocol seems also to be supported opening up the possibility to read local files.",
		"severity": "critical",
		"CWEId": "CWE-918",
		"tags": [
			"SSRF",
			"PRIVATE"
		]
	},
	"request": {
		"method": "GET",
		"path": [
			"/api/documents/document-loader?document_URI=http://localhost:8080"
		],
		"headers": "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36;;",
		"body": ""
	},
	"operator": "AND",
	"matchers": [
		{
			"negative": false,
			"type": "statuscode",
			"value": "200"
		},
		{
			"negative": false,
			"type": "word",
			"value": "Internal developer app portal"
		}
	],
	"validator": {
		"type": "",
		"value": ""
	}
}

Complete YAML Template

template.yaml

metadata:
  name: SSRF Check
  description: >-
    Any external user is able to reach internal-only resources or make external
    HTTP requests on behalf of the server. The "file:///" protocol seems also to
    be supported opening up the possibility to read local files.
  severity: critical
  CWEId: CWE-918
  tags:
    - SSRF
    - PRIVATE
request:
  method: GET
  path:
    - /api/documents/document-loader?document_URI=http://localhost:8080
  headers: >-
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
    (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36;;
  body: ''
operator: AND
matchers:
  - negative: false
    type: statuscode
    value: '200'
  - negative: false
    type: word
    value: Internal developer app portal
validator:
  type: ''
  value: ''