diff --git a/zap/src/main/java/org/parosproxy/paros/core/scanner/ScannerParam.java b/zap/src/main/java/org/parosproxy/paros/core/scanner/ScannerParam.java index 18ac9a50c7f..e3292608922 100644 --- a/zap/src/main/java/org/parosproxy/paros/core/scanner/ScannerParam.java +++ b/zap/src/main/java/org/parosproxy/paros/core/scanner/ScannerParam.java @@ -72,6 +72,7 @@ import org.apache.logging.log4j.Logger; import org.parosproxy.paros.Constant; import org.parosproxy.paros.common.AbstractParam; +import org.zaproxy.zap.ZAP; import org.zaproxy.zap.extension.api.ZapApiIgnore; public class ScannerParam extends AbstractParam { @@ -145,6 +146,9 @@ public class ScannerParam extends AbstractParam { private static final String MAX_ALERTS_PER_RULE = ACTIVE_SCAN_BASE_KEY + ".maxAlertsPerRule"; + private static final String PERSIST_TEMPORARY_MESSAGES = + ACTIVE_SCAN_BASE_KEY + ".persistTemporaryMessages"; + // ZAP: Configuration constants public static final int TARGET_QUERYSTRING = 1; public static final int TARGET_POSTDATA = 1 << 1; @@ -239,6 +243,8 @@ public class ScannerParam extends AbstractParam { // ZAP: internal Logger private static final Logger LOGGER = LogManager.getLogger(ScannerParam.class); + private boolean persistTemporaryMessages; + public ScannerParam() {} @Override @@ -338,6 +344,11 @@ protected void parse() { } maxAlertsPerRule = Math.max(0, getInt(MAX_ALERTS_PER_RULE, 0)); + + persistTemporaryMessages = + getBoolean( + PERSIST_TEMPORARY_MESSAGES, + ZAP.getProcessType() != ZAP.ProcessType.cmdline); } private void migrateOldOptions() { @@ -775,4 +786,38 @@ public boolean isEncodeCookieValues() { public void setEncodeCookieValues(boolean encodeCookieValues) { this.encodeCookieValues = encodeCookieValues; } + + /** + * Tells whether or not the temporary HTTP messages sent while active scanning should be + * persisted. + * + * @return {@code true} if the temporary HTTP messages should be persisted, {@code false} + * otherwise. + * @since 2.17.0 + * @see #setPersistTemporaryMessages(boolean) + */ + public boolean isPersistTemporaryMessages() { + return persistTemporaryMessages; + } + + /** + * Sets whether or not the temporary HTTP messages sent while active scanning should be + * persisted. + * + *
By default the HTTP messages are persisted unless in command line mode, where sessions are + * usually discarded once ZAP finishes. + * + * @param value {@code true} if the temporary HTTP messages should be persisted, {@code false} + * otherwise. + * @since 2.17.0 + * @see #isPersistTemporaryMessages() + */ + public void setPersistTemporaryMessages(boolean value) { + if (persistTemporaryMessages == value) { + return; + } + + this.persistTemporaryMessages = value; + getConfig().setProperty(PERSIST_TEMPORARY_MESSAGES, this.persistTemporaryMessages); + } } diff --git a/zap/src/main/java/org/zaproxy/zap/extension/ascan/ActiveScan.java b/zap/src/main/java/org/zaproxy/zap/extension/ascan/ActiveScan.java index 223d6cad58b..6a04c0f9ed5 100644 --- a/zap/src/main/java/org/zaproxy/zap/extension/ascan/ActiveScan.java +++ b/zap/src/main/java/org/zaproxy/zap/extension/ascan/ActiveScan.java @@ -81,6 +81,8 @@ public static enum State { private static final Logger LOGGER = LogManager.getLogger(ActiveScan.class); + private boolean persistTemporaryMessages; + @Deprecated public ActiveScan( String displayName, @@ -110,6 +112,8 @@ public ActiveScan( ScanPolicy scanPolicy, RuleConfigParam ruleConfigParam) { super(scannerParam, scanPolicy, ruleConfigParam); + persistTemporaryMessages = scannerParam.isPersistTemporaryMessages(); + this.displayName = displayName; this.maxResultsToList = scannerParam.getMaxResultsToList(); // Easiest way to get the messages and alerts ;) @@ -277,6 +281,12 @@ public ActiveScanTableModel getMessagesTableModel() { @Override public void notifyNewMessage(final HttpMessage msg) { + this.rcTotals.incResponseCodeCount(msg.getResponseHeader().getStatusCode()); + + if (!persistTemporaryMessages) { + return; + } + HistoryReference hRef = msg.getHistoryRef(); if (hRef == null) { try { @@ -294,8 +304,6 @@ public void notifyNewMessage(final HttpMessage msg) { hRefs.add(hRef.getHistoryId()); } - this.rcTotals.incResponseCodeCount(msg.getResponseHeader().getStatusCode()); - if (hRef != null && View.isInitialised()) { // Very large lists significantly impact the UI responsiveness // limiting them makes large scans _much_ quicker diff --git a/zap/src/main/java/org/zaproxy/zap/extension/ascan/OptionsScannerPanel.java b/zap/src/main/java/org/zaproxy/zap/extension/ascan/OptionsScannerPanel.java index df7ede84f8e..91dbafef7ff 100644 --- a/zap/src/main/java/org/zaproxy/zap/extension/ascan/OptionsScannerPanel.java +++ b/zap/src/main/java/org/zaproxy/zap/extension/ascan/OptionsScannerPanel.java @@ -50,6 +50,7 @@ public class OptionsScannerPanel extends AbstractParamPanel { private ZapNumberSpinner spinnerMaxRuleDuration = null; private ZapNumberSpinner spinnerMaxScanDuration = null; private ZapNumberSpinner maxAlertsPerRule; + private JCheckBox persistTemporaryMessages; private ZapNumberSpinner spinnerMaxResultsList = null; private JCheckBox chkInjectPluginIdInHeader = null; private JCheckBox chkHandleAntiCsrfTokens = null; @@ -123,6 +124,20 @@ private JPanel getPanelScanner() { GridBagConstraints.HORIZONTAL, new Insets(2, 2, 2, 2))); + persistTemporaryMessages = + new JCheckBox( + Constant.messages.getString("ascan.options.persistTempMessages.label")); + panelScanner.add( + persistTemporaryMessages, + LayoutHelper.getGBC( + 0, + row++, + 2, + 0.0D, + 0, + GridBagConstraints.HORIZONTAL, + new Insets(2, 2, 2, 2))); + panelScanner.add( new JLabel(Constant.messages.getString("ascan.options.maxRes.label")), LayoutHelper.getGBC( @@ -418,6 +433,7 @@ public void initParam(Object obj) { getSliderHostPerScan().setValue(param.getHostPerScan()); getSpinnerThreadsPerHost().setValue(param.getThreadPerHost()); getSpinnerDelayInMs().setValue(param.getDelayInMs()); + persistTemporaryMessages.setSelected(param.isPersistTemporaryMessages()); getSpinnerMaxResultsList().setValue(param.getMaxResultsToList()); getSpinnerMaxRuleDuration().setValue(param.getMaxRuleDurationInMins()); getSpinnerMaxScanDuration().setValue(param.getMaxScanDurationInMins()); @@ -444,6 +460,7 @@ public void saveParam(Object obj) throws Exception { param.setHostPerScan(getSliderHostPerScan().getValue()); param.setThreadPerHost(getSpinnerThreadsPerHost().getValue()); param.setDelayInMs(getDelayInMs()); + param.setPersistTemporaryMessages(persistTemporaryMessages.isSelected()); param.setMaxResultsToList(this.getSpinnerMaxResultsList().getValue()); param.setMaxRuleDurationInMins(this.getSpinnerMaxRuleDuration().getValue()); param.setMaxScanDurationInMins(this.getSpinnerMaxScanDuration().getValue()); diff --git a/zap/src/main/resources/org/zaproxy/zap/resources/Messages.properties b/zap/src/main/resources/org/zaproxy/zap/resources/Messages.properties index bae183a7281..ff859943c27 100644 --- a/zap/src/main/resources/org/zaproxy/zap/resources/Messages.properties +++ b/zap/src/main/resources/org/zaproxy/zap/resources/Messages.properties @@ -337,6 +337,8 @@ ascan.api.action.setOptionMaxScanDurationInMins = ascan.api.action.setOptionMaxScanDurationInMins.param.Integer = ascan.api.action.setOptionMaxScansInUI = ascan.api.action.setOptionMaxScansInUI.param.Integer = +ascan.api.action.setOptionPersistTemporaryMessages = Sets whether or not the temporary HTTP messages sent while active scanning should be persisted. +ascan.api.action.setOptionPersistTemporaryMessages.param.Boolean = true if the temporary HTTP messages should be persisted, false otherwise. ascan.api.action.setOptionPromptInAttackMode = ascan.api.action.setOptionPromptInAttackMode.param.Boolean = ascan.api.action.setOptionPromptToClearFinishedScans = @@ -408,6 +410,7 @@ ascan.api.view.optionMaxResultsToList = ascan.api.view.optionMaxRuleDurationInMins = ascan.api.view.optionMaxScanDurationInMins = ascan.api.view.optionMaxScansInUI = +ascan.api.view.optionPersistTemporaryMessages = Tells whether or not the temporary HTTP messages sent while active scanning should be persisted. ascan.api.view.optionPromptInAttackMode = ascan.api.view.optionPromptToClearFinishedScans = ascan.api.view.optionRescanInAttackMode = @@ -495,6 +498,7 @@ ascan.options.maxRule.label = Maximum Rule Duration (minutes; 0 is unlimited): ascan.options.maxScan.label = Maximum Scan Duration (minutes; 0 is unlimited): ascan.options.numHosts.label = Number of Hosts Scanned Concurrently: ascan.options.numThreads.label = Concurrent Scanning Threads per Host: +ascan.options.persistTempMessages.label = Persist temporary HTTP messages. ascan.options.pluginHeader.label = Inject plugin ID in header for all active scan requests. ascan.options.policy.ascan.label = Default Active Scan Policy: ascan.options.policy.attack.label = Attack Mode Scan Policy: