Skip to content

Commit

Permalink
Merge pull request #5945 from psiinon/sequence/gui
Browse files Browse the repository at this point in the history
Sequence: New sequence ascan dialog
  • Loading branch information
kingthorin authored Nov 26, 2024
2 parents 0826ae8 + 7a7ccf2 commit 7a35800
Show file tree
Hide file tree
Showing 10 changed files with 208 additions and 506 deletions.
6 changes: 5 additions & 1 deletion addOns/sequence/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,18 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Stats for import automation and active scan.
- Sequence active scan policy which will be used if neither a policy nor policyDefinition are set.
- Add Import top level menu item to import HAR as sequence.
- Active Scan Sequence dialog.

### Changed
- Depend on Import/Export add-on to allow to import HARs as sequences.
- Update minimum ZAP version to 2.15.0.
- Maintenance changes.
- To use new sequence scan from the desktop.
- Sequence scan implementation.
- Promoted to beta.

### Removed
- Sequence panel from the Active Scan dialog.

## [7] - 2023-10-23
### Changed
- Maintenance changes.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,20 @@

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.swing.ImageIcon;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.parosproxy.paros.control.Control;
import org.parosproxy.paros.control.Control.Mode;
import org.parosproxy.paros.core.scanner.AbstractPlugin;
import org.parosproxy.paros.core.scanner.Scanner;
import org.parosproxy.paros.core.scanner.ScannerHook;
import org.parosproxy.paros.extension.Extension;
import org.parosproxy.paros.extension.ExtensionAdaptor;
import org.parosproxy.paros.extension.ExtensionHook;
import org.parosproxy.paros.extension.SessionChangedListener;
import org.parosproxy.paros.extension.ViewDelegate;
import org.parosproxy.paros.model.Session;
import org.parosproxy.paros.network.HttpMessage;
import org.parosproxy.paros.view.View;
import org.zaproxy.addon.exim.ExtensionExim;
import org.zaproxy.addon.network.ExtensionNetwork;
import org.zaproxy.zap.extension.ascan.ExtensionActiveScan;
Expand All @@ -47,8 +45,9 @@
import org.zaproxy.zap.extension.sequence.internal.ImportHarMenuItem;
import org.zaproxy.zap.extension.zest.ExtensionZest;
import org.zaproxy.zap.extension.zest.ZestScriptWrapper;
import org.zaproxy.zap.view.ZapMenuItem;

