Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Intruder mvc #27

Merged
merged 4 commits into from
Feb 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,11 @@ public void addKey(Key key) {
oldKey = keys.put(key.getID(), key);
}

for (KeysModelListener modelListener: this.modelListeners) {
modelListener.notifyKeyDeleted(oldKey);
for (KeysModelListener modelListener : modelListeners) {
if (oldKey != null) {
modelListener.notifyKeyDeleted(oldKey);
}

modelListener.notifyKeyInserted(key);
}
}
Expand Down Expand Up @@ -165,7 +168,7 @@ public void deleteKey(String keyId) {
}

if (rowIndex >= 0) {
for (KeysModelListener modelListener: this.modelListeners) {
for (KeysModelListener modelListener : this.modelListeners) {
modelListener.notifyKeyDeleted(rowIndex);
}
}
Expand Down
307 changes: 19 additions & 288 deletions src/main/java/com/blackberry/jwteditor/view/config/ConfigView.form

Large diffs are not rendered by default.

179 changes: 13 additions & 166 deletions src/main/java/com/blackberry/jwteditor/view/config/ConfigView.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,185 +20,32 @@

import burp.api.montoya.ui.UserInterface;
import burp.config.BurpConfig;
import burp.intruder.FuzzLocation;
import burp.intruder.IntruderConfig;
import burp.proxy.HighlightColor;
import burp.proxy.ProxyConfig;
import burp.scanner.ScannerConfig;
import com.blackberry.jwteditor.model.keys.Key;
import com.blackberry.jwteditor.model.keys.KeysModel;
import com.blackberry.jwteditor.model.keys.KeysModelListener.SimpleKeysModelListener;
import com.blackberry.jwteditor.view.utils.DocumentAdapter;
import com.nimbusds.jose.JWSAlgorithm;

import javax.swing.*;
import java.awt.*;
import java.util.List;
import java.util.Optional;

import static java.awt.Font.BOLD;


public class ConfigView {
private final IntruderConfig intruderConfig;
private final BurpConfig burpConfig;
private final UserInterface userInterface;
private final boolean isProVersion;
private final KeysModel keysModel;

private JPanel mainPanel;
private JCheckBox checkBoxHighlightJWT;
private JLabel labelHighlightColor;
private JComboBox comboBoxHighlightColor;
private JLabel labelHighlightJWT;
private JTextField intruderParameterName;
private JComboBox comboBoxPayloadPosition;
private JComboBox comboBoxIntruderSigningKeyId;
private JCheckBox checkBoxHeaderInsertionPoint;
private JTextField scannerParameterName;
private JPanel proxyPanel;
private JLabel proxyLabel;
private JLabel intruderLabel;
private JLabel scannerLabel;
private JPanel intruderPanel;
private JLabel spacerLabel;
private JCheckBox resignIntruderJWS;
private JComboBox comboBoxIntruderSigningAlg;
private ProxyConfigView proxyConfigView;
private ScannerConfigView scannerConfigView;
private IntruderConfigView intruderConfigView;

public ConfigView(BurpConfig burpConfig, UserInterface userInterface, boolean isProVersion, KeysModel keysModel) {
this.burpConfig = burpConfig;
this.userInterface = userInterface;
this.isProVersion = isProVersion;
this.keysModel = keysModel;
this.intruderConfig = burpConfig.intruderConfig();

ProxyConfig proxyConfig = burpConfig.proxyConfig();

checkBoxHighlightJWT.setSelected(proxyConfig.highlightJWT());
checkBoxHighlightJWT.addActionListener(e -> {
comboBoxHighlightColor.setEnabled(checkBoxHighlightJWT.isSelected());
proxyConfig.setHighlightJWT(checkBoxHighlightJWT.isSelected());
});

comboBoxHighlightColor.setModel(new DefaultComboBoxModel<>(HighlightColor.values()));
comboBoxHighlightColor.setSelectedItem(proxyConfig.highlightColor());
comboBoxHighlightColor.setEnabled(proxyConfig.highlightJWT());
comboBoxHighlightColor.addActionListener(e -> proxyConfig.setHighlightColor((HighlightColor) comboBoxHighlightColor.getSelectedItem()));

intruderParameterName.setText(intruderConfig.fuzzParameter());
intruderParameterName.getDocument().addDocumentListener(
new DocumentAdapter(e -> intruderConfig.setFuzzParameter(intruderParameterName.getText()))
);

comboBoxPayloadPosition.setModel(new DefaultComboBoxModel<>(FuzzLocation.values()));
comboBoxPayloadPosition.setSelectedItem(intruderConfig.fuzzLocation());
comboBoxPayloadPosition.addActionListener(e -> intruderConfig.setFuzzLocation((FuzzLocation) comboBoxPayloadPosition.getSelectedItem()));

updateSigningKeyList();
comboBoxIntruderSigningKeyId.addActionListener(e -> {
String newSigningKeyId = (String) comboBoxIntruderSigningKeyId.getSelectedItem();

if (!intruderConfig.signingKeyId().equals(newSigningKeyId)) {
intruderConfig.setSigningKeyId(newSigningKeyId);
updateSigningAlgorithmList();
}
});
comboBoxIntruderSigningAlg.addActionListener(e -> intruderConfig.setSigningAlgorithm((JWSAlgorithm) comboBoxIntruderSigningAlg.getSelectedItem()));
resignIntruderJWS.addActionListener(e -> intruderConfig.setResign(resignIntruderJWS.isSelected()));
keysModel.addKeyModelListener(new SimpleKeysModelListener(this::updateSigningKeyList));

ScannerConfig scannerConfig = burpConfig.scannerConfig();

checkBoxHeaderInsertionPoint.setEnabled(isProVersion);
checkBoxHeaderInsertionPoint.setSelected(scannerConfig.enableHeaderJWSInsertionPointLocation());
checkBoxHeaderInsertionPoint.addActionListener(e -> {
scannerConfig.setEnableHeaderJWSInsertionPointLocation(checkBoxHeaderInsertionPoint.isSelected());
scannerParameterName.setEnabled(checkBoxHeaderInsertionPoint.isSelected());
});

scannerParameterName.setEnabled(scannerConfig.enableHeaderJWSInsertionPointLocation());
scannerParameterName.setText(scannerConfig.insertionPointLocationParameterName());
scannerParameterName.getDocument().addDocumentListener(
new DocumentAdapter(e -> scannerConfig.setInsertionPointLocationParameterName(scannerParameterName.getText()))
);

proxyLabel.setFont(proxyLabel.getFont().deriveFont(BOLD));
intruderLabel.setFont(intruderLabel.getFont().deriveFont(BOLD));
scannerLabel.setFont(scannerLabel.getFont().deriveFont(BOLD));
userInterface.applyThemeToComponent(mainPanel);

comboBoxHighlightColor.setRenderer(new HighlightComboRenderer());
}

private void updateSigningKeyList() {
List<Key> signingKeys = keysModel.getSigningKeys();
String[] signingKeyIds = signingKeys.stream().map(Key::getID).toArray(String[]::new);
String modelSelectedSigningId = intruderConfig.signingKeyId();

String viewSelectedKeyId = (String) comboBoxIntruderSigningKeyId.getSelectedItem();
comboBoxIntruderSigningKeyId.setModel(new DefaultComboBoxModel<>(signingKeyIds));

if (signingKeys.isEmpty()) {
resignIntruderJWS.setSelected(false);
resignIntruderJWS.setEnabled(false);
comboBoxIntruderSigningKeyId.setEnabled(false);
comboBoxIntruderSigningAlg.setEnabled(false);
intruderConfig.setResign(false);
intruderConfig.setSigningKeyId(null);
} else {
resignIntruderJWS.setEnabled(true);
comboBoxIntruderSigningKeyId.setEnabled(true);
comboBoxIntruderSigningAlg.setEnabled(true);

Optional<Key> selectedKey = signingKeys.stream()
.filter(k -> k.getID().equals(modelSelectedSigningId))
.findFirst();


if (selectedKey.isPresent()) {
Key key = selectedKey.get();

resignIntruderJWS.setSelected(intruderConfig.resign());
comboBoxIntruderSigningKeyId.setSelectedItem(key.getID());

if (!modelSelectedSigningId.equals(viewSelectedKeyId)) {
comboBoxIntruderSigningAlg.setModel(new DefaultComboBoxModel(key.getSigningAlgorithms()));
comboBoxIntruderSigningAlg.setSelectedIndex(0);
}
} else {
resignIntruderJWS.setSelected(false);
comboBoxIntruderSigningKeyId.setSelectedIndex(0);

Key key = signingKeys.get(0);
comboBoxIntruderSigningAlg.setModel(new DefaultComboBoxModel(key.getSigningAlgorithms()));
}
}
}

private void updateSigningAlgorithmList() {
Key key = keysModel.getSigningKeys().stream()
.filter(k -> k.getID().equals(intruderConfig.signingKeyId()))
.findFirst()
.orElseThrow();

JWSAlgorithm[] signingAlgorithms = key.getSigningAlgorithms();
comboBoxIntruderSigningAlg.setModel(new DefaultComboBoxModel(signingAlgorithms));

if (signingAlgorithms.length > 0) {
JWSAlgorithm algorithm = signingAlgorithms[0];
comboBoxIntruderSigningAlg.setSelectedItem(algorithm);
intruderConfig.setSigningAlgorithm(algorithm);
}
}

/**
* Custom list cell renderer to color rows of combo box drop down list.
*/
private static class HighlightComboRenderer implements ListCellRenderer<HighlightColor> {
private final ListCellRenderer renderer = new DefaultListCellRenderer();

@Override
public Component getListCellRendererComponent(JList<? extends HighlightColor> list, HighlightColor value, int index, boolean isSelected, boolean cellHasFocus) {
JLabel label = (JLabel) renderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);

Color background = isSelected ? list.getSelectionBackground() : value.color;
label.setBackground(background);

return label;
}
private void createUIComponents() {
proxyConfigView = new ProxyConfigView(userInterface, burpConfig.proxyConfig());
intruderConfigView = new IntruderConfigView(userInterface, new IntruderConfigModel(keysModel, burpConfig.intruderConfig()));
scannerConfigView = new ScannerConfigView(userInterface, burpConfig.scannerConfig(), isProVersion);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
package com.blackberry.jwteditor.view.config;

import burp.intruder.FuzzLocation;
import burp.intruder.IntruderConfig;
import com.blackberry.jwteditor.model.keys.Key;
import com.blackberry.jwteditor.model.keys.KeysModel;
import com.blackberry.jwteditor.model.keys.KeysModelListener.SimpleKeysModelListener;
import com.nimbusds.jose.JWSAlgorithm;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.ArrayList;
import java.util.List;

import static java.util.Arrays.stream;

class IntruderConfigModel {
static final String SIGNING_KEYS_UPDATED = "signingKeysUpdated";
static final String SELECTED_KEY_UPDATED = "selectedKeyUpdated";
static final String SIGNING_ALGORITHMS_UPDATED = "signingAlgorithmsUpdated";
static final String SELECTED_ALGORITHM_UPDATED = "selectedAlgorithmUpdated";
static final String RESIGN_UPDATED = "resignUpdated";

private static final JWSAlgorithm[] NO_ALGORITHMS = new JWSAlgorithm[0];

private final PropertyChangeSupport propertyChangeSupport;
private final KeysModel keysModel;
private final IntruderConfig intruderConfig;
private final List<PropertyChangeListener> listeners;

private String[] signingKeyIds;
private JWSAlgorithm[] selectedKeySigningAlgorithms;

IntruderConfigModel(KeysModel keysModel, IntruderConfig intruderConfig) {
this.keysModel = keysModel;
this.intruderConfig = intruderConfig;
this.signingKeyIds = signingKeyIds();
this.selectedKeySigningAlgorithms = signingAlgorithms();
this.listeners = new ArrayList<>();
this.propertyChangeSupport = new PropertyChangeSupport(this);

keysModel.addKeyModelListener(new SimpleKeysModelListener(this::updateSigningKeyList));
}

String fuzzParameter() {
return intruderConfig.fuzzParameter();
}

void setFuzzParameter(String fuzzParameter) {
intruderConfig.setFuzzParameter(fuzzParameter);
}

FuzzLocation fuzzLocation() {
return intruderConfig.fuzzLocation();
}

void setFuzzLocation(FuzzLocation fuzzLocation) {
intruderConfig.setFuzzLocation(fuzzLocation);
}

FuzzLocation[] fuzzLocations() {
return FuzzLocation.values();
}

boolean hasSigningKeys() {
return !keysModel.getSigningKeys().isEmpty();
}

String[] signingKeyIds() {
return keysModel.getSigningKeys().stream().map(Key::getID).toArray(String[]::new);
}

String signingKeyId() {
return intruderConfig.signingKeyId();
}

public void setSigningKeyId(String signingKeyId) {
String oldSigningKeyId = intruderConfig.signingKeyId();
JWSAlgorithm[] oldAlgorithms = selectedKeySigningAlgorithms;
intruderConfig.setSigningKeyId(signingKeyId);

boolean selectedKeyUnchanged = (oldSigningKeyId == null && signingKeyId==null) || (oldSigningKeyId != null && oldSigningKeyId.equals(signingKeyId));

if (!selectedKeyUnchanged) {
selectedKeySigningAlgorithms = signingAlgorithms();
propertyChangeSupport.firePropertyChange(SIGNING_ALGORITHMS_UPDATED, oldAlgorithms, selectedKeySigningAlgorithms);
}
}

JWSAlgorithm[] signingAlgorithms() {
if (intruderConfig.signingKeyId() == null) {
return NO_ALGORITHMS;
}

return keysModel.getSigningKeys().stream()
.filter(k -> k.getID().equals(intruderConfig.signingKeyId()))
.findFirst()
.orElseThrow()
.getSigningAlgorithms();
}

JWSAlgorithm signingAlgorithm() {
return intruderConfig.signingAlgorithm();
}

void setSigningAlgorithm(JWSAlgorithm signingAlgorithm) {
intruderConfig.setSigningAlgorithm(signingAlgorithm);
}

boolean resign() {
return intruderConfig.resign() && hasSigningKeys();
}

void setResign(boolean resign) {
intruderConfig.setResign(resign);
}

void addPropertyChangeListener(PropertyChangeListener listener) {
listeners.add(listener);
propertyChangeSupport.addPropertyChangeListener(listener);
}

void clearListeners() {
listeners.forEach(propertyChangeSupport::removePropertyChangeListener);
}

private void updateSigningKeyList() {
String[] oldSigningKeyIds = signingKeyIds;
JWSAlgorithm[] oldSigningAlgorithms = selectedKeySigningAlgorithms;
JWSAlgorithm oldSigningAlgorithm = intruderConfig.signingAlgorithm();
signingKeyIds = signingKeyIds();
propertyChangeSupport.firePropertyChange(SIGNING_KEYS_UPDATED, oldSigningKeyIds, signingKeyIds);

String selectedKeyId = intruderConfig.signingKeyId();
boolean modelIsEmpty = signingKeyIds.length == 0;
boolean modelWasEmpty = oldSigningKeyIds.length == 0 && signingKeyIds.length > 0;
boolean selectedKeyDeleted = selectedKeyId != null && (signingKeyIds.length == 0 || stream(signingKeyIds).noneMatch(selectedKeyId::equals));
boolean wasResigning = intruderConfig.resign();

if (modelIsEmpty) {
selectedKeySigningAlgorithms = NO_ALGORITHMS;
propertyChangeSupport.firePropertyChange(SIGNING_ALGORITHMS_UPDATED, oldSigningAlgorithms, NO_ALGORITHMS);

String oldSigningKeyId = intruderConfig.signingKeyId();
intruderConfig.setSigningKeyId(null);
propertyChangeSupport.firePropertyChange(SELECTED_KEY_UPDATED, oldSigningKeyId, null);

intruderConfig.setSigningAlgorithm(null);
propertyChangeSupport.firePropertyChange(SELECTED_ALGORITHM_UPDATED, oldSigningAlgorithm, null);

intruderConfig.setResign(false);
propertyChangeSupport.firePropertyChange(RESIGN_UPDATED, wasResigning, false);
}
else if (modelWasEmpty || selectedKeyDeleted) {
String firstKeyId = signingKeyIds[0];
intruderConfig.setSigningKeyId(firstKeyId);
selectedKeySigningAlgorithms = signingAlgorithms();
JWSAlgorithm firstSigningAlgorithm = selectedKeySigningAlgorithms[0];
intruderConfig.setSigningAlgorithm(firstSigningAlgorithm);
intruderConfig.setResign(false);

propertyChangeSupport.firePropertyChange(SELECTED_KEY_UPDATED, null, firstKeyId);
propertyChangeSupport.firePropertyChange(SIGNING_ALGORITHMS_UPDATED, oldSigningAlgorithms, selectedKeySigningAlgorithms);
propertyChangeSupport.firePropertyChange(SELECTED_ALGORITHM_UPDATED, oldSigningAlgorithm, firstSigningAlgorithm);
propertyChangeSupport.firePropertyChange(RESIGN_UPDATED, wasResigning, false);
}
}
}
Loading
Loading