package com.mcafee.gui; import java.awt.Dimension; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.Scanner; import java.util.concurrent.ExecutionException; import javax.naming.InitialContext; import javax.swing.BorderFactory; import javax.swing.ButtonGroup; import javax.swing.DefaultListModel; import javax.swing.JButton; import javax.swing.JFileChooser; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JProgressBar; import javax.swing.JRadioButton; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.SwingWorker; import javax.swing.border.Border; import javax.swing.border.EtchedBorder; import com.mcafee.AMQOps; import com.mcafee.JmsAuthentication; import com.mcafee.JmsDestination; import com.mcafee.JmsDiggerException; import com.mcafee.JmsHelper; import com.mcafee.JmsLoginInfo; import com.mcafee.JmsPasswordOps; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * * @author Gursev Singh Kalra @ McAfee, Inc. * */ public class AmqOpsTab extends JPanel { private static final long serialVersionUID = 1L; private String title; private static int space = 5; private JmsConfigTab jmsConfigTab; private JmsConfig jmsConfig; private InitialContext initialContext; private JmsLoginInfo loginInfo; private boolean boolResult; private JTextField destNameInput; private JButton createDestButton; private JTextArea outputArea; private JRadioButton queueRadio; private JRadioButton topicRadio; private ButtonGroup radioGroup; private JTextField obtainStatsInput; private JRadioButton queueStats; private JRadioButton topicStats; private JRadioButton brokerStats; private JRadioButton subscriptionStats; private JButton statsButton; private JList<String> decKeysList; private JList<String> encPasswordList; private JButton loadEncPasswordsButton; private JButton clearEncPasswordsButton; private JButton loadDecKeysButton; private JButton clearDecKeysButton; private JButton goDecryptButton; private JFileChooser fileChooser; private JProgressBar progressBar; private static final Logger LOG = LoggerFactory.getLogger(AmqOpsTab.class); private DecryptionWorker decryptionWorker; public String getTitle() { return title; } public AmqOpsTab(JmsConfigTab jmsConfigTab) throws JmsDiggerException { this.jmsConfigTab = jmsConfigTab; this.title = "ActiveMQ Ops"; // jmsConfig = this.jmsConfigTab.getJmsConfig(); // initialContext = jmsConfig.buildInitialContext(); KeyEncPasswdListManipulator keyEncPasswdListManipulator = new KeyEncPasswdListManipulator(); GridBagConstraints masterGbc = new GridBagConstraints(); JPanel masterPanel = new JPanel(new GridBagLayout()); Border border = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED); Insets inset = new Insets(space, space, space, space); Insets masterInset = new Insets(space * 2 , space * 2 , space * 2 , space * 2 ); masterGbc.insets = masterInset; masterGbc.anchor = GridBagConstraints.LINE_START; GridBagConstraints gbc = new GridBagConstraints(); Border createDestBorder = BorderFactory.createTitledBorder(border, "Create Destination"); JPanel createDestPanel = new JPanel(new GridBagLayout()); gbc.insets = inset; JLabel destNameLabel = new JLabel("Name"); gbc.gridx = 0; gbc.gridy = 0; createDestPanel.add(destNameLabel, gbc); destNameInput = new JTextField(15); gbc.gridx = 1; gbc.gridy = 0; createDestPanel.add(destNameInput, gbc); JPanel queueTopicRadioPanel = new JPanel(); queueRadio = new JRadioButton("Queue"); queueRadio.setSelected(true); topicRadio = new JRadioButton("Topic"); radioGroup = new ButtonGroup(); radioGroup.add(queueRadio); radioGroup.add(topicRadio); queueTopicRadioPanel.add(queueRadio); queueTopicRadioPanel.add(topicRadio); queueTopicRadioPanel.setBorder(border); gbc.gridx = 2; gbc.gridy = 0; createDestPanel.add(queueTopicRadioPanel, gbc); createDestButton = new JButton("Go"); gbc.gridx = 3; gbc.gridy = 0; createDestPanel.add(createDestButton, gbc); createDestButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { if(JmsHelper.isStringNullOrEmpty(destNameInput.getText())) { JOptionPane.showMessageDialog(null, "Destination name cannot be empty or null", "Failure", JOptionPane.ERROR_MESSAGE); return; } boolean createQueue = false; if(queueRadio.isSelected()) { createQueue = true; } try { CreateDestinationWorker worker = new CreateDestinationWorker(destNameInput.getText(), createQueue); worker.execute(); createDestButton.setEnabled(false); } catch (JmsDiggerException e) { createDestButton.setEnabled(true); JOptionPane.showMessageDialog(null, "An error has occured. See the results box for details", "Failure", JOptionPane.ERROR_MESSAGE); outputArea.setText(JmsHelper.exceptionStacktraceToString(e)); return; } } }); createDestPanel.setBorder(createDestBorder); masterGbc.insets = masterInset; masterGbc.gridx = 0; masterGbc.gridy = 0; masterPanel.add(createDestPanel, masterGbc); Border obtainStatsBorder = BorderFactory.createTitledBorder(border, "Query Statistics"); JPanel obtainStatsPanel = new JPanel(new GridBagLayout()); JLabel queryStatsLabel = new JLabel("Name"); gbc.insets = inset; gbc.gridx = 0; gbc.gridy = 0; obtainStatsPanel.add(queryStatsLabel, gbc); obtainStatsInput = new JTextField(15); gbc.gridx = 1; gbc.gridy = 0; obtainStatsPanel.add(obtainStatsInput, gbc); JPanel getStatsRadioPanel = new JPanel(); queueStats = new JRadioButton("Queue"); queueStats.setSelected(true); topicStats = new JRadioButton("Topic"); brokerStats = new JRadioButton("Broker"); subscriptionStats = new JRadioButton("Subscription"); ButtonGroup statsRadioGroup = new ButtonGroup(); statsRadioGroup.add(queueStats); statsRadioGroup.add(topicStats); statsRadioGroup.add(brokerStats); statsRadioGroup.add(subscriptionStats); getStatsRadioPanel.add(queueStats); getStatsRadioPanel.add(topicStats); getStatsRadioPanel.add(brokerStats); getStatsRadioPanel.add(subscriptionStats); getStatsRadioPanel.setBorder(border); gbc.gridx = 2; gbc.gridy = 0; obtainStatsPanel.add(getStatsRadioPanel, gbc); statsButton = new JButton("Go"); statsButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { JmsDestination destType = JmsDestination.QUEUE; if((queueStats.isSelected() || topicStats.isSelected()) && JmsHelper.isStringNullOrEmpty(obtainStatsInput.getText())) { JOptionPane.showMessageDialog(null, "Destination name cannot be empty for Queue or Topic Statistics", "Error", JOptionPane.ERROR_MESSAGE); return; } if(queueStats.isSelected()) { destType = JmsDestination.QUEUE; } else { if(topicStats.isSelected()){ destType = JmsDestination.TOPIC; } else { if(brokerStats.isSelected()) { destType = JmsDestination.BROKER; } else { if(subscriptionStats.isSelected()) { destType = JmsDestination.SUBSCRIPTION; } } } } try { QueryDestinationWorker worker = new QueryDestinationWorker(obtainStatsInput.getText(), destType); worker.execute(); statsButton.setEnabled(false); } catch (JmsDiggerException e) { statsButton.setEnabled(true); LOG.info("A JMSDiggerException occured", e); JOptionPane.showMessageDialog(null, "An error has occured. See the results box for details", "Error", JOptionPane.ERROR_MESSAGE); outputArea.setText(JmsHelper.exceptionStacktraceToString(e)); return; } } }); gbc.gridx = 3; gbc.gridy = 0; obtainStatsPanel.add(statsButton, gbc); obtainStatsPanel.setBorder(obtainStatsBorder); masterGbc.insets = masterInset; masterGbc.gridx = 0; masterGbc.gridy = 1; masterPanel.add(obtainStatsPanel, masterGbc); Border decryptBorder = BorderFactory.createTitledBorder(border, "ActiveMQ Password Decryption"); JPanel passwordDecryptPanel = new JPanel(new GridBagLayout()); Dimension encryptedAndPasswordListSize = new Dimension(300,80); gbc = new GridBagConstraints(); //gbc.insets = inset; /* * Build the USERNAME, Jlist and corresponding load and clear buttons */ JPanel encPasswordListPanel = new JPanel(new GridBagLayout()); JLabel encPasswordListLabel = new JLabel("Encrypted Passwords"); gbc.gridx = 0; gbc.gridy = 0; encPasswordListPanel.add(encPasswordListLabel, gbc); encPasswordList = new JList<String>(); encPasswordList.setBorder(border); gbc.gridx = 0; gbc.gridy = 1; JScrollPane encPasswordScrollPane = new JScrollPane(encPasswordList); encPasswordScrollPane.setPreferredSize(encryptedAndPasswordListSize); encPasswordListPanel.add(encPasswordScrollPane, gbc); JPanel encPasswordLoadClearPanel = new JPanel(); loadEncPasswordsButton = new JButton("Load"); loadEncPasswordsButton.addActionListener(keyEncPasswdListManipulator); encPasswordLoadClearPanel.add(loadEncPasswordsButton); clearEncPasswordsButton = new JButton("Clear"); clearEncPasswordsButton.addActionListener(keyEncPasswdListManipulator); encPasswordLoadClearPanel.add(clearEncPasswordsButton); gbc.gridx = 0; gbc.gridy = 2; encPasswordListPanel.add(encPasswordLoadClearPanel, gbc); gbc.gridx = 0; gbc.gridy = 0; passwordDecryptPanel.add(encPasswordListPanel, gbc); /* * Build the PASSWORD, Jlist and corresponding load and clear buttons */ JPanel decKeyPanel = new JPanel(new GridBagLayout()); JLabel decKeyLabel = new JLabel("Decryption Keys"); gbc.gridx = 0; gbc.gridy = 0; decKeyPanel.add(decKeyLabel, gbc); decKeysList = new JList<String>(); decKeysList.setBorder(border); gbc.gridx = 0; gbc.gridy = 1; JScrollPane decKeyScrollPane = new JScrollPane(decKeysList); decKeyScrollPane.setPreferredSize(encryptedAndPasswordListSize); decKeyPanel.add(decKeyScrollPane, gbc); JPanel decKeysLoadClearPanel = new JPanel(); loadDecKeysButton = new JButton("Load"); loadDecKeysButton.addActionListener(keyEncPasswdListManipulator); decKeysLoadClearPanel.add(loadDecKeysButton); clearDecKeysButton = new JButton("Clear"); clearDecKeysButton.addActionListener(keyEncPasswdListManipulator); decKeysLoadClearPanel.add(clearDecKeysButton); gbc.gridx = 0; gbc.gridy = 2; decKeyPanel.add(decKeysLoadClearPanel, gbc); gbc.gridx = 1; gbc.gridy = 0; passwordDecryptPanel.add(decKeyPanel, gbc); /* * Create the go button and stick it to the end of the Fuzzing */ JPanel goDecryptPanel = new JPanel(new GridBagLayout()); goDecryptButton = new JButton("Go"); goDecryptButton.addActionListener(new TriggerDecryptionWorker()); goDecryptPanel.add(goDecryptButton); gbc.gridx = 0; gbc.gridy = 0; goDecryptPanel.add(goDecryptButton, gbc); gbc.gridx = 0; gbc.gridy = 1; gbc.gridwidth = 2; passwordDecryptPanel.add(goDecryptPanel, gbc); passwordDecryptPanel.setBorder(decryptBorder); masterGbc.gridx = 0; masterGbc.gridy = 2; masterPanel.add(passwordDecryptPanel, masterGbc); /* * Add a text box to display results and exception details */ JPanel outputBoxPanel = new JPanel(new GridBagLayout()); outputArea = new JTextArea(9, 55); outputArea.setEditable(false); gbc.fill = GridBagConstraints.BOTH; gbc.gridx = 0; gbc.gridy = 0; outputBoxPanel.add(new JScrollPane(outputArea), gbc); Border authBorder = BorderFactory.createTitledBorder(border, "Results"); outputBoxPanel.setBorder(authBorder); masterGbc.gridx = 0; masterGbc.gridy = 3; masterPanel.add(outputBoxPanel, masterGbc); /* * Pane to display progress */ JPanel progressPanel = new JPanel(new GridBagLayout()); JLabel progressLabel = new JLabel("Progress > "); gbc.gridx = 0; gbc.gridy = 0; gbc.fill = GridBagConstraints.NONE; progressPanel.add(progressLabel, gbc); progressBar = new JProgressBar(); gbc.fill = GridBagConstraints.HORIZONTAL; gbc.gridx = 2; gbc.gridy = 0; gbc.weightx = 1.0; progressPanel.add(progressBar, gbc); masterGbc.gridx = 0; masterGbc.gridy = 4; masterGbc.fill = GridBagConstraints.HORIZONTAL; masterPanel.add(progressPanel, masterGbc); masterGbc = new GridBagConstraints(); masterGbc.gridx = 0; masterGbc.gridy = 0; this.add(masterPanel, masterGbc); } class CreateDestinationWorker extends SwingWorker<ProgressInfo, ProgressInfo> { private AMQOps amqOps; private boolean createQueue; private String destinationName; private InitialContext localInitialContext; private JmsConfig localJmsConfig; // To ensure that the affects of executing this worker are limited its own objects. public CreateDestinationWorker(String destinationName, boolean createQueue) throws JmsDiggerException { localJmsConfig = jmsConfigTab.getJmsConfig(); localInitialContext = localJmsConfig.buildInitialContext(); this.createQueue = createQueue; this.destinationName = destinationName; } @Override protected ProgressInfo doInBackground() { amqOps = new AMQOps(localInitialContext, localJmsConfig.getConnFactName(), localJmsConfig.getLoginInfo()); ProgressInfo pInfo = new ProgressInfo(); try { amqOps.init(); if(createQueue) amqOps.createQueue(destinationName); else amqOps.createTopic(destinationName); pInfo.setSuccessful(true); } catch (JmsDiggerException e) { LOG.info("An error occured while creating a destination", e); pInfo.setDescription(JmsHelper.exceptionStacktraceToString(e)); pInfo.setSuccessful(false); } return pInfo; } @Override public void done() { ProgressInfo pInfo = null; try { pInfo = get(); } catch (InterruptedException e) { LOG.info("An InterruptedException occured", e); } catch (ExecutionException e) { LOG.info("An ExecutionException occured", e); } if(pInfo != null) { if(pInfo.isSuccessful()) { JOptionPane.showMessageDialog(null, "Destination " +destinationName + " created!", "Success", JOptionPane.INFORMATION_MESSAGE); } else { JOptionPane.showMessageDialog(null, "Destination " +destinationName + " could not be created!", "Failure", JOptionPane.ERROR_MESSAGE); outputArea.setText(pInfo.getDescription()); } } createDestButton.setEnabled(true); } } class QueryDestinationWorker extends SwingWorker<ProgressInfo, ProgressInfo> { private AMQOps amqOps; private JmsDestination destType; private String destinationName; private InitialContext localInitialContext; private JmsConfig localJmsConfig; // To ensure that the affects of executing this worker are limited its own objects. public QueryDestinationWorker(String destinationName, JmsDestination destType) throws JmsDiggerException { localJmsConfig = jmsConfigTab.getJmsConfig(); localInitialContext = localJmsConfig.buildInitialContext(); this.destType = destType; this.destinationName = destinationName; } @Override protected ProgressInfo doInBackground() { amqOps = new AMQOps(localInitialContext, localJmsConfig.getConnFactName(), localJmsConfig.getLoginInfo()); ProgressInfo pInfo = new ProgressInfo(); try { amqOps.init(); switch(destType) { case QUEUE: amqOps.getQueueStats(destinationName, true); break; case TOPIC: amqOps.getTopicStats(destinationName, true); break; case BROKER: amqOps.getBrokerStats(); break; case SUBSCRIPTION: amqOps.getSubscriptionsStats(); break; default: amqOps.getBrokerStats(); break; } pInfo.setDescription(amqOps.getStatsAsString()); pInfo.setSuccessful(true); } catch (JmsDiggerException e) { LOG.info("A JMSDiggerException has occured", e); pInfo.setDescription(JmsHelper.exceptionStacktraceToString(e)); pInfo.setSuccessful(false); } return pInfo; } @Override public void done() { ProgressInfo pInfo = null; try { pInfo = get(); } catch (InterruptedException e) { LOG.info("Error occured while retrieving thread results", e); JmsGuiCommon.showErrorAndLogMessage(e.getMessage()); } catch (ExecutionException e) { LOG.info("Error occured while retrieving thread results", e); JmsGuiCommon.showErrorAndLogMessage(e.getMessage()); } if(pInfo != null) { if(pInfo.isSuccessful()) { //JOptionPane.showMessageDialog(null, "Destination " +destinationName + " created!", "Success", JOptionPane.INFORMATION_MESSAGE); outputArea.setText(pInfo.getDescription()); if(JmsHelper.isStringNullOrEmpty(pInfo.getDescription())) outputArea.setText("[-] No information was available"); } else { JOptionPane.showMessageDialog(null, destinationName + " could not be queried!", "Failure", JOptionPane.ERROR_MESSAGE); outputArea.setText(pInfo.getDescription()); } } statsButton.setEnabled(true); } } class KeyEncPasswdListManipulator implements ActionListener { public void actionPerformed(ActionEvent event) { DefaultListModel<String> decKeysAndEncPasswdListModel = new DefaultListModel<String>(); if(event.getSource() == clearDecKeysButton) { decKeysList.setModel(decKeysAndEncPasswdListModel); return; } else { if(event.getSource() == clearEncPasswordsButton) { encPasswordList.setModel(decKeysAndEncPasswdListModel); return; } } fileChooser = new JFileChooser(); fileChooser.setCurrentDirectory(new File(".")); Scanner fileScanner; int result = fileChooser.showOpenDialog(null); if(result == JFileChooser.APPROVE_OPTION) { File file = fileChooser.getSelectedFile(); try { fileScanner = new Scanner(new FileInputStream(file)); while(fileScanner.hasNextLine()) { decKeysAndEncPasswdListModel.addElement(fileScanner.nextLine()); } fileScanner.close(); } catch (FileNotFoundException e) { LOG.info("An error occured with the Scanner", e); JmsGuiCommon.showErrorAndLogMessage("An error occured with the Scanner."); } if(event.getSource() == loadDecKeysButton) decKeysList.setModel(decKeysAndEncPasswdListModel); else if(event.getSource() == loadEncPasswordsButton) encPasswordList.setModel(decKeysAndEncPasswdListModel); } } } class TriggerDecryptionWorker implements ActionListener { public void actionPerformed(ActionEvent event) { outputArea.setText(""); progressBar.setValue(0); DefaultListModel<String> decKeysModel = (DefaultListModel<String>)(decKeysList.getModel()); ArrayList<String> decKeysArrayList = new ArrayList<String>(); DefaultListModel<String> encPasswordsModel = (DefaultListModel<String>)(encPasswordList.getModel()); ArrayList<String> encPasswordsArrayList = new ArrayList<String>(); if(decKeysModel.getSize() == 0 || encPasswordsModel.getSize() == 0) { JOptionPane.showMessageDialog(null, "Decryption Keys or Passwords not available", "Error", JOptionPane.ERROR_MESSAGE); return; } Enumeration<String> e = encPasswordsModel.elements(); while(e.hasMoreElements()) encPasswordsArrayList.add(e.nextElement()); e = decKeysModel.elements(); while(e.hasMoreElements()) decKeysArrayList.add(e.nextElement()); decryptionWorker = new DecryptionWorker(encPasswordsArrayList, decKeysArrayList); decryptionWorker.execute(); disableAllButtons(); } private void disableAllButtons() { loadEncPasswordsButton.setEnabled(false); clearEncPasswordsButton.setEnabled(false); loadDecKeysButton.setEnabled(false); clearDecKeysButton.setEnabled(false); goDecryptButton.setEnabled(false); } } /** * One million decryption keys (passwords) against one password took 260 seconds * @author Gursev Singh Kalra * */ class DecryptionWorker extends SwingWorker<String, ProgressInfo> { private ArrayList<String> encPasswordsArrayList; private ArrayList<String> decKeysArrayList; public DecryptionWorker(ArrayList<String> encPasswordsArrayList, ArrayList<String> decKeysArrayList) { this.encPasswordsArrayList = encPasswordsArrayList; this.decKeysArrayList = decKeysArrayList; } @Override public String doInBackground() throws JmsDiggerException { JmsPasswordOps passwordDecryptor = new JmsPasswordOps(); StringBuilder testResults; StringBuilder workingCreds = new StringBuilder(); String decryptedPassword = null; workingCreds.append("\n\n###########################################################\nSuccessful Decryption:\n"); int encPasswordDecKeyCombinations = encPasswordsArrayList.size() * decKeysArrayList.size(); int count = 0; for(String encPassword: encPasswordsArrayList) { for(String decKey: decKeysArrayList) { testResults = new StringBuilder(); testResults.append("Trying => \"" + encPassword + "\" with \"" + decKey + "\" : Result => "); count++; decryptedPassword = passwordDecryptor.decryptOne(encPassword, decKey); if(decryptedPassword == null) { testResults.append("Failed"); publish(new ProgressInfo(testResults.toString(), false, count*100/encPasswordDecKeyCombinations)); } else { testResults.append("Success"); publish(new ProgressInfo(testResults.toString(), true, count*100/encPasswordDecKeyCombinations)); workingCreds.append("\nEncrypted Password: \"" + encPassword+ "\", Decryption Key: \""+ decKey + "\", Decrypted Password: \"" + decryptedPassword + "\""); } } } return workingCreds.toString(); } @Override public void process(List<ProgressInfo> progressInfo) { progressBar.setValue(progressInfo.get(progressInfo.size() - 1).getPercentage()); for(ProgressInfo pInfo : progressInfo) outputArea.append("\n" + pInfo.getDescription()); } @Override public void done() { try { outputArea.append(get()); } catch (InterruptedException e) { LOG.info("Thread was interrupted", e); } catch (ExecutionException e) { LOG.info("An executionException occured", e); } enableAllButtons(); } private void enableAllButtons() { loadEncPasswordsButton.setEnabled(true); clearEncPasswordsButton.setEnabled(true); loadDecKeysButton.setEnabled(true); clearDecKeysButton.setEnabled(true); goDecryptButton.setEnabled(true); } } }