Introduction
PAC provides a feature to write your own custom attacks and load into the platform. This is a useful feature to write custom business logic attacks and use them across all the applications in your enterprise. These attacks should be in compliant with one of the scanners PAC supports.
Note: Currently PAC supports custom attacks for ZAProxy scanner. All of the custom scripts should be compatible with ZAProxy custom script specifications scripts
Common Vulnerabilities and Exposures (CVE)
Custom attacks are categorised under CVE section of the PAC config file.
This documentation provides the complete steps about how to use the custom scripts in PAC.
Setup the Git Repository
We have to store the script file and metadata yaml file in the Git repository at particular location. To explain better, we are going over an example for the custom script.
http_sender_attack.js
Here is a httpsender
type script which checks the every response during penetration testing and generates an alert for every response which status code is equal to 400 or more, upto 599.
// A script which will raise alerts based on HTTP Response codes
// By default it will raise 'Info' level alerts for Client Errors (4xx) (apart from 404s) and 'Low' Level alerts for Server Errors (5xx)
// But it can be easily changed.
var control, model
if (!control) control = Java.type("org.parosproxy.paros.control.Control").getSingleton()
if (!model) model = Java.type("org.parosproxy.paros.model.Model").getSingleton()
var Pattern = Java.type("java.util.regex.Pattern")
pluginid = 100000 // https://github.com/zaproxy/zaproxy/blob/main/docs/scanners.md
function sendingRequest(msg, initiator, helper) {
// Nothing to do
}
function logger() {
print('[' + this['zap.script.name'] + '] ' + arguments[0]);
}
var control
if (!control) control = Java.type("org.parosproxy.paros.control.Control").getSingleton()
function responseReceived(msg, initiator, helper) {
var code = msg.getResponseHeader().getStatusCode()
var extensionAlert = control.getExtensionLoader().getExtension(org.zaproxy.zap.extension.alert.ExtensionAlert.NAME)
if (extensionAlert != null) {
var code = msg.getResponseHeader().getStatusCode()
if (code < 400 || code >= 600) {
// Do nothing
} else {
var risk = 0 // Info
var title = "A Client Error response code was returned by the server"
if (code >= 500) {
// Server error
risk = 1 // Low
title = "A Server Error response code was returned by the server"
}
// CONFIDENCE_HIGH = 3 (we can be pretty sure we're right)
var alert = new org.parosproxy.paros.core.scanner.Alert(pluginid, risk, 3, title)
var ref = msg.getHistoryRef()
if (ref != null && org.parosproxy.paros.model.HistoryReference.getTemporaryTypes().contains(
java.lang.Integer.valueOf(ref.getHistoryType()))) {
// Dont use temporary types as they will get deleted
ref = null
}
if (ref == null) {
// map the initiator
var type
switch (initiator) {
case 1: // PROXY_INITIATOR
type = 1 // Proxied
break
case 2: // ACTIVE_SCANNER_INITIATOR
type = 3 // Scanner
break
case 3: // SPIDER_INITIATOR
type = 2 // Spider
break
case 4: // FUZZER_INITIATOR
type = 8 // Fuzzer
break
case 5: // AUTHENTICATION_INITIATOR
type = 15 // User
break
case 6: // MANUAL_REQUEST_INITIATOR
type = 15 // User
break
case 8: // BEAN_SHELL_INITIATOR
type = 15 // User
break
case 9: // ACCESS_CONTROL_SCANNER_INITIATOR
type = 13 // Access control
break
default:
type = 15 // User - fallback
break
}
ref = new org.parosproxy.paros.model.HistoryReference(model.getSession(), type, msg)
}
alert.setMessage(msg)
alert.setUri(msg.getRequestHeader().getURI().toString())
alert.setDescription("A response code of " + code + " was returned by the server.\n" +
"This may indicate that the application is failing to handle unexpected input correctly.\n" +
"Raised by the 'Alert on HTTP Response Code Error' script");
// Use a regex to extract the evidence from the response header
var regex = new RegExp("^HTTP.*" + code)
alert.setEvidence(msg.getResponseHeader().toString().match(regex))
alert.setCweId(388) // CWE CATEGORY: Error Handling
alert.setWascId(20) // WASC Improper Input Handling
extensionAlert.alertFound(alert , ref)
}
}
}
metadata.yaml
Metadata file contains the configurations and details which are required for Prancer PAC to read.
Name: Alert On Http Response Code Errors
Type: httpsender
Engine: Oracle Nashorn
Description: A HTTP Sender Script which will raise alerts based on HTTP Response code
Charset: UTF-8
Save both http_sender_attack.js and metadata.yaml files at particular location in git. For example, we saved files inside the Alert_on_HTTP_Response_Code_Errors
folder.
Git repository
.
|___ Alert_on_HTTP_Response_Code_Errors
│ │ http_sender_attack.js
│ │ metadata.yaml
Create a PAC Application from the PAC Wizard
- Create a PAC application from the PAC Wizard screen, you will see the PAC config file like below.
Collection: azure_remote_test
ConnectionName: azure_remote_test_connector
CloudType: azure
ApplicatioName: Azure Remote Application
RiskLevel: safe
Compliance:
- CSA-CCM
- HIPAA
- ISO 27001
- SOC 2
- HITRUST
- NIST 800
ApplicationType: APIScan
Schedule: onetime
Target: http://prancersampleapp01.eastus2.cloudapp.azure.com:8888
# You can use postman collection as code for running attack inside the prancer.
# Connector defines the name of the git connector available in the collection.
# Postman remote files should include a path which has postman collection file and
# for postman env remote files, if you have environment variable file you can put
# the path inside the postmanEnvRemote file so prancer will go and extract the env
# variables and their values and merged it with postman collection.
APIScan:
Type: OpenAPI
DirectionProvider: git
Direction: http://prancersampleapp01.eastus2.cloudapp.azure.com:8888/v2/swagger.json
PostmanRemoteFile: remote_postman/postman_collection.json
PostmanEnvRemoteFile: remote_postman/postman_environment.json
Connector: azure_postman_connector
Scanner:
Cloud:
Platform:
Azure:
ContainerInstance:
AfterRun: delete
NewContainerInstance:
External:
SubscriptionId: 12345678-1234-5678-abcd-1234abcd4567
ResourceGp: testgroup
Region: eastus2
ContainerGroupName: prancer-scanner-group
ContainerName: prancer-pentest-instance
ResourceName: prancer-instances-1
AuthenticationMethod: noAuthentication
AddOns:
- accessControl
- ascanrulesBeta
- sqliplugin
- directorylistv2_3
- portscan
- pscanrulesBeta
- websocket
- fuzzdb
- fuzzdboffensive
- fuzz
- graphql
- openapi
Create and upload a Git connector file
We need to create a connector file which will use to connect Git repository.
azure_custom_script_connector.json
{
"container" : "azure_remote_test",
"name": "azure_custom_script_connector",
"json": {
"branchName": "main",
"companyName": "prancer",
"fileType": "structure",
"gitProvider": "https://github.com/prancer-io/prancer-pac-sample.git",
"httpsAccessToken": "secret-git-key",
"private": true,
"type": "filesystem"
}
}
name of the collection
defined in git
Field | Value | Description |
---|---|---|
container | container name | The container name should be match with the value of Collection property defined in PAC config file. |
name | connector name | Any name of the connector which will use to define in PAC config file |
gitProvider | clone URL | The URL for clone the git repository. |
branchName | branch name | Git branch name where the zap scripts are available |
httpsAccessToken | secret key | Any secret key which will be used to store the git token in the key vault |
- Once the connector file is created then Drag and drop the file over a collection.
Store the secrets in Key Vault
We require to store the authentication token to connect and clone the Git repository. Generate the git access token from the Git console. Here is the documentation for create the personal access token on Github.
- Give the following permissions while generating the access token.
repo: Full control of private repositories
read: user Read ALL user profile data
Create the new entry in Key Vault, where Key Name is the value of httpsAccessToken
and Key Value is generated access token.
Update the PAC Config file:
- Open the PAC Management screen and click on PAC Configuration for which you want to add the script.
Add the CVE field in the PAC configuration file.
CVE:
- Path:
Include:
- .*\.js
- abc.java
Exclude:
- .*\.py
Connector: azure_custom_script_connector
Field | Value | Description |
---|---|---|
Connector | connector name | the container name which you specified in Git connector. |
Path | Include and Exclude paths | Contains list of include and exclude paths |
Path.Include | list of path | Contains list of script paths ( Regex ) which need to include in processing |
Path.Exclude | list of path | Contains list of paths ( Regex ) which will be excluded while load the scripts. |
Complete PAC File
Collection: azure_remote_test
ConnectionName: azure_remote_test_connector
CloudType: azure
ApplicatioName: Azure Remote Application
RiskLevel: safe
Compliance:
- CSA-CCM
- HIPAA
- ISO 27001
- SOC 2
- HITRUST
- NIST 800
ApplicationType: APIScan
Schedule: onetime
Target: http://prancersampleapp01.eastus2.cloudapp.azure.com:8888
# You can use postman collection as code for running attack inside the prancer.
# Connector defines the name of the git connector available in the collection.
# Postman remote files should include a path which has postman collection file and
# for postman env remote files, if you have environment variable file you can put
# the path inside the postmanEnvRemote file so prancer will go and extract the env
# variables and their values and merged it with postman collection.
APIScan:
Type: OpenAPI
DirectionProvider: git
Direction: http://prancersampleapp01.eastus2.cloudapp.azure.com:8888/v2/swagger.json
PostmanRemoteFile: remote_postman/postman_collection.json
PostmanEnvRemoteFile: remote_postman/postman_environment.json
Connector: azure_postman_connector
CVE:
- Path:
Include:
- .*\.js
- abc.java
Exclude:
- .*\.py
Connector: azure_custom_script_connector
Scanner:
Cloud:
Platform:
Azure:
ContainerInstance:
AfterRun: delete
NewContainerInstance:
External:
SubscriptionId: 12345678-1234-5678-abcd-1234abcd4567
ResourceGp: testgroup
Region: eastus2
ContainerGroupName: prancer-scanner-group
ContainerName: prancer-pentest-instance
ResourceName: prancer-instances-1
AuthenticationMethod: noAuthentication
AddOns:
- accessControl
- ascanrulesBeta
- sqliplugin
- directorylistv2_3
- portscan
- pscanrulesBeta
- websocket
- fuzzdb
- fuzzdboffensive
- fuzz
- graphql
- openapi
Run the Pentest:
- Click on
start
button to run the pentest.
- After sometimes when the Pentest will complete then you can see the results by click on
See Latest Results
link.
- It will open the
Application Security Findings
page.