|
| 1 | +// This script monitors the active scanner and ends the scan if certain conditions are met. |
| 2 | +// By default it just ends the scan for high: |
| 3 | +// * Connection failures |
| 4 | +// * Authentication failures |
| 5 | +// * Response times |
| 6 | +// You can easily chane the script to end the scan for other conditions, such as high 4xx / 5xx response codes, |
| 7 | +// but these tend to be application specific so they are not enabled by default. |
| 8 | + |
| 9 | +var SessionStructure = Java.type("org.zaproxy.zap.model.SessionStructure"); |
| 10 | +var Timer = Java.type("java.util.Timer"); |
| 11 | +var TimerTask = Java.type("java.util.TimerTask"); |
| 12 | +var URI = Java.type("org.apache.commons.httpclient.URI"); |
| 13 | + |
| 14 | +var extAscan = control.getExtensionLoader().getExtension("ExtensionActiveScan"); |
| 15 | +var inMemoryStats = control |
| 16 | + .getExtensionLoader() |
| 17 | + .getExtension("ExtensionStats") |
| 18 | + .getInMemoryStats(); |
| 19 | + |
| 20 | +var timer = new Timer(); |
| 21 | +var timerSecs = 10 * 1000; // Check every 10 secs |
| 22 | + |
| 23 | +// Set to true to see the stats reported live |
| 24 | +var log = false; |
| 25 | + |
| 26 | +function install(helper) { |
| 27 | + timer.scheduleAtFixedRate( |
| 28 | + new TimerTask() { |
| 29 | + run: function () { |
| 30 | + runchecks(); |
| 31 | + }, |
| 32 | + }, |
| 33 | + 0, |
| 34 | + timerSecs |
| 35 | + ); |
| 36 | +} |
| 37 | + |
| 38 | +function getStat(site, stat) { |
| 39 | + var val = |
| 40 | + site == null |
| 41 | + ? inMemoryStats.getStat(stat) |
| 42 | + : inMemoryStats.getStat(site, stat); |
| 43 | + return val == null ? 0 : val; |
| 44 | +} |
| 45 | + |
| 46 | +// Response times are recorded in logarithmic millisec time slices |
| 47 | +function getLongRespStats(site) { |
| 48 | + return ( |
| 49 | + getStat(site, "stats.responseTime.16384") + |
| 50 | + getStat(site, "stats.responseTime.32768") + |
| 51 | + getStat(site, "stats.responseTime.65536") |
| 52 | + ); |
| 53 | +} |
| 54 | + |
| 55 | +function runchecks() { |
| 56 | + if (log) print("Running checks.."); |
| 57 | + ascans = extAscan.getActiveScans(); |
| 58 | + ascans.forEach((as, i) => { |
| 59 | + // For the full set of stats that can be monitored see https://www.zaproxy.org/docs/internal-statistics/ |
| 60 | + var site = SessionStructure.getHostName(new URI(as.getDisplayName(), true)); |
| 61 | + if (log) print("Site: " + site); |
| 62 | + // Connection failures are global rather than site specific |
| 63 | + var connFails = getStat(null, "stats.network.send.failure"); |
| 64 | + // All HTTP response codes are recorded, so you can add checks for 401, 403 etc etc |
| 65 | + var stats401 = getStat(site, "stats.code.401"); |
| 66 | + var stats500 = getStat(site, "stats.code.500"); |
| 67 | + // Auth fails are only relevant for authenticated scans |
| 68 | + var authFails = getStat(site, "stats.auth.failure"); |
| 69 | + var longResp = getLongRespStats(site); |
| 70 | + |
| 71 | + if (log) { |
| 72 | + print(" 401 resps:\t" + stats401); |
| 73 | + print(" 500 resps:\t" + stats500); |
| 74 | + print(" conn fails:\t" + connFails); |
| 75 | + print(" auth fails:\t" + authFails); |
| 76 | + print(" long resps:\t" + longResp); |
| 77 | + } |
| 78 | + // Change this test to meet your requirements as needed. |
| 79 | + if (connFails > 1000 || authFails > 1000 || longResp > 1000) { |
| 80 | + if (log) print("Stopping ascan " + site); |
| 81 | + as.stopScan(); |
| 82 | + } |
| 83 | + }); |
| 84 | +} |
| 85 | + |
| 86 | +function uninstall(helper) { |
| 87 | + timer.cancel(); |
| 88 | +} |
0 commit comments