public class ExtensionSequence extends ExtensionAdaptor implements ScannerHook {
public class ExtensionSequence extends ExtensionAdaptor {

private static final List<Class<? extends Extension>> DEPENDENCIES =
List.of(
Expand All @@ -65,12 +64,11 @@ public class ExtensionSequence extends ExtensionAdaptor implements ScannerHook {
private ImportHarMenuItem importHarMenuItem;

private List<ScriptWrapper> directScripts = null;
private SequenceAscanPanel sequencePanel;
private ZapMenuItem activeScanMenu;
private SequenceAscanDialog ascanDialog;

private ScriptType scriptType;

private boolean scanning = false;

public ExtensionSequence() {
super("ExtensionSequence");
this.setOrder(29);
Expand All @@ -93,23 +91,6 @@ public void init() {
new String[] {ScriptType.CAPABILITY_APPEND});
}

@Override
public void initView(ViewDelegate view) {
super.initView(view);

ExtensionActiveScan extAscan = getExtActiveScan();
if (extAscan != null) {
sequencePanel = new SequenceAscanPanel(getExtScript());
}
}

@Override
public void postInit() {
if (sequencePanel != null) {
getExtActiveScan().addCustomScanPanel(sequencePanel);
}
}

@Override
public List<Class<? extends Extension>> getDependencies() {
return DEPENDENCIES;
Expand All @@ -123,11 +104,10 @@ public boolean canUnload() {
@Override
public void unload() {
super.unload();
if (sequencePanel != null) {
getExtActiveScan().removeCustomScanPanel(sequencePanel);
}
getExtScript().removeScriptType(scriptType);

if (ascanDialog != null) {
ascanDialog.dispose();
}
if (importHarMenuItem != null) {
importHarMenuItem.unload();
}
Expand All @@ -138,37 +118,36 @@ public ScanPolicy getDefaultScanPolicy() throws ConfigurationException {
return getExtActiveScan().getPolicyManager().getPolicy("Sequence");
}

@Override
public void scannerComplete() {
if (!scanning && sequencePanel != null) {
// Active scan all of the selected sequences
// Need this bool otherwise we will infinitely recurse!
scanning = true;
List<ScriptWrapper> scripts = sequencePanel.getPanel(false).getSelectedIncludeScripts();

List<Object> contextSpecificObjects = new ArrayList<>();
try {
contextSpecificObjects.add(getDefaultScanPolicy());
} catch (ConfigurationException e4) {
// Ignore
public Stream<ZestScriptWrapper> getSequences() {
return extScript.getScripts(ExtensionSequence.TYPE_SEQUENCE).stream()
.filter(ZestScriptWrapper.class::isInstance)
.map(ZestScriptWrapper.class::cast);
}

public List<String> getSequenceNames() {
return getSequences().map(ScriptWrapper::getName).collect(Collectors.toList());
}

public void activeScanSequences(String policy, List<String> sequences) {
List<Object> contextSpecificObjects = new ArrayList<>();
try {
contextSpecificObjects.add(getExtActiveScan().getPolicyManager().getPolicy(policy));
} catch (ConfigurationException e4) {
// Ignore
}

for (String seq : sequences) {
ScriptWrapper script = getExtScript().getScript(seq);
if (script instanceof ZestScriptWrapper) {
StdActiveScanRunner zzr =
new StdActiveScanRunner(
(ZestScriptWrapper) script, null, null, contextSpecificObjects);
try {
zzr.run(null, null);
} catch (Exception e1) {
LOGGER.error(e1.getMessage(), e1);
}
}
scripts.forEach(
s -> {
if (s instanceof ZestScriptWrapper) {
StdActiveScanRunner zzr =
new StdActiveScanRunner(
(ZestScriptWrapper) s,
null,
null,
contextSpecificObjects);
try {
zzr.run(null, null);
} catch (Exception e1) {
LOGGER.error(e1.getMessage(), e1);
}
}
});
scanning = false;
}
}

Expand All @@ -188,11 +167,9 @@ public void hook(ExtensionHook extensionhook) {
extensionhook
.getHookMenu()
.addPopupMenuItem(new SequencePopupMenuItem(this, getExtScript()));
extensionhook.getHookMenu().addToolsMenuItem(getActiveScanMenu());
extensionhook.addSessionListener(new SessionChangedListenerImpl());
}

// Add class as a scannerhook (implements the scannerhook interface)
extensionhook.addScannerHook(this);
}

/**
Expand All @@ -204,12 +181,6 @@ public ScriptType getScriptType() {
return scriptType;
}

@Override
public void beforeScan(HttpMessage msg, AbstractPlugin plugin, Scanner scanner) {}

@Override
public void afterScan(HttpMessage msg, AbstractPlugin plugin, Scanner scanner) {}

public void setDirectScanScript(ScriptWrapper script) {
directScripts = new ArrayList<>();
directScripts.add(script);
Expand All @@ -233,6 +204,21 @@ protected ExtensionActiveScan getExtActiveScan() {
return extActiveScan;
}

private SequenceAscanDialog getAscanDialog() {
if (ascanDialog == null) {
ascanDialog = new SequenceAscanDialog(this, View.getSingleton().getMainFrame());
}
return ascanDialog;
}

private ZapMenuItem getActiveScanMenu() {
if (activeScanMenu == null) {
activeScanMenu = new ZapMenuItem("sequence.tools.menu.ascan");
activeScanMenu.addActionListener(e -> getAscanDialog().setVisible(true));
}
return activeScanMenu;
}

private class SessionChangedListenerImpl implements SessionChangedListener {

@Override
Expand All @@ -256,7 +242,6 @@ public void sessionScopeChanged(Session session) {
@Override
public void sessionModeChanged(Mode mode) {
// Nothing to do.

}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* Zed Attack Proxy (ZAP) and its related class files.
*
* ZAP is an HTTP/HTTPS proxy for assessing web application security.
*
* Copyright 2024 The ZAP Development Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.zaproxy.zap.extension.sequence;

import java.awt.Frame;
import javax.swing.DefaultListModel;
import javax.swing.JList;
import javax.swing.JScrollPane;
import org.apache.commons.configuration.ConfigurationException;
import org.parosproxy.paros.Constant;
import org.zaproxy.zap.extension.ascan.ScanPolicy;
import org.zaproxy.zap.utils.DisplayUtils;
import org.zaproxy.zap.view.StandardFieldsDialog;

@SuppressWarnings("serial")
public class SequenceAscanDialog extends StandardFieldsDialog {

private static final String FIELD_POLICY = "sequence.scan.dialog.label.policy";
private static final String FIELD_SEQS = "sequence.scan.dialog.label.sequences";

private static final long serialVersionUID = 1L;
private ExtensionSequence ext;

private JList<String> seqList;
private DefaultListModel<String> model;

public SequenceAscanDialog(ExtensionSequence ext, Frame owner) {
super(owner, "sequence.scan.dialog.title", DisplayUtils.getScaledDimension(500, 300));
this.ext = ext;

String defaultPolicyName = "";
try {
ScanPolicy defaultPolicy = ext.getDefaultScanPolicy();
if (defaultPolicy != null) {
defaultPolicyName = defaultPolicy.getName();
}
} catch (ConfigurationException e) {
// Ignore
}

this.addComboField(
FIELD_POLICY,
ext.getExtActiveScan().getPolicyManager().getAllPolicyNames(),
defaultPolicyName);

model = new DefaultListModel<>();
model.addAll(ext.getSequenceNames());
seqList = new JList<>(model);
this.addCustomComponent(FIELD_SEQS, new JScrollPane(seqList), 100);
}

@Override
public String getSaveButtonText() {
return Constant.messages.getString("sequence.scan.dialog.button.scan");
}

@Override
public void save() {
new Thread(
() ->
ext.activeScanSequences(
this.getStringValue(FIELD_POLICY),
seqList.getSelectedValuesList()),
"ZAP-SequenceActiveScanGui")
.start();
}

@Override
public String validateFields() {
if (this.isEmptyField(FIELD_POLICY)) {
return Constant.messages.getString("sequence.scan.dialog.error.policy");
}
if (seqList.isSelectionEmpty()) {
return Constant.messages.getString("sequence.scan.dialog.error.sequences");
}
return null;
}

@Override
public String getHelpIndex() {
return "addon.sequence";
}
}
Loading

0 comments on commit 7a35800

Please sign in to comment.