Skip to content

Commit

Permalink
Add extender/ScanMonitor script
Browse files Browse the repository at this point in the history
Signed-off-by: Simon Bennetts <[email protected]>
  • Loading branch information
psiinon committed Sep 13, 2024
1 parent a727590 commit 57b0545
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### Added
- Standalone script 'PrivateMethodAccess.js'
- Variant script 'AddUrlParams.js'
- Extender script 'ScanMonitor.js'
### Changed
- Add cautionary note to help and readme.
### Fixed
Expand Down
94 changes: 94 additions & 0 deletions extender/ScanMonitor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// This script monitors the active scanner and ends the scan if certain conditions are met.
// By default it just ends the scan for high:
// * Connection failures
// * Authentication failures
// * Response times
// You can easily chane the script to end the scan for other conditions, such as high 4xx / 5xx response codes,
// but these tend to be application specific so they are not enabled by default.

var SessionStructure = Java.type("org.zaproxy.zap.model.SessionStructure");
var Timer = Java.type("java.util.Timer");
var TimerTask = Java.type("java.util.TimerTask");
var URI = Java.type("org.apache.commons.httpclient.URI");
var View = Java.type("org.parosproxy.paros.view.View");

var extAscan = control.getExtensionLoader().getExtension("ExtensionActiveScan");
var inMemoryStats = control.getExtensionLoader()
.getExtension("ExtensionStats").getInMemoryStats();

var timer = new Timer();
var timerSecs = 10 * 1000; // Check every 10 secs

// Set to true to see the stats reported live
var log = false;

/**
* This function is called when the script is enabled.
*
* @param helper - a helper class which provides the methods:
* getView() this returns a View object which provides an easy way to add graphical elements.
* It will be null is ZAP is running in daemon mode.
* getApi() this returns an API object which provides an easy way to add new API calls.
* Links to any functionality added should be held in script variables so that they can be removed in uninstall.
*/
function install(helper) {
timer.scheduleAtFixedRate(new TimerTask() {
run() {
runchecks();
}
}, 0, timerSecs);
}

function getStat(site, stat) {
var val = site == null ? inMemoryStats.getStat(stat) : inMemoryStats.getStat(site, stat);
return val == null ? 0 : val;
}

// Response times are recorded in logarithmic time slices
function getLongRespStats(site) {
return getStat(site, "stats.responseTime.16384")
+ getStat(site, "stats.responseTime.32768")
+ getStat(site, "stats.responseTime.65536");
}

function runchecks() {
if (log) print("Running checks..");
ascans = extAscan.getActiveScans();
ascans.forEach((as, i) => {
// For the full set of stats that can be monitored see https://www.zaproxy.org/docs/internal-statistics/
var site = SessionStructure.getHostName(new URI(as.getDisplayName(), true));
print("Site: " + site);
// Connection failures are global rather than site specific
var connFails = getStat(null, "stats.connect.failure"); // TODO change to new name
// All HTTP response codes are recorded, so you can add checks for 401, 403 etc etc
var stats401 = getStat(site, "stats.code.401");
var stats500 = getStat(site, "stats.code.500");
// Auth fails are only relevant for authenticated scans
var authFails = getStat(site, "stats.auth.failure");
var longResp = getLongRespStats(site)

if (log) {
print(" 401 resps:\t" + stats401);
print(" 500 resps:\t" + stats500);
print(" conn fails:\t" + connFails);
print(" auth fails:\t" + authFails);
print(" long resps:\t" + longResp);
}
if (connFails > 1000 || authFails > 1000 || longResp > 1000) {
if (log) print("Stopping ascan " + site);
as.stopScan();
}
});
}

/**
* This function is called when the script is disabled.
*
* @param helper - a helper class which provides the methods:
* getView() this returns a View object which provides an easy way to add graphical elements.
* It will be null is ZAP is running in daemon mode.
* getApi() this returns an API object which provides an easy way to add new API calls.
*/
function uninstall(helper) {
timer.cancel();
}
3 changes: 3 additions & 0 deletions other/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ All notable changes to the 'other' section of this repository will be documented

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

### 2024-08-30
- Added af-plans/ApiScanExample.yaml

### 2024-02-06
- Added af-plans/FullScanBrokenCrystals.yaml
- Added af-plans/ScriptEnvVarAccess.yaml
Expand Down

0 comments on commit 57b0545

Please sign in to comment.