/*
* Zed Attack Proxy (ZAP) and its related class files.
*
* ZAP is an HTTP/HTTPS proxy for assessing web application security.
*
* Copyright 2011 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.alert;
import java.awt.CardLayout;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;
import org.apache.log4j.Logger;
import org.parosproxy.paros.Constant;
import org.parosproxy.paros.core.scanner.Alert;
import org.parosproxy.paros.extension.AbstractPanel;
import org.parosproxy.paros.model.HistoryReference;
import org.parosproxy.paros.network.HttpMessage;
import org.zaproxy.zap.model.Vulnerabilities;
import org.zaproxy.zap.model.Vulnerability;
import org.zaproxy.zap.utils.FontUtils;
import org.zaproxy.zap.utils.ZapLabel;
import org.zaproxy.zap.utils.ZapNumberSpinner;
import org.zaproxy.zap.utils.ZapTextArea;
import org.zaproxy.zap.utils.ZapTextField;
import org.zaproxy.zap.view.LayoutHelper;
public class AlertViewPanel extends AbstractPanel {
private static final long serialVersionUID = 1L;
private static final Logger logger = Logger.getLogger(AlertViewPanel.class);
private static final Insets DEFAULT_INSETS = new Insets(1,1,1,1);
private JScrollPane defaultPane = null;
private JScrollPane alertPane = null;
private ZapTextArea defaultOutput = null;
private JPanel alertDisplay = null;
private CardLayout cardLayout = null;
private ZapLabel alertUrl = null;
private ZapLabel alertName = null;
private JLabel alertRisk = null;
private JLabel alertConfidence = null;
private ZapLabel alertParam = null;
private ZapLabel alertAttack = null;
private ZapLabel alertEvidence = null;
private ZapTextArea alertDescription = null;
private ZapTextArea alertOtherInfo = null;
private ZapTextArea alertSolution = null;
private ZapTextArea alertReference = null;
private JLabel alertCweId = null;
private JLabel alertWascId = null;
private JLabel alertSource;
private JComboBox<String> alertEditName = null;
private JComboBox<String> alertEditRisk = null;
private JComboBox<String> alertEditConfidence = null;
private JComboBox<String> alertEditParam = null;
private ZapTextField alertEditAttack = null;
private ZapTextField alertEditEvidence = null;
private DefaultComboBoxModel<String> nameListModel = null;
private DefaultComboBoxModel<String> paramListModel = null;
private ZapNumberSpinner alertEditCweId = null;
private ZapNumberSpinner alertEditWascId = null;
private JLabel attackLabel;
private JLabel cweidLabel;
private JLabel evidenceLabel;
private JLabel otherLabel;
private JLabel confidenceLabel;
private JLabel riskLabel;
private JLabel sourceLabel;
private JLabel urlLabel;
private JLabel wascidLabel;
private boolean editable = false;
private Alert originalAlert = null;
private List <Vulnerability> vulnerabilities = null;
private HistoryReference historyRef = null;
/**
* Used to set the {@code HttpMessage} to the new alert when there is no
* {@code historyRef}.
*/
private HttpMessage httpMessage;
public AlertViewPanel() {
this (false);
}
public AlertViewPanel(boolean editable) {
super();
this.editable = editable;
initialize();
}
/**
* This method initializes this
*/
private void initialize() {
cardLayout = new CardLayout();
this.setLayout(cardLayout);
this.setName("AlertView");
if (! editable) {
this.add(getDefaultPane(), getDefaultPane().getName());
}
this.add(getAlertPane(), getAlertPane().getName());
}
private JScrollPane getAlertPane() {
if (alertPane == null) {
alertPane = new JScrollPane();
alertPane.setViewportView(getAlertDisplay());
alertPane.setName("alertPane");
}
return alertPane;
}
private ZapTextArea createZapTextArea() {
ZapTextArea ZapTextArea = new ZapTextArea(3, 30);
ZapTextArea.setLineWrap(true);
ZapTextArea.setWrapStyleWord(true);
ZapTextArea.setEditable(editable);
return ZapTextArea;
}
private JScrollPane createJScrollPane(String name) {
JScrollPane jScrollPane = new JScrollPane();
jScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
jScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
jScrollPane.setBorder(
BorderFactory.createTitledBorder(
null, name,
TitledBorder.DEFAULT_JUSTIFICATION,
javax.swing.border.TitledBorder.DEFAULT_POSITION,
FontUtils.getFont(FontUtils.Size.standard),
java.awt.Color.black));
return jScrollPane;
}
private JPanel getAlertDisplay() {
if (alertDisplay == null) {
alertDisplay = new JPanel();
alertDisplay.setLayout(new GridBagLayout());
alertDisplay.setName("alertDisplay");
// Create the labels
alertEditName = new JComboBox<>();
alertEditName.setEditable(true);
nameListModel = new DefaultComboBoxModel<>();
List <String> allVulns = getAllVulnerabilityNames();
nameListModel.addElement(""); // Default to blank
for (String vuln : allVulns) {
nameListModel.addElement(vuln);
}
alertEditName.setModel(nameListModel);
alertEditName.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if ("comboBoxChanged".equals(e.getActionCommand())) {
Vulnerability v = getVulnerability((String)alertEditName.getSelectedItem());
if (v != null) {
if (v.getDescription() != null && v.getDescription().length() > 0) {
setAlertDescription(v.getDescription());
}
if (v.getSolution() != null && v.getSolution().length() > 0) {
setAlertSolution(v.getSolution());
}
if (v.getReferences() != null) {
StringBuilder sb = new StringBuilder();
for (String ref : v.getReferences()) {
sb.append(ref);
sb.append('\n');
}
setAlertReference(sb.toString());
}
alertEditWascId.setValue(v.getWascId());
}
}
}
});
alertEditRisk = new JComboBox<>(Alert.MSG_RISK);
alertEditConfidence = new JComboBox<>(Alert.MSG_CONFIDENCE);
alertEditConfidence.setSelectedItem(Alert.MSG_CONFIDENCE[Alert.CONFIDENCE_MEDIUM]);
alertEditAttack = new ZapTextField();
paramListModel = new DefaultComboBoxModel<>();
paramListModel.addElement(""); // Default is empty so user can type anything in
alertEditParam = new JComboBox<>();
alertEditParam.setModel(paramListModel);
alertEditParam.setEditable(true);
alertEditEvidence = new ZapTextField();
alertEditCweId = new ZapNumberSpinner();
if (alertEditCweId.getEditor() instanceof JSpinner.DefaultEditor) {
((JSpinner.DefaultEditor) alertEditCweId.getEditor()).getTextField()
.setHorizontalAlignment(JTextField.LEFT);
}
alertEditWascId = new ZapNumberSpinner();
if (alertEditWascId.getEditor() instanceof JSpinner.DefaultEditor) {
((JSpinner.DefaultEditor) alertEditWascId.getEditor()).getTextField()
.setHorizontalAlignment(JTextField.LEFT);
}
// Read only ones
alertName = new ZapLabel();
alertName.setFont(FontUtils.getFont(Font.BOLD));
alertRisk = new JLabel();
alertConfidence = new JLabel();
alertParam = new ZapLabel();
alertAttack = new ZapLabel();
alertEvidence = new ZapLabel();
alertCweId = new JLabel();
alertWascId = new JLabel();
alertSource = new JLabel();
alertUrl = new ZapLabel();
alertDescription = createZapTextArea();
JScrollPane descSp = createJScrollPane(Constant.messages.getString("alert.label.desc"));
descSp.setViewportView(alertDescription);
alertDescription.addKeyListener(new KeyAdapter() {
// Change tab key to transfer focus to the next element
@Override
public void keyPressed(java.awt.event.KeyEvent evt) {
if (evt.getKeyCode() == KeyEvent.VK_TAB) {
alertDescription.transferFocus();
}
}
});
alertOtherInfo = createZapTextArea();
JScrollPane otherSp = createJScrollPane(Constant.messages.getString("alert.label.other"));
otherSp.setViewportView(alertOtherInfo);
alertOtherInfo.addKeyListener(new KeyAdapter() {
// Change tab key to transfer focus to the next element
@Override
public void keyPressed(java.awt.event.KeyEvent evt) {
if (evt.getKeyCode() == KeyEvent.VK_TAB) {
alertOtherInfo.transferFocus();
}
}
});
alertSolution = createZapTextArea();
JScrollPane solutionSp = createJScrollPane(Constant.messages.getString("alert.label.solution"));
solutionSp.setViewportView(alertSolution);
alertSolution.addKeyListener(new KeyAdapter() {
// Change tab key to transfer focus to the next element
@Override
public void keyPressed(java.awt.event.KeyEvent evt) {
if (evt.getKeyCode() == KeyEvent.VK_TAB) {
alertSolution.transferFocus();
}
}
});
alertReference = createZapTextArea();
JScrollPane referenceSp = createJScrollPane(Constant.messages.getString("alert.label.ref"));
referenceSp.setViewportView(alertReference);
alertReference.addKeyListener(new KeyAdapter() {
// Change tab key to transfer focus to the next element
@Override
public void keyPressed(java.awt.event.KeyEvent evt) {
if (evt.getKeyCode() == KeyEvent.VK_TAB) {
alertReference.transferFocus();
}
}
});
int gbcRow = 0;
alertDisplay.add(editable ? alertEditName : alertName,
LayoutHelper.getGBC(0, gbcRow, 2, 0, DEFAULT_INSETS));
// Show a blank label instead of the edit button if already editing
gbcRow++;
alertDisplay.add(getUrlLabel(), LayoutHelper.getGBC(0, gbcRow, 1, 0, DEFAULT_INSETS));
alertDisplay.add(alertUrl, LayoutHelper.getGBC(1, gbcRow, 1, 1, DEFAULT_INSETS));
gbcRow++;
alertDisplay.add(getRiskLabel(), LayoutHelper.getGBC(0, gbcRow, 1, 0, DEFAULT_INSETS));
alertDisplay.add(editable ? alertEditRisk : alertRisk,
LayoutHelper.getGBC(1, gbcRow, 1, 1, DEFAULT_INSETS));
gbcRow++;
alertDisplay.add(getConfidenceLabel(), LayoutHelper.getGBC(0, gbcRow, 1, 0, DEFAULT_INSETS));
alertDisplay.add(editable ? alertEditConfidence : alertConfidence,
LayoutHelper.getGBC(1, gbcRow, 1, 1, DEFAULT_INSETS));
gbcRow++;
alertDisplay.add(getParameterLabel(), LayoutHelper.getGBC(0, gbcRow, 1, 0, DEFAULT_INSETS));
alertDisplay.add(editable ? alertEditParam : alertParam,
LayoutHelper.getGBC(1, gbcRow, 1, 1, DEFAULT_INSETS));
gbcRow++;
alertDisplay.add(getAttackLabel(), LayoutHelper.getGBC(0, gbcRow, 1, 0, DEFAULT_INSETS));
alertDisplay.add(editable ? alertEditAttack : alertAttack,
LayoutHelper.getGBC(1, gbcRow, 1, 1, DEFAULT_INSETS));
gbcRow++;
alertDisplay.add(getEvidenceLabel(), LayoutHelper.getGBC(0, gbcRow, 1, 0, DEFAULT_INSETS));
alertDisplay.add(editable ? alertEditEvidence : alertEvidence,
LayoutHelper.getGBC(1, gbcRow, 1, 1, DEFAULT_INSETS));
gbcRow++;
alertDisplay.add(getCweidLabel(), LayoutHelper.getGBC(0, gbcRow, 1, 0, DEFAULT_INSETS));
alertDisplay.add(editable ? alertEditCweId : alertCweId,
LayoutHelper.getGBC(1, gbcRow, 1, 1, DEFAULT_INSETS));
gbcRow++;
alertDisplay.add(getWascidLabel(), LayoutHelper.getGBC(0, gbcRow, 1, 0, DEFAULT_INSETS));
alertDisplay.add(editable ? alertEditWascId : alertWascId,
LayoutHelper.getGBC(1, gbcRow, 1, 1, DEFAULT_INSETS));
gbcRow++;
if (!editable) {
alertDisplay.add(getSourceLabel(), LayoutHelper.getGBC(0, gbcRow, 1, 0, DEFAULT_INSETS));
alertDisplay.add(alertSource, LayoutHelper.getGBC(1, gbcRow, 1, 1, DEFAULT_INSETS));
gbcRow++;
}
alertDisplay.add(descSp,
LayoutHelper.getGBC(0, gbcRow, 2, 1.0D, 1.0D, GridBagConstraints.BOTH, DEFAULT_INSETS));
gbcRow++;
alertDisplay.add(otherSp,
LayoutHelper.getGBC(0, gbcRow, 2, 1.0D, 1.0D, GridBagConstraints.BOTH, DEFAULT_INSETS));
gbcRow++;
alertDisplay.add(solutionSp,
LayoutHelper.getGBC(0, gbcRow, 2, 1.0D, 1.0D, GridBagConstraints.BOTH, DEFAULT_INSETS));
gbcRow++;
alertDisplay.add(referenceSp,
LayoutHelper.getGBC(0, gbcRow, 2, 1.0D, 1.0D, GridBagConstraints.BOTH, DEFAULT_INSETS));
}
return alertDisplay;
}
public void displayAlert (Alert alert) {
this.originalAlert = alert;
alertUrl.setText(alert.getUri());
if (editable) {
nameListModel.addElement(alert.getName());
alertEditName.setSelectedItem(alert.getName());
alertEditRisk.setSelectedItem(Alert.MSG_RISK[alert.getRisk()]);
alertEditConfidence.setSelectedItem(Alert.MSG_CONFIDENCE[alert.getConfidence()]);
alertEditParam.setSelectedItem(alert.getParam());
alertEditAttack.setText(alert.getAttack());
alertEditAttack.discardAllEdits();
alertEditEvidence.setText(alert.getEvidence());
alertEditEvidence.discardAllEdits();
alertEditCweId.setValue(alert.getCweId());
alertEditWascId.setValue(alert.getWascId());
} else {
alertName.setText(alert.getName());
alertRisk.setText(Alert.MSG_RISK[alert.getRisk()]);
alertRisk.setIcon(alert.getIcon());
alertConfidence.setText(Alert.MSG_CONFIDENCE[alert.getConfidence()]);
alertParam.setText(alert.getParam());
alertAttack.setText(alert.getAttack());
alertEvidence.setText(alert.getEvidence());
alertCweId.setText(Integer.toString(alert.getCweId()));
alertWascId.setText(Integer.toString(alert.getWascId()));
alertSource.setText(Constant.messages.getString(alert.getSource().getI18nKey()));
}
setAlertDescription(alert.getDescription());
setAlertOtherInfo(alert.getOtherInfo());
setAlertSolution(alert.getSolution());
setAlertReference(alert.getReference());
cardLayout.show(this, getAlertPane().getName());
}
public void clearAlert () {
cardLayout.show(this, getDefaultPane().getName());
originalAlert = null;
historyRef = null;
httpMessage = null;
alertName.setText("");
alertRisk.setText("");
alertConfidence.setText("");
alertParam.setText("");
alertAttack.setText("");
alertDescription.setText("");
alertOtherInfo.setText("");
alertSolution.setText("");
alertReference.setText("");
alertSource.setText("");
if (editable) {
alertEditAttack.setText("");
alertEditAttack.discardAllEdits();
alertEditEvidence.setText("");
alertEditEvidence.discardAllEdits();
alertDescription.discardAllEdits();
alertOtherInfo.discardAllEdits();
alertSolution.discardAllEdits();
alertReference.discardAllEdits();
}
}
/**
* This method initializes jScrollPane
*
* @return javax.swing.JScrollPane
*/
private JScrollPane getDefaultPane() {
if (defaultPane == null) {
defaultPane = new JScrollPane();
defaultPane.setViewportView(getDefaultOutput());
defaultPane.setName("defaultPane");
defaultPane.setHorizontalScrollBarPolicy(javax.swing.JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
}
return defaultPane;
}
private ZapTextArea getDefaultOutput() {
if (defaultOutput == null) {
defaultOutput = new ZapTextArea();
defaultOutput.setEditable(false);
defaultOutput.setLineWrap(true);
defaultOutput.setName("");
defaultOutput.append(Constant.messages.getString("alerts.label.defaultMessage"));
}
return defaultOutput;
}
public void append(final String msg) {
if (EventQueue.isDispatchThread()) {
getDefaultOutput().append(msg);
return;
}
try {
EventQueue.invokeAndWait(new Runnable() {
@Override
public void run() {
getDefaultOutput().append(msg);
}
});
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
}
public void clear() {
getDefaultOutput().setText("");
}
public void setParamNames(String[] paramNames) {
for (String param : paramNames) {
paramListModel.addElement(param);
}
}
public Alert getAlert() {
if (! editable && originalAlert != null) {
Alert alert = originalAlert.newInstance();
alert.setAlertId(originalAlert.getAlertId());
alert.setName((String)alertEditName.getSelectedItem());
alert.setParam((String)alertEditParam.getSelectedItem());
alert.setRiskConfidence(alertEditRisk.getSelectedIndex(),
alertEditConfidence.getSelectedIndex());
alert.setDescription(alertDescription.getText());
alert.setOtherInfo(alertOtherInfo.getText());
alert.setSolution(alertSolution.getText());
alert.setReference(alertReference.getText());
alert.setEvidence(alertEvidence.getText());
alert.setCweId(alertEditCweId.getValue());
alert.setWascId(alertEditWascId.getValue());
alert.setHistoryRef(historyRef);
return alert;
}
Alert alert = new Alert(-1, alertEditRisk.getSelectedIndex(),
alertEditConfidence.getSelectedIndex(), (String) alertEditName.getSelectedItem());
alert.setHistoryRef(historyRef);
if (originalAlert != null) {
alert.setAlertId(originalAlert.getAlertId());
alert.setSource(originalAlert.getSource());
}
String uri = null;
HttpMessage msg = null;
if (httpMessage != null) {
uri = httpMessage.getRequestHeader().getURI().toString();
msg = httpMessage;
} else if (historyRef != null) {
try {
uri = historyRef.getURI().toString();
msg = historyRef.getHttpMessage();
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
} else if (originalAlert != null) {
uri = originalAlert.getUri();
msg = originalAlert.getMessage();
}
alert.setDetail(alertDescription.getText(),
uri,
(String)alertEditParam.getSelectedItem(),
alertEditAttack.getText(),
alertOtherInfo.getText(),
alertSolution.getText(),
alertReference.getText(),
alertEditEvidence.getText(),
alertEditCweId.getValue(),
alertEditWascId.getValue(),
msg);
return alert;
}
public Alert getOriginalAlert() {
return this.originalAlert;
}
public void setHistoryRef(HistoryReference historyRef) {
this.historyRef = historyRef;
this.httpMessage = null;
try {
if (historyRef != null) {
HttpMessage msg = historyRef.getHttpMessage();
setParamNames(msg.getParamNames());
this.alertUrl.setText(msg.getRequestHeader().getURI().toString());
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
}
/**
* Sets the {@code HttpMessage} that will be set to the new alert.
*
* @param httpMessage
* the {@code HttpMessage} that will be set to the new alert
*/
public void setHttpMessage(HttpMessage httpMessage) {
this.httpMessage = httpMessage;
setParamNames(httpMessage.getParamNames());
this.alertUrl.setText(httpMessage.getRequestHeader().getURI().toString());
this.historyRef = null;
}
public boolean isEditable() {
return editable;
}
private List <Vulnerability> getAllVulnerabilities() {
if (vulnerabilities == null) {
vulnerabilities = Vulnerabilities.getAllVulnerabilities();
}
return vulnerabilities;
}
private Vulnerability getVulnerability (String alert) {
if (alert == null) {
return null;
}
List <Vulnerability> vulns = this.getAllVulnerabilities();
for (Vulnerability v : vulns) {
if (alert.equals(v.getAlert())) {
return v;
}
}
return null;
}
private List<String> getAllVulnerabilityNames() {
List <Vulnerability> vulns = this.getAllVulnerabilities();
List <String> names = new ArrayList<>(vulns.size());
for (Vulnerability v : vulns) {
names.add(v.getAlert());
}
Collections.sort(names);
return names;
}
private void setAlertDescription(String description) {
setTextDiscardEditsAndInitCaretPosition(alertDescription, description);
}
private void setAlertOtherInfo(String otherInfo) {
setTextDiscardEditsAndInitCaretPosition(alertOtherInfo, otherInfo);
}
private void setAlertSolution(String solution) {
setTextDiscardEditsAndInitCaretPosition(alertSolution, solution);
}
private void setAlertReference(String reference) {
setTextDiscardEditsAndInitCaretPosition(alertReference, reference);
}
private static void setTextDiscardEditsAndInitCaretPosition(ZapTextArea textArea, String text) {
textArea.setText(text);
textArea.discardAllEdits();
textArea.setCaretPosition(0);
}
private JLabel getAttackLabel() {
if (attackLabel == null) {
attackLabel = new JLabel(Constant.messages.getString("alert.label.attack"));
}
return attackLabel;
}
private JLabel getCweidLabel() {
if (cweidLabel == null) {
cweidLabel = new JLabel(Constant.messages.getString("alert.label.cweid"));
}
return cweidLabel;
}
private JLabel getEvidenceLabel() {
if (evidenceLabel == null) {
evidenceLabel = new JLabel(Constant.messages.getString("alert.label.evidence"));
}
return evidenceLabel;
}
private JLabel getParameterLabel() {
if (otherLabel == null) {
otherLabel = new JLabel(Constant.messages.getString("alert.label.parameter"));
}
return otherLabel;
}
private JLabel getConfidenceLabel() {
if (confidenceLabel == null) {
confidenceLabel = new JLabel(Constant.messages.getString("alert.label.confidence"));
}
return confidenceLabel;
}
private JLabel getRiskLabel() {
if (riskLabel == null) {
riskLabel = new JLabel(Constant.messages.getString("alert.label.risk"));
}
return riskLabel;
}
private JLabel getSourceLabel() {
if (sourceLabel == null) {
sourceLabel = new JLabel(Constant.messages.getString("alert.label.source"));
}
return sourceLabel;
}
private JLabel getUrlLabel() {
if (urlLabel == null) {
urlLabel = new JLabel(Constant.messages.getString("alert.label.url"));
}
return urlLabel;
}
private JLabel getWascidLabel() {
if (wascidLabel == null) {
wascidLabel = new JLabel(Constant.messages.getString("alert.label.wascid"));
}
return wascidLabel;
}
}