예제 #1
0
class PrefsPanel(JPanel):
    """JPanle with gui for tool preferences
    """
    def __init__(self, app):
        strings = app.strings

        self.setLayout(GridLayout(3, 2, 5, 5))
        userLbl = JLabel(strings.getString("osmose_pref_username"))
        self.userTextField = JTextField(20)
        self.userTextField.setToolTipText(
            strings.getString("osmose_pref_username_tooltip"))

        levelLbl = JLabel(strings.getString("osmose_pref_level"))
        self.levels = ["1", "1,2", "1,2,3", "2", "3"]
        self.levelsCombo = JComboBox(self.levels)
        self.levelsCombo.setToolTipText(
            strings.getString("osmose_pref_level_tooltip"))

        limitLbl = JLabel(strings.getString("osmose_pref_limit"))
        self.limitTextField = JTextField(20)
        self.limitTextField.setToolTipText(
            strings.getString("osmose_pref_limit_tooltip"))

        self.add(userLbl)
        self.add(self.userTextField)
        self.add(levelLbl)
        self.add(self.levelsCombo)
        self.add(limitLbl)
        self.add(self.limitTextField)

    def update_gui(self, preferences):
        """Update preferences gui
        """
        self.userTextField.setText(preferences["username"])
        self.levelsCombo.setSelectedIndex(
            self.levels.index(preferences["level"]))
        self.limitTextField.setText(str(preferences["limit"]))

    def read_gui(self):
        """Read preferences from gui
        """
        username = self.userTextField.getText()
        level = self.levelsCombo.getSelectedItem()
        limit = self.limitTextField.getText()
        try:
            limit = Integer.parseInt(limit)
            if limit > 500:
                limit = 500
            limit = str(limit)
        except NumberFormatException:
            limit = ""

        preferences = {
            "username": username.strip(),
            "level": level,
            "limit": limit
        }
        return preferences
예제 #2
0
class PrefsPanel(JPanel):
    """JPanle with gui for tool preferences
    """
    def __init__(self, app):
        strings = app.strings

        self.setLayout(GridLayout(3, 2, 5, 5))
        userLbl = JLabel(strings.getString("osmose_pref_username"))
        self.userTextField = JTextField(20)
        self.userTextField.setToolTipText(strings.getString("osmose_pref_username_tooltip"))

        levelLbl = JLabel(strings.getString("osmose_pref_level"))
        self.levels = ["1", "1,2", "1,2,3", "2", "3"]
        self.levelsCombo = JComboBox(self.levels)
        self.levelsCombo.setToolTipText(strings.getString("osmose_pref_level_tooltip"))

        limitLbl = JLabel(strings.getString("osmose_pref_limit"))
        self.limitTextField = JTextField(20)
        self.limitTextField.setToolTipText(strings.getString("osmose_pref_limit_tooltip"))

        self.add(userLbl)
        self.add(self.userTextField)
        self.add(levelLbl)
        self.add(self.levelsCombo)
        self.add(limitLbl)
        self.add(self.limitTextField)

    def update_gui(self, preferences):
        """Update preferences gui
        """
        self.userTextField.setText(preferences["username"])
        self.levelsCombo.setSelectedIndex(self.levels.index(preferences["level"]))
        self.limitTextField.setText(str(preferences["limit"]))

    def read_gui(self):
        """Read preferences from gui
        """
        username = self.userTextField.getText()
        level = self.levelsCombo.getSelectedItem()
        limit = self.limitTextField.getText()
        try:
            limit = Integer.parseInt(limit)
            if limit > 500:
                limit = 500
            limit = str(limit)
        except NumberFormatException:
            limit = ""

        preferences = {"username": username.strip(),
                       "level": level,
                       "limit": limit}
        return preferences
예제 #3
0
 def addDetails(self):
     jf0 = JFrame()
     jf0.setTitle("Add Issue");
     jf0.setLayout(None);
     
     txtEnterIssue = JTextField();
     txtEnterIssue.setName("Enter Issue Name");
     txtEnterIssue.setToolTipText("Enter Issue Name Here");
     txtEnterIssue.setBounds(182, 58, 473, 40);
     jf0.add(txtEnterIssue);
     txtEnterIssue.setColumns(10);
     
     btnNewButton = JButton("Add");
     btnNewButton.setBounds(322, 178, 139, 41);
     jf0.add(btnNewButton);
     
     comboBox = JComboBox();
     comboBox.setMaximumRowCount(20);
     comboBox.setEditable(True);
     comboBox.setToolTipText("Objective Name");
     comboBox.setBounds(182, 125, 473, 40);
     jf0.add(comboBox);
     
     lblNewLabel = JLabel("Issue Name Here");
     lblNewLabel.setFont(Font("Tahoma", Font.PLAIN, 16));
     lblNewLabel.setBounds(25, 58, 130, 40);
     jf0.add(lblNewLabel);
     
     lblNewLabel_1 = JLabel("Objective Name");
     lblNewLabel_1.setFont(Font("Tahoma", Font.PLAIN, 16));
     lblNewLabel_1.setBounds(25, 125, 130, 40);
     jf0.add(lblNewLabel_1);
     jf0.setVisible(True)
     jf0.setBounds(400, 300, 700, 300)
     jf0.EXIT_ON_CLOSE
     
     txtEnterIssue.addKeyListener(self)
class BurpExtender(IBurpExtender, IHttpListener, IMessageEditorTabFactory,
                   ITab):
    #
    # implement IBurpExtender
    #
    def registerExtenderCallbacks(self, callbacks):
        global EXTENSION_NAME

        sys.stdout = callbacks.getStdout()
        sys.stderr = callbacks.getStderr()
        # keep a reference to our callbacks object
        self._callbacks = callbacks

        # obtain an extension helpers object
        self._helpers = callbacks.getHelpers()

        # set our extension name
        callbacks.setExtensionName(EXTENSION_NAME)

        # register ourselves as a Http Listener
        callbacks.registerHttpListener(self)

        # register ourselves as a message editor tab factory
        callbacks.registerMessageEditorTabFactory(self)

        # setup the UI
        self.initGui()

        # add the custom tab to Burp's UI
        self._callbacks.addSuiteTab(self)

        return

    #
    # create the Gui
    #
    def initGui(self):
        #~ if DEBUG:
        #~ import pdb;
        #~ pdb.set_trace()
        tabPane = JTabbedPane(JTabbedPane.TOP)
        CreditsText = "<html># Burp Custom Deserializer<br/># Copyright (c) 2016, Marco Tinari<br/>#<br/># This program is free software: you can redistribute it and/or modify<br/># it under the terms of the GNU General Public License as published by<br/># the Free Software Foundation, either version 3 of the License, or<br/># (at your option) any later version.<br/>#<br/># This program is distributed in the hope that it will be useful,<br/># but WITHOUT ANY WARRANTY; without even the implied warranty of<br/># MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the<br/># GNU General Public License for more details.<br/>#<br/># You should have received a copy of the GNU General Public License<br/># along with this program.  If not, see <http://www.gnu.org/licenses/>.)<br/></html>"
        label1 = JLabel(
            "<html>Usage:<br>1 - Select the desired encoding functions<br>2 - Enter the name of the parameter in the input field below and press the Apply button!</html>"
        )
        label2 = JLabel(CreditsText)
        panel1 = JPanel()
        #set layout
        panel1.setLayout(GridLayout(11, 1))
        panel2 = JPanel()
        panel1.add(label1)
        panel2.add(label2)
        tabPane.addTab("Configuration", panel1)
        tabPane.addTab("Credits", panel2)

        applyButton = JButton('Apply', actionPerformed=self.reloadConf)
        panel1.add(applyButton, BorderLayout.SOUTH)

        #define GET/POST/COOKIE radio button
        self.GETparameterTypeRadioButton = JRadioButton('GET parameter')
        self.POSTparameterTypeRadioButton = JRadioButton('POST parameter')
        self.COOKIEparameterTypeRadioButton = JRadioButton('COOKIE parameter')
        self.POSTparameterTypeRadioButton.setSelected(True)
        group = ButtonGroup()
        group.add(self.GETparameterTypeRadioButton)
        group.add(self.POSTparameterTypeRadioButton)
        group.add(self.COOKIEparameterTypeRadioButton)
        self.base64Enabled = JCheckBox("Base64 encode")
        self.URLEnabled = JCheckBox("URL encode")
        self.ASCII2HexEnabled = JCheckBox("ASCII to Hex")
        self.ScannerEnabled = JCheckBox(
            "<html>Enable serialization in Burp Scanner<br>Usage:<br>1.Place unencoded values inside intruder request and define the placeholder positions<br>2.rightclick->Actively scan defined insertion points)</html>"
        )
        self.IntruderEnabled = JCheckBox(
            "<html>Enable serialization in Burp Intruder<br>Usage:<br>1.Place unencoded values inside intruder request and define the placeholder positions<br>2.Start the attack</html>"
        )
        self.parameterName = JTextField("Parameter name goes here...", 60)

        #set the tooltips
        self.parameterName.setToolTipText(
            "Fill in the parameter name and apply")
        self.base64Enabled.setToolTipText("Enable base64 encoding/decoding")
        self.ASCII2HexEnabled.setToolTipText(
            "Enable ASCII 2 Hex encoding/decoding")
        self.URLEnabled.setToolTipText("Enable URL encoding/decoding")
        self.IntruderEnabled.setToolTipText(
            "Check this if You want the extension to intercept and modify every request made by the Burp Intruder containing the selected paramter"
        )
        self.ScannerEnabled.setToolTipText(
            "Check this if You want the extension to intercept and modify every request made by the Burp Scanner containing the selected paramter"
        )

        #add checkboxes to the panel
        panel1.add(self.parameterName)
        panel1.add(self.POSTparameterTypeRadioButton)
        panel1.add(self.GETparameterTypeRadioButton)
        panel1.add(self.COOKIEparameterTypeRadioButton)
        panel1.add(self.base64Enabled)
        panel1.add(self.URLEnabled)
        panel1.add(self.ASCII2HexEnabled)
        panel1.add(self.IntruderEnabled)
        panel1.add(self.ScannerEnabled)
        #assign tabPane
        self.tab = tabPane

    def reloadConf(self, event):
        #~ if DEBUG:
        #~ import pdb; pdb.set_trace()
        source = event.getSource()
        print 'APPLY button clicked. New configuration loaded.'
        global MAGIC_PARAMETER
        global PARAMETERISPOST
        global PARAMETERISGET
        global PARAMETERISCOOKIE
        global BASE64ENCODINGENABLED
        global ASCII2HEXENCODINGENABLED
        global URLENCODINGENABLED
        global INTRUDERENABLED
        global SCANNERENABLED
        MAGIC_PARAMETER = self.parameterName.getText()
        print 'Base64 checkbox is: ' + str(self.base64Enabled.isSelected())
        if self.base64Enabled.isSelected():
            BASE64ENCODINGENABLED = True
        else:
            BASE64ENCODINGENABLED = False
        print 'ASCII2Hex checkbox is: ' + str(
            self.ASCII2HexEnabled.isSelected())
        if self.ASCII2HexEnabled.isSelected():
            ASCII2HEXENCODINGENABLED = True
        else:
            ASCII2HEXENCODINGENABLED = False
        print 'URL checkbox is: ' + str(self.URLEnabled.isSelected())
        if self.URLEnabled.isSelected():
            URLENCODINGENABLED = True
        else:
            URLENCODINGENABLED = False
        print 'New Magic parameter is: ' + str(MAGIC_PARAMETER)
        if self.POSTparameterTypeRadioButton.isSelected():  #BODYPARAM
            PARAMETERISPOST = True
            print "parameterispost has been set to: " + str(PARAMETERISPOST)
        else:
            PARAMETERISPOST = False
            print "parameterispost has been set to: " + str(PARAMETERISPOST)
        if self.GETparameterTypeRadioButton.isSelected():  #GETPARAM
            PARAMETERISGET = True
            print "parameterisget has been set to: " + str(PARAMETERISGET)
        else:
            PARAMETERISGET = False
            print "parameterisget has been set to: " + str(PARAMETERISGET)
        if self.COOKIEparameterTypeRadioButton.isSelected():  #COOKIEPARAM
            PARAMETERISCOOKIE = True
            print "parameteriscookie has been set to: " + str(
                PARAMETERISCOOKIE)
        else:
            PARAMETERISCOOKIE = False
            print "parameteriscookie has been set to: " + str(
                PARAMETERISCOOKIE)
        if self.ScannerEnabled.isSelected():
            SCANNERENABLED = True
            print "Scanner Enabled"
        else:
            SCANNERENABLED = False
        if self.IntruderEnabled.isSelected():
            INTRUDERENABLED = True
            print "Intruder Enabled"
        else:
            INTRUDERENABLED = False

    #
    # implement IHTTPListener
    #
    def processHttpMessage(self, toolFlag, messageIsRequest, currentRequest):
        global PARAMETERISPOST
        global PARAMETERISGET
        global PARAMETERISCOOKIE
        global URLENCODINGENABLED
        global BASE64ENCODINGENABLED
        global ASCII2HEXENCODINGENABLED
        global INTRUDERENABLED
        global SCANNERENABLED
        #only process requests
        if not messageIsRequest:
            return
        #only process messages from Intruder and Scanner, otherwise exit
        #if (not self._callbacks.TOOL_INTRUDER == toolFlag):
        if ((not (
            (self._callbacks.TOOL_INTRUDER == toolFlag) and INTRUDERENABLED))
                and (not ((self._callbacks.TOOL_SCANNER == toolFlag)
                          and SCANNERENABLED))):
            #print "exiting- toolflag:"+str(toolFlag)+' INTRUDERENABLED='+str(INTRUDERENABLED)+' SCANNERENABLED='+str(SCANNERENABLED)
            return
        #if ((not self._callbacks.TOOL_INTRUDER == toolFlag)) and ((not self._callbacks.TOOL_SCANNER == toolFlag)):#remove the comment to always enable
        if DEBUG:
            print "IHTTPListener Enabled in: " + str(toolFlag)
        requestInfo = self._helpers.analyzeRequest(currentRequest)
        timestamp = datetime.now()
        if DEBUG:
            print "Intercepting message at: ", timestamp.isoformat()
        #parameters = requestInfo.getParameters()
        dataParameter = self._helpers.getRequestParameter(
            currentRequest.getRequest(), MAGIC_PARAMETER)
        #FIXME: add exception handling for multiple parameters with the same name and/or in a different position!!!
        if DEBUG:
            print 'dataparameter:' + str(dataParameter)
        if (dataParameter == None):
            if DEBUG:
                print 'Parameter does not exist'
            return
        serializedValue = dataParameter.getValue()
        #FIXME: substitute '[AND]' placeholder with '&' charachter - we should do something more elegant here :/
        serializedValue = re.sub(r'\[AND\]', '&', serializedValue)
        print "unserialized parameter value: ", str(serializedValue)
        if BASE64ENCODINGENABLED:  #if base64Encode is selected
            serializedValue = self._helpers.base64Encode(serializedValue)
            if DEBUG:
                print "base64 encoded parameter value: ", str(serializedValue)
        if URLENCODINGENABLED:  #if URLEncode is selected
            serializedValue = self._helpers.urlEncode(serializedValue)
            if DEBUG:
                print "URL ecoded parameter value: ", str(serializedValue)
        if ASCII2HEXENCODINGENABLED:  #if ASCII2HexEncode is selected
            serializedValue = convert_ascii2hex(serializedValue)
            if DEBUG:
                print "ASCII2Hex ecoded parameter value: ", str(
                    serializedValue)
        print "serialized parameter value: ", serializedValue
        if PARAMETERISPOST:
            if DEBUG:
                print "parameter is BODY"
            currentRequest.setRequest(
                self._helpers.updateParameter(
                    currentRequest.getRequest(),
                    self._helpers.buildParameter(MAGIC_PARAMETER,
                                                 serializedValue,
                                                 IParameter.PARAM_BODY)))
        elif PARAMETERISGET:
            if DEBUG:
                print "parameter is in URL"
            currentRequest.setRequest(
                self._helpers.updateParameter(
                    currentRequest.getRequest(),
                    self._helpers.buildParameter(MAGIC_PARAMETER,
                                                 serializedValue,
                                                 IParameter.PARAM_URL)))
        elif PARAMETERISCOOKIE:
            if DEBUG:
                print "parameter is a COOKIE"
            currentRequest.setRequest(
                self._helpers.updateParameter(
                    currentRequest.getRequest(),
                    self._helpers.buildParameter(MAGIC_PARAMETER,
                                                 serializedValue,
                                                 IParameter.PARAM_COOKIE)))
        return

    #
    # implement ITab
    #

    def getTabCaption(self):
        global EXTENSION_TABCAPTION
        return (EXTENSION_TABCAPTION)

    def getUiComponent(self):
        #~ return self._splitpane
        return self.tab

    #
    # implement IMessageEditorTabFactory
    #
    def createNewInstance(self, controller, editable):

        # create a new instance of our custom editor tab
        return CustomInputTab(self, controller, editable)
class BurpExtender(IBurpExtender, IScannerCheck, IScanIssue, ITab):
    def registerExtenderCallbacks(self, callbacks):
        self.callbacks = callbacks
        self.helpers = callbacks.getHelpers()
        callbacks.setExtensionName("Missing Scanner Checks")
        self.out = callbacks.getStdout()

        # define all checkboxes
        self.cbPassiveChecks = self.defineCheckBox("Passive Scanner Checks")
        self.cbDOMXSS = self.defineCheckBox("DOM XSS", False)
        self.cbDOMXSSSources = self.defineCheckBox("Sources", False)
        self.cbDOMXSSSinks = self.defineCheckBox("Sinks")
        self.cbDOMXSSjQuerySinks = self.defineCheckBox("jQuery Sinks", False)
        self.grpDOMXSSSettings = JPanel()
        self.grpDOMXSSSettings.add(self.cbDOMXSSSources)
        self.grpDOMXSSSettings.add(self.cbDOMXSSSinks)
        self.grpDOMXSSSettings.add(self.cbDOMXSSjQuerySinks)
        self.cbSTS = self.defineCheckBox("Strict Transport Security")
        self.lblSTSMin = JLabel("Minimum acceptable max-age")
        self.inSTSMin = JTextField(str(STSMinimum), 9, actionPerformed=self.setSTSMinimum) # TODO: actionPerformed only fires on enter key - focus lost would be better
        self.inSTSMin.setToolTipText("Enter the minimum max-age value which is considered as acceptable. Press return to change setting!")
        self.grpSTSSettings = JPanel()
        self.grpSTSSettings.add(self.lblSTSMin)
        self.grpSTSSettings.add(self.inSTSMin)
        self.cbXCTO = self.defineCheckBox("Content Sniffing")
        self.cbXXP = self.defineCheckBox("Client-side XSS Filter Configuration")
        self.cbRedirToHTTPS = self.defineCheckBox("Redirection from HTTP to HTTPS")
        self.btnSave = JButton("Set as default", actionPerformed=self.saveConfig)
        self.btnRestore = JButton("Restore", actionPerformed=self.restoreConfig)
        self.grpConfig = JPanel()
        self.grpConfig.add(self.btnSave)
        self.grpConfig.add(self.btnRestore)
        self.restoreConfig()

        # definition of config tab
        self.tab = JPanel()
        layout = GroupLayout(self.tab)
        self.tab.setLayout(layout)
        layout.setAutoCreateGaps(True)
        layout.setAutoCreateContainerGaps(True)
        layout.setHorizontalGroup(
            layout.createSequentialGroup()
            .addGroup(layout.createParallelGroup()
                      .addComponent(self.cbPassiveChecks)
                      )
            .addGroup(layout.createParallelGroup()
                      .addComponent(self.cbDOMXSS)
                      .addComponent(self.cbSTS)
                      .addComponent(self.cbXCTO)
                      .addComponent(self.cbXXP)
                      .addComponent(self.cbRedirToHTTPS)
                      )
            .addGroup(layout.createParallelGroup()
                      .addComponent(self.grpDOMXSSSettings, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE)
                      .addComponent(self.grpSTSSettings, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE)
                      .addComponent(self.grpConfig, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE)
                      )
            )
        layout.setVerticalGroup(
            layout.createSequentialGroup()
            .addGroup(layout.createParallelGroup()
                      .addComponent(self.cbPassiveChecks)
                      .addComponent(self.cbDOMXSS)
                      .addComponent(self.grpDOMXSSSettings, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE)
                      )
            .addGroup(layout.createParallelGroup()
                      .addComponent(self.cbSTS)
                      .addComponent(self.grpSTSSettings, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE)
                      )
            .addComponent(self.cbXCTO)
            .addComponent(self.cbXXP)
            .addComponent(self.cbRedirToHTTPS)
            .addComponent(self.grpConfig, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE)
            )

        self.domXSSSourcesRE = re.compile("(location\s*[\[.])|([.\[]\s*[\"']?\s*(arguments|dialogArguments|innerHTML|write(ln)?|open(Dialog)?|showModalDialog|cookie|URL|documentURI|baseURI|referrer|name|opener|parent|top|content|self|frames)\W)|(localStorage|sessionStorage|Database)")
        # NOTE: done some optimizations here, original RE caused too much noise
        # - added leading dot in the first part - original recognized "<a href=..." etc.
        # - removed "value" in first part
        self.domXSSSinksRE = re.compile("(\.(src|href|data|location|code|action)\s*[\"'\]]*\s*\+?\s*=)|((replace|assign|navigate|getResponseHeader|open(Dialog)?|showModalDialog|eval|evaluate|execCommand|execScript|setTimeout|setInterval)\s*[\"'\]]*\s*\()")
        self.domXSSjQuerySinksRE = re.compile("after\(|\.append\(|\.before\(|\.html\(|\.prepend\(|\.replaceWith\(|\.wrap\(|\.wrapAll\(|\$\(|\.globalEval\(|\.add\(|jQUery\(|\$\(|\.parseHTML\(")
        self.headerSTSRE = re.compile("^Strict-Transport-Security:.*?max-age=\"?(\d+)\"?", re.I) # TODO: multiple max-age directives cause confusion!
        self.headerXCTORE = re.compile("^X-Content-Type-Options:\s*nosniff\s*$", re.I)
        self.headerXXP = re.compile("^X-XSS-Protection:\s*(\d)(?:\s*;\s*mode\s*=\s*\"?(block)\"?)?", re.I)
        self.headerLocationHTTPS = re.compile("^(?:Content-)?Location:\s*(https://.*)$", re.I)

        callbacks.registerScannerCheck(self)
        callbacks.addSuiteTab(self)

    def defineCheckBox(self, caption, selected=True, enabled=True):
        checkBox = JCheckBox(caption)
        checkBox.setSelected(selected)
        checkBox.setEnabled(enabled)
        return checkBox

    def setSTSMinimum(self, e=None):
        val = self.inSTSMin.text
        if re.match("^\d+$", val):
            STSMinimum = int(val)
        else:
            self.inSTSMin.setText(str(STSMinimum))   # TODO: doesn't works as desired

    def saveConfig(self, e=None):
        config = {
            'passiveChecks': self.cbPassiveChecks.isSelected(),
            'DOMXSS': self.cbDOMXSS.isSelected(),
            'DOMXSSSources': self.cbDOMXSSSources.isSelected(),
            'DOMXSSSinks': self.cbDOMXSSSinks.isSelected(),
            'DOMXSSjQuerySinks': self.cbDOMXSSjQuerySinks.isSelected(),
            'STS': self.cbSTS.isSelected(),
            'STSMin': self.inSTSMin.text,
            'XCTO': self.cbXCTO.isSelected(),
            'XXP': self.cbXXP.isSelected(),
            'RedirToHTTPS': self.cbRedirToHTTPS.isSelected(),
            }
        self.callbacks.saveExtensionSetting("config", pickle.dumps(config))

    def restoreConfig(self, e=None):
        storedConfig = self.callbacks.loadExtensionSetting("config")
        if storedConfig != None:
            try:
                config = pickle.loads(storedConfig)
                self.cbPassiveChecks.setSelected(config['passiveChecks'])
                self.cbDOMXSS.setSelected(config['DOMXSS'])
                self.cbDOMXSSSources.setSelected(config['DOMXSSSources'])
                self.cbDOMXSSSinks.setSelected(config['DOMXSSSinks'])
                self.cbDOMXSSjQuerySinks.setSelected(config['DOMXSSjQuerySinks'])
                self.cbSTS.setSelected(config['STS'])
                self.inSTSMin.text = config['STSMin'] 
                self.cbXCTO.setSelected(config['XCTO'])
                self.cbXXP.setSelected(config['XXP'])
                self.cbRedirToHTTPS.setSelected(config['RedirToHTTPS'])
                self.setSTSMinimum()
            except:
                print("Classical case of \"shouldn't happen\": something went wrong with config restore. Submit a bug or patch and keep your eyes open for Zombies. Something is really strange here.\nConfig contained: " + storedConfig)
        
    ### ITab ###
    def getTabCaption(self):
        return("Additional Scanner Checks")

    def getUiComponent(self):
        return self.tab

    ### IScannerCheck ###
    def doPassiveScan(self, baseRequestResponse):
        if not self.cbPassiveChecks.isSelected():
            return None
        scanIssues = list()
        requestProtocol = baseRequestResponse.getHttpService().getProtocol()
        analyzedResponse = self.helpers.analyzeResponse(baseRequestResponse.getResponse())
        responseHeaders = analyzedResponse.getHeaders()
        bodyOffset = analyzedResponse.getBodyOffset()
        responseBody = baseRequestResponse.getResponse()[analyzedResponse.getBodyOffset():].tostring()

        # Identify DOMXSS sources and sinks
        domXSSSources = list()
        domXSSSinks = list()
        domXSSjQuerySinks = list()
        
        if self.cbDOMXSS.isSelected():
            if self.cbDOMXSSSources.isSelected():
                domXSSSources = self.domXSSSourcesRE.finditer(responseBody)
            if self.cbDOMXSSSinks.isSelected():
                domXSSSinks = self.domXSSSinksRE.finditer(responseBody)
            if self.cbDOMXSSjQuerySinks.isSelected():
                domXSSjQuerySinks = self.domXSSjQuerySinksRE.finditer(responseBody)

            domXSSSourcesPos = extractMatchPositions(domXSSSources, bodyOffset)
            domXSSSinksPos = extractMatchPositions(domXSSSinks, bodyOffset)
            domXSSjQuerySinksPos = extractMatchPositions(domXSSjQuerySinks, bodyOffset)

            if len(domXSSSourcesPos) + len(domXSSSinksPos) + len(domXSSjQuerySinksPos) > 0: # One of the DOMXSS REs matched
                scanIssues.append(DOMXSSScanIssue(
                    baseRequestResponse,
                    domXSSSourcesPos,
                    domXSSSinksPos,
                    domXSSjQuerySinksPos,
                    self.helpers,
                    self.callbacks
                    ))

        # Identify missing, wrong or multiple occurring HTTP headers
        headersSTS = list()
        headersXCTO = list()
        headersXXP = list()
        headersLocationHTTPS = list()

        offset = 0
        for header in responseHeaders:
            if self.cbSTS.isSelected():
                match = self.headerSTSRE.match(header)
                if match:
                    headersSTS.append((match, offset))

            if self.cbXCTO.isSelected():
                match = self.headerXCTORE.match(header)
                if match:
                    headersXCTO.append(match)

            if self.cbXXP.isSelected():
                match = self.headerXXP.match(header)
                if match:
                    headersXXP.append((match, offset))

            if self.cbRedirToHTTPS.isSelected() and requestProtocol == 'http':
                match = self.headerLocationHTTPS.match(header)
                if match:
                    headersLocationHTTPS.append((match, offset))

            offset += len(header) + 2     # TODO: assumption that CRLF is always used. The world is ugly, make a real check.

        if requestProtocol != "https":
            pass                          # HSTS only valid in HTTPS responses.
        elif self.cbSTS.isSelected():
            if len(headersSTS) == 0:        # No HSTS header
                scanIssues.append(STSScanIssue(
                    baseRequestResponse,
                    STSScanIssue.caseNoHeader,
                    None,
                    self.helpers,
                    self.callbacks
                    ))
            elif len(headersSTS) == 1 and int(headersSTS[0][0].group(1)) < STSMinimum: # HSTS header present, but time frame too short
                scanIssues.append(STSScanIssue(
                    baseRequestResponse,
                    STSScanIssue.caseTooLow,
                    (int(headersSTS[0][0].group(1)), headersSTS[0][1] + headersSTS[0][0].start(1), headersSTS[0][1] + headersSTS[0][0].end(1)),
                    self.helpers,
                    self.callbacks
                    ))
            elif len(headersSTS) > 1:         # multiple HSTS headers
                scanIssues.append(STSScanIssue(
                    baseRequestResponse,
                    STSScanIssue.caseMultipleHeaders,
                    headersSTS,
                    self.helpers,
                    self.callbacks
                    ))

        # Redirection from HTTP to HTTPS
        if self.cbRedirToHTTPS.isSelected() and len(headersLocationHTTPS) > 0:
            scanIssues.append(RedirectFromHTTP2HTTPSScanIssue(
                baseRequestResponse,
                headersLocationHTTPS,
                self.helpers,
                self.callbacks                
                ))

        if self.cbXXP.isSelected():
            if len(headersXXP) == 0:          # No XSS protection header
                scanIssues.append(XXPScanIssue(
                    baseRequestResponse,
                    XXPScanIssue.caseNoHeader,
                    None,
                    self.helpers,
                    self.callbacks
                    ))
            elif len(headersXXP) == 1 and int(headersXXP[0][0].group(1)) == 1 and headersXXP[0][0].group(2) != "block":          # Activated but not in block mode
                scanIssues.append(XXPScanIssue(
                    baseRequestResponse,
                    XXPScanIssue.caseNoBlockMode,
                    headersXXP,
                    self.helpers,
                    self.callbacks
                    ))
            elif len(headersXXP) > 1:          # Multiple XXP headers
                scanIssues.append(XXPScanIssue(
                    baseRequestResponse,
                    XXPScanIssue.caseMultipleHeaders,
                    headersXXP,
                    self.helpers,
                    self.callbacks
                    ))
                # "X-XSS-Protection: 0" already catched by Burp
            

        # X-Content-Type-Options missing
        # NOTE: it is assumed that multiple "X-Content-Type-Options: nosniff" headers can't cause confusion at browser side because they all have the same meaning.
        if self.cbXCTO.isSelected() and len(headersXCTO) == 0:
            scanIssues.append(XCTOScanIssue(
                baseRequestResponse,
                self.helpers,
                self.callbacks
                ))

        return scanIssues

    def consolidateDuplicateIssues(self, existingIssue, newIssue):
        if existingIssue.getIssueName() == newIssue.getIssueName():
            if newIssue.getIssueName() == issueNameDOMXSS:   # DOMXSS issues are different if response content is different.
                responseExisting = existingIssue.getHttpMessages()[0].getResponse()
                analyzedResponseExisting = self.helpers.analyzeResponse(responseExisting)
                bodyOffsetExisting = analyzedResponseExisting.getBodyOffset()
                responseBodyExisting = responseExisting.getResponse()[analyzedResponseExisting.getBodyOffset():].tostring()

                responseNew = newIssue.getHttpMessages()[0].getResponse()
                analyzedResponseNew = self.helpers.analyzeResponse(responseNew)
                bodyOffsetNew = analyzedResponseNew.getBodyOffset()
                responseBodyNew = responseNew.getResponse()[analyzedResponseNew.getBodyOffset():].tostring()

                if responseBodyExisting == responseBodyNew:
                    return -1
                else:
                    return 0
            elif newIssue.getIssueName() == issueNameRedirectFromHTTP2HTTPS: # Redirection issues are different if target URLs differ
                if existingIssue.getIssueDetail() == newIssue.getIssueDetail():
                    return -1
                else:
                    return 0
            else:                         # In all other cases: keep existing issue
                return -1
        return 0
class BurpExtender(IBurpExtender, IHttpListener, IMessageEditorTabFactory, ITab):
    #
    # implement IBurpExtender
    #
    def	registerExtenderCallbacks(self, callbacks):
        global EXTENSION_NAME
        
        sys.stdout = callbacks.getStdout()
        sys.stderr = callbacks.getStderr()
        # keep a reference to our callbacks object
        self._callbacks = callbacks
        
        # obtain an extension helpers object
        self._helpers = callbacks.getHelpers()
        
        # set our extension name
        callbacks.setExtensionName(EXTENSION_NAME)
        
        # register ourselves as a Http Listener
        callbacks.registerHttpListener(self)

        # register ourselves as a message editor tab factory
        callbacks.registerMessageEditorTabFactory(self) 
        
        # setup the UI
        self.initGui()        
        
        # add the custom tab to Burp's UI
        self._callbacks.addSuiteTab(self)  
        
        return
    #
    # create the Gui
    #    
    def initGui(self):
        #~ if DEBUG:
            #~ import pdb;
            #~ pdb.set_trace()
        tabPane = JTabbedPane(JTabbedPane.TOP)
        CreditsText = "<html># Burp Custom Deserializer<br/># Copyright (c) 2016, Marco Tinari<br/>#<br/># This program is free software: you can redistribute it and/or modify<br/># it under the terms of the GNU General Public License as published by<br/># the Free Software Foundation, either version 3 of the License, or<br/># (at your option) any later version.<br/>#<br/># This program is distributed in the hope that it will be useful,<br/># but WITHOUT ANY WARRANTY; without even the implied warranty of<br/># MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the<br/># GNU General Public License for more details.<br/>#<br/># You should have received a copy of the GNU General Public License<br/># along with this program.  If not, see <http://www.gnu.org/licenses/>.)<br/></html>"
        label1 = JLabel("<html>Usage:<br>1 - Select the desired encoding functions<br>2 - Enter the name of the parameter in the input field below and press the Apply button!</html>")
        label2 = JLabel(CreditsText)
        panel1 = JPanel()
        #set layout
        panel1.setLayout(GridLayout(11,1))
        panel2 = JPanel()
        panel1.add(label1)
        panel2.add(label2)
        tabPane.addTab("Configuration", panel1)
        tabPane.addTab("Credits", panel2)

        applyButton = JButton('Apply',actionPerformed=self.reloadConf)
        panel1.add(applyButton, BorderLayout.SOUTH)
        
        #define GET/POST/COOKIE radio button
        self.GETparameterTypeRadioButton = JRadioButton('GET parameter')
        self.POSTparameterTypeRadioButton = JRadioButton('POST parameter')
        self.COOKIEparameterTypeRadioButton = JRadioButton('COOKIE parameter')
        self.POSTparameterTypeRadioButton.setSelected(True)
        group = ButtonGroup()
        group.add(self.GETparameterTypeRadioButton)
        group.add(self.POSTparameterTypeRadioButton)
        group.add(self.COOKIEparameterTypeRadioButton)
        self.base64Enabled = JCheckBox("Base64 encode")
        self.URLEnabled = JCheckBox("URL encode")
        self.ASCII2HexEnabled = JCheckBox("ASCII to Hex")
        self.ScannerEnabled = JCheckBox("<html>Enable serialization in Burp Scanner<br>Usage:<br>1.Place unencoded values inside intruder request and define the placeholder positions<br>2.rightclick->Actively scan defined insertion points)</html>")
        self.IntruderEnabled = JCheckBox("<html>Enable serialization in Burp Intruder<br>Usage:<br>1.Place unencoded values inside intruder request and define the placeholder positions<br>2.Start the attack</html>")
        self.parameterName = JTextField("Parameter name goes here...",60)
        
        #set the tooltips
        self.parameterName.setToolTipText("Fill in the parameter name and apply")
        self.base64Enabled.setToolTipText("Enable base64 encoding/decoding")
        self.ASCII2HexEnabled.setToolTipText("Enable ASCII 2 Hex encoding/decoding") 
        self.URLEnabled.setToolTipText("Enable URL encoding/decoding")
        self.IntruderEnabled.setToolTipText("Check this if You want the extension to intercept and modify every request made by the Burp Intruder containing the selected paramter")
        self.ScannerEnabled.setToolTipText("Check this if You want the extension to intercept and modify every request made by the Burp Scanner containing the selected paramter")

        #add checkboxes to the panel            
        panel1.add(self.parameterName)
        panel1.add(self.POSTparameterTypeRadioButton)
        panel1.add(self.GETparameterTypeRadioButton)
        panel1.add(self.COOKIEparameterTypeRadioButton)
        panel1.add(self.base64Enabled)
        panel1.add(self.URLEnabled)
        panel1.add(self.ASCII2HexEnabled)
        panel1.add(self.IntruderEnabled)
        panel1.add(self.ScannerEnabled)
        #assign tabPane
        self.tab = tabPane
        
    def reloadConf(self,event):
        #~ if DEBUG:
            #~ import pdb; pdb.set_trace()
        source = event.getSource()
        print 'APPLY button clicked. New configuration loaded.'
        global MAGIC_PARAMETER
        global PARAMETERISPOST
        global PARAMETERISGET
        global PARAMETERISCOOKIE
        global BASE64ENCODINGENABLED
        global ASCII2HEXENCODINGENABLED
        global URLENCODINGENABLED
        global INTRUDERENABLED
        global SCANNERENABLED
        MAGIC_PARAMETER=self.parameterName.getText()
        print 'Base64 checkbox is: '+str(self.base64Enabled.isSelected())
        if self.base64Enabled.isSelected(): 
            BASE64ENCODINGENABLED=True
        else:
            BASE64ENCODINGENABLED=False
        print 'ASCII2Hex checkbox is: '+str(self.ASCII2HexEnabled.isSelected())
        if self.ASCII2HexEnabled.isSelected(): 
            ASCII2HEXENCODINGENABLED=True
        else:
            ASCII2HEXENCODINGENABLED=False
        print 'URL checkbox is: '+str(self.URLEnabled.isSelected())
        if self.URLEnabled.isSelected(): 
            URLENCODINGENABLED=True
        else:
            URLENCODINGENABLED=False
        print 'New Magic parameter is: '+str(MAGIC_PARAMETER)
        if self.POSTparameterTypeRadioButton.isSelected(): #BODYPARAM
            PARAMETERISPOST=True
            print "parameterispost has been set to: " + str(PARAMETERISPOST)
        else:
            PARAMETERISPOST=False
            print "parameterispost has been set to: " + str(PARAMETERISPOST)
        if self.GETparameterTypeRadioButton.isSelected(): #GETPARAM
            PARAMETERISGET=True
            print "parameterisget has been set to: " + str(PARAMETERISGET)
        else:
            PARAMETERISGET=False
            print "parameterisget has been set to: " + str(PARAMETERISGET)
        if self.COOKIEparameterTypeRadioButton.isSelected(): #COOKIEPARAM
            PARAMETERISCOOKIE=True
            print "parameteriscookie has been set to: " + str(PARAMETERISCOOKIE)
        else:
            PARAMETERISCOOKIE=False
            print "parameteriscookie has been set to: " + str(PARAMETERISCOOKIE)
        if self.ScannerEnabled.isSelected(): 
            SCANNERENABLED=True
            print "Scanner Enabled"
        else:
            SCANNERENABLED=False
        if self.IntruderEnabled.isSelected(): 
            INTRUDERENABLED=True
            print "Intruder Enabled"
        else:
            INTRUDERENABLED=False
    #
    # implement IHTTPListener
    #
    def processHttpMessage(self, toolFlag, messageIsRequest, currentRequest):
        global PARAMETERISPOST
        global PARAMETERISGET
        global PARAMETERISCOOKIE
        global URLENCODINGENABLED
        global BASE64ENCODINGENABLED
        global ASCII2HEXENCODINGENABLED
        global INTRUDERENABLED
        global SCANNERENABLED
        #only process requests
        if not messageIsRequest:
            return
        #only process messages from Intruder and Scanner, otherwise exit
        #if (not self._callbacks.TOOL_INTRUDER == toolFlag):
        if ((not ((self._callbacks.TOOL_INTRUDER == toolFlag) and INTRUDERENABLED)) and (not ((self._callbacks.TOOL_SCANNER == toolFlag) and SCANNERENABLED))):
            #print "exiting- toolflag:"+str(toolFlag)+' INTRUDERENABLED='+str(INTRUDERENABLED)+' SCANNERENABLED='+str(SCANNERENABLED)
            return
        #if ((not self._callbacks.TOOL_INTRUDER == toolFlag)) and ((not self._callbacks.TOOL_SCANNER == toolFlag)):#remove the comment to always enable
        if DEBUG:
            print "IHTTPListener Enabled in: " + str(toolFlag)
        requestInfo = self._helpers.analyzeRequest(currentRequest)
        timestamp = datetime.now()
        if DEBUG: 
            print "Intercepting message at: ", timestamp.isoformat()
        #parameters = requestInfo.getParameters()
        dataParameter = self._helpers.getRequestParameter(currentRequest.getRequest(), MAGIC_PARAMETER)
        #FIXME: add exception handling for multiple parameters with the same name and/or in a different position!!!
        if DEBUG:
            print 'dataparameter:'+str(dataParameter)
        if (dataParameter == None):
            if DEBUG:
                print 'Parameter does not exist'
            return
        serializedValue = dataParameter.getValue()
        #FIXME: substitute '[AND]' placeholder with '&' charachter - we should do something more elegant here :/
        serializedValue = re.sub(r'\[AND\]', '&', serializedValue) 
        print "unserialized parameter value: ", str(serializedValue)
        if BASE64ENCODINGENABLED: #if base64Encode is selected
            serializedValue = self._helpers.base64Encode(serializedValue)
            if DEBUG:
                print "base64 encoded parameter value: ", str(serializedValue)
        if URLENCODINGENABLED: #if URLEncode is selected
            serializedValue = self._helpers.urlEncode(serializedValue)
            if DEBUG:
                print "URL ecoded parameter value: ", str(serializedValue)
        if ASCII2HEXENCODINGENABLED: #if ASCII2HexEncode is selected
            serializedValue = convert_ascii2hex(serializedValue)
            if DEBUG:
                print "ASCII2Hex ecoded parameter value: ", str(serializedValue)
        print "serialized parameter value: ", serializedValue
        if PARAMETERISPOST:
            if DEBUG:
                print "parameter is BODY"
            currentRequest.setRequest(self._helpers.updateParameter(currentRequest.getRequest(),self._helpers.buildParameter(MAGIC_PARAMETER, serializedValue,IParameter.PARAM_BODY)))
        elif PARAMETERISGET:
            if DEBUG:
                print "parameter is in URL"
            currentRequest.setRequest(self._helpers.updateParameter(currentRequest.getRequest(),self._helpers.buildParameter(MAGIC_PARAMETER, serializedValue,IParameter.PARAM_URL)))       
        elif PARAMETERISCOOKIE:
            if DEBUG:
                print "parameter is a COOKIE"
            currentRequest.setRequest(self._helpers.updateParameter(currentRequest.getRequest(),self._helpers.buildParameter(MAGIC_PARAMETER, serializedValue,IParameter.PARAM_COOKIE)))       
        return
    
    # 
    # implement ITab
    #
    
    def getTabCaption(self):
        global EXTENSION_TABCAPTION
        return(EXTENSION_TABCAPTION)

    def getUiComponent(self):
        #~ return self._splitpane
        return self.tab


    # 
    # implement IMessageEditorTabFactory
    #
    def createNewInstance(self, controller, editable):
        
        # create a new instance of our custom editor tab
        return CustomInputTab(self, controller, editable)
예제 #7
0
class CumulusUI(JFrame):
    '''Java Swing used to create a JFrame UI.  On init the objects will be
    populated with information derived from URL requests to CUMULUS and
    the open CWMS watershed.
    '''
    def __init__(self, arg_dict):
        super(CumulusUI, self).__init__()

        # Load argument from the command line
        self.start_time = arg_dict['start_time']
        self.end_time = arg_dict['end_time']
        self.dss_path = arg_dict['dss_path']
        self.cwms_home = arg_dict['cwms_home']
        self.config = arg_dict['config']

        # Get the DSS Path if one was saved in the "cumulus.config" file
        if os.path.isfile(self.config):
            with open(os.path.join(APPDATA, "cumulus.config")) as f:
                self.dss_path = f.read()

        # Get the basins and products, load JSON, create lists for JList, and create dictionaries
        self.basin_download = json.loads(self.http_get(url_basins))        
        self.jlist_basins = ["{}:{}".format(b['office_symbol'], b['name']) for b in self.basin_download]
        self.basin_meta = dict(zip(self.jlist_basins, self.basin_download))
        self.jlist_basins.sort()

        self.product_download = json.loads(self.http_get(url_products))
        self.jlist_products = ["{}".format(p['name'].replace("_", " ").title()) for p in self.product_download]
        self.product_meta = dict(zip(self.jlist_products, self.product_download))
        self.jlist_products.sort()

        btn_submit = JButton()
        lbl_start_date = JLabel()
        lbl_end_date = JLabel()
        self.txt_select_file = JTextField()
        btn_select_file = JButton()
        lbl_origin = JLabel()
        lbl_extent = JLabel()
        lbl_select_file = JLabel()

        self.txt_start_time = JTextField()
        self.txt_end_time = JTextField()

        jScrollPane1 = JScrollPane()
        self.lst_product = JList()
        self.lst_product = JList(self.jlist_products, valueChanged = self.choose_product)
        
        jScrollPane2 = JScrollPane()
        self.lst_watershed = JList()
        self.lst_watershed = JList(self.jlist_basins, valueChanged = self.choose_watershed)

        self.cwms_dssname = JCheckBox()

        self.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE)
        self.setTitle("Cumulus CAVI UI")
        self.setLocation(Point(10, 10))
        self.setLocationByPlatform(True)
        self.setName("CumulusCaviUi")
        self.setResizable(False)

        btn_submit.setFont(Font("Tahoma", 0, 18))
        btn_submit.setText("Submit")
        btn_submit.actionPerformed = self.submit

        lbl_start_date.setText("Start Date/Time")

        lbl_end_date.setText("End Date/Time")

        self.txt_select_file.setToolTipText("FQPN to output file (.dss)")

        btn_select_file.setText("...")
        btn_select_file.setToolTipText("Select File...")
        btn_select_file.actionPerformed = self.select_file

        lbl_origin.setText("Minimum (x,y):")

        lbl_extent.setText("Maximum (x,y):")

        lbl_select_file.setText("Output File Location")

        self.txt_start_time.setToolTipText("Start Time")
        self.txt_end_time.setToolTipText("End Time")

        self.lst_product.setBorder(BorderFactory.createTitledBorder(None, "Available Products", TitledBorder.CENTER, TitledBorder.TOP, Font("Tahoma", 0, 14)))
        self.lst_product.setFont(Font("Tahoma", 0, 14))
        jScrollPane1.setViewportView(self.lst_product)
        self.lst_product.getAccessibleContext().setAccessibleName("Available Products")
        self.lst_product.getAccessibleContext().setAccessibleParent(jScrollPane2)

        self.lst_watershed.setBorder(BorderFactory.createTitledBorder(None, "Available Watersheds", TitledBorder.CENTER, TitledBorder.TOP, Font("Tahoma", 0, 14)))
        self.lst_watershed.setFont(Font("Tahoma", 0, 14))
        self.lst_watershed.setSelectionMode(ListSelectionModel.SINGLE_SELECTION)
        jScrollPane2.setViewportView(self.lst_watershed)

        self.cwms_dssname.setText("CWMS DSS filename")
        self.cwms_dssname.setToolTipText("Parameter.yyyy.mm.dss")
        self.cwms_dssname.setVisible(False)

        layout = GroupLayout(self.getContentPane());
        self.getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING, False)
                    .addComponent(lbl_select_file)
                    .addComponent(jScrollPane1)
                    .addComponent(jScrollPane2)
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(GroupLayout.Alignment.TRAILING)
                            .addComponent(btn_submit)
                            .addComponent(self.txt_select_file, GroupLayout.PREFERRED_SIZE, 377, GroupLayout.PREFERRED_SIZE))
                        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(btn_select_file))
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
                            .addComponent(lbl_start_date)
                            .addComponent(self.txt_start_time, GroupLayout.PREFERRED_SIZE, 170, GroupLayout.PREFERRED_SIZE))
                        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
                            .addComponent(self.txt_end_time, GroupLayout.PREFERRED_SIZE, 170, GroupLayout.PREFERRED_SIZE)
                            .addComponent(lbl_end_date))))
                .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        )
        layout.setVerticalGroup(
            layout.createParallelGroup(GroupLayout.Alignment.LEADING)
            .addGroup(GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addGap(25, 25, 25)
                .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
                    .addComponent(lbl_start_date)
                    .addComponent(lbl_end_date))
                .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
                    .addComponent(self.txt_start_time, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
                    .addComponent(self.txt_end_time, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
                .addGap(18, 18, 18)
                .addComponent(jScrollPane2, GroupLayout.PREFERRED_SIZE, 201, GroupLayout.PREFERRED_SIZE)
                .addGap(18, 18, 18)
                .addComponent(jScrollPane1, GroupLayout.PREFERRED_SIZE, 201, GroupLayout.PREFERRED_SIZE)
                .addGap(18, 18, Short.MAX_VALUE)
                .addComponent(lbl_select_file)
                .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
                    .addComponent(self.txt_select_file, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
                    .addComponent(btn_select_file))
                .addGap(18, 18, 18)
                .addComponent(btn_submit)
                .addContainerGap())
        )

        self.txt_select_file.setText(self.dss_path)
        self.txt_start_time.setText(self.start_time)
        self.txt_end_time.setText(self.end_time)

        self.pack()
        self.setLocationRelativeTo(None)

    def http_get(self, url):
        '''Return java.lang.String JSON
        
        Input: java.lang.String URL
        '''
        start_timer = System.currentTimeMillis()
        try:
            url = URL(url)
            urlconnect = url.openConnection()
            br = BufferedReader(
                InputStreamReader(
                    urlconnect.getInputStream(), "UTF-8"
                )
            )
            s = br.readLine()
            br.close()
        except MalformedURLException() as ex:
            cumulus_logger.error(str(ex))
            MessageBox.showError(str(ex), "Exception")
            raise
        except IOException as ex:
            cumulus_logger.error(str(ex))
            MessageBox.showError(str(ex), "Exception")
            raise
        end_timer = System.currentTimeMillis()
        cumulus_logger.debug(
            "HTTP GET (milliseconds): {}".format(
                (end_timer - start_timer)
                )
        )

        return s

    def http_post(self, json_string, url):
        '''Return java.lang.String JSON

        Input: java.lang.String JSON, java.lang.String URL
        '''
        start_timer = System.currentTimeMillis()

        try:
            # Get a connection and set the request properties
            url = URL(url)
            urlconnect = url.openConnection()
            urlconnect.setDoOutput(True)
            urlconnect.setRequestMethod("POST")
            urlconnect.setRequestProperty("Content-Type", "application/json; UTF-8")
            urlconnect.setRequestProperty("Accept", "application/json")
            # Write to the body
            bw = BufferedWriter(
                OutputStreamWriter(
                    urlconnect.getOutputStream()
                )
            )
            bw.write(json_string)
            bw.flush()
            bw.close()
            # Read the result from the POST
            br = BufferedReader(
                InputStreamReader(
                    urlconnect.getInputStream(), "UTF-8"
                )
            )
            s = br.readLine()
            br.close()
        except MalformedURLException() as ex:
            cumulus_logger.error(str(ex))
            MessageBox.showError(str(ex), "Exception")
            raise Exception(ex)
        except IOException as ex:
            cumulus_logger.error(str(ex))
            MessageBox.showError(str(ex), "Exception")
            raise Exception(ex)

        end_timer = System.currentTimeMillis()
        cumulus_logger.debug(
            "HTTP GET (milliseconds): {}".format(
                (end_timer - start_timer)
                )
        )

        return s

    def json_build(self):
        '''Return JSON string or 'None' if failed

        The returning JSON string is from the UI and used when POSTing to the
        Cumulus API.
        '''
        conf = {
            'datetime_start': None,
            'datetime_end': None,
            'watershed_id': None,
            'product_id': None,
            }

        try:
            tf = TimeFormatter()
            tz = tf.zid
            st = tf.parse_zoned_date_time(self.txt_start_time.getText(), tz)
            et = tf.parse_zoned_date_time(self.txt_end_time.getText(), tz)

            conf['datetime_start'] = st.format(tf.iso_instant())
            conf['datetime_end'] = et.format(tf.iso_instant())
        except DateTimeParseException as ex:
            MessageBox.showWarning(ex, "Exception")


        selected_watershed = self.lst_watershed.getSelectedValue()
        selected_products = self.lst_product.getSelectedValues()

        if selected_watershed is not None:
            watershed_id = self.basin_meta[selected_watershed]['id']
            conf['watershed_id'] = watershed_id
        else:
            MessageBox.showWarning(
                "No Watershed Selected",
                "Exception"
                )
            return None
        
        product_ids = list()
        if len(selected_products) > 0:
            for p in selected_products:
                product_ids.append(self.product_meta[p]['id'])
                conf['product_id'] = product_ids
        else:
            MessageBox.showWarning(
                "No Products Selected",
                "Exception"
                )
            return None

        return json.dumps(conf)

    def choose_product(self, event):
        '''The event here is a javax.swing.event.ListSelectionEvent because
        it comes from a Jlist.  Use getValueIsAdjusting() to only get the
        mouse up value.
        '''
        output_str = '''{name}
After: {after}
Before: {before}
Parameter: {para}
Unit: {u}
'''
        index = self.lst_product.selectedIndex
        if not event.getValueIsAdjusting():
            pnames = self.lst_product.getSelectedValues()
            for pname in pnames:
                cumulus_logger.info("~" * 50)
                cumulus_logger.info("Product: {}".format(pname))
                cumulus_logger.info(
                    "After time: {}".format(self.product_meta[pname]['after']))
                cumulus_logger.info(
                    "Before time: {}".format(self.product_meta[pname]['before']))
                cumulus_logger.info(
                    "Parameter: {}".format(self.product_meta[pname]['parameter']))
                cumulus_logger.info(
                    "unit: {}".format(self.product_meta[pname]['unit']))

    def choose_watershed(self, event):
        '''The event here is a javax.swing.event.ListSelectionEvent because
        it comes from a Jlist.  Use getValueIsAdjusting() to only get the
        mouse up value.
        '''
        index = self.lst_watershed.selectedIndex
        if not event.getValueIsAdjusting():
            _dict = self.basin_meta[self.lst_watershed.getSelectedValue()]

    def select_file(self, event):
        '''Provide the user a JFileChooser to select the DSS file data is to download to.

        Event is a java.awt.event.ActionEvent
        '''
        fc = FileChooser(self.txt_select_file)
        fc.title = "Select Output DSS File"
        _dir = os.path.dirname(self.dss_path)
        fc.set_current_dir(File(_dir))
        fc.show()

    def submit(self, event):
        '''Collect user inputs and initiate download of DSS files to process.

        Event is a java.awt.event.ActionEvent
        '''

        start_timer = end_timer = System.currentTimeMillis()
        # Build the JSON from the UI inputs and POST if we have JSON
        json_string = self.json_build()
        cumulus_logger.debug("JSON String Builder: {}".format(json_string))

        if json_string is not None:
            cumulus_logger.info("*" * 50)
            cumulus_logger.info("Initiated Cumulus Product Request")
            cumulus_logger.info("*" * 50)
            post_result = self.http_post(json_string, url_downloads)
            json_post_result = json.loads(post_result)
            id = json_post_result['id']
            max_timeout = 180
            while max_timeout > 0:
                get_result = self.http_get("/".join([url_downloads, id]))
                if get_result is not None:
                    json_get_result = json.loads(get_result)
                    progress = json_get_result['progress']                          #100%
                    stat = json_get_result['status']                                #SUCCESS
                    fname = json_get_result['file']                                 # not null

                    cumulus_logger.info("Status: {:>10}; Progress: {:>4.1f}%; Timeout: {:>4}".format(stat, progress, max_timeout))

                    if stat == 'FAILED':
                        cumulus_logger.error("Failed to load grid products.")
                        MessageBox.showError(
                            "Failed to load grid products.",
                            "Failed Download"
                            )
                        break

                    if int(progress) == 100 and stat == 'SUCCESS' and fname is not None:
                        dest_dssfile = self.txt_select_file.getText()
                        cumulus_logger.debug("DSS Download Filname: {}".format(fname))
                        downloaded_dssfile = download_dss(fname)
                        if downloaded_dssfile is not None:
                            cumulus_logger.info("DSS file downloaded.")
                            merged_dssfiles = merge_dss(downloaded_dssfile, dest_dssfile)
                            if len(merged_dssfiles) > 0:
                                end_timer = System.currentTimeMillis()

                                msg = "DSS file downloaded and merged to: {}".format(
                                        '\n'.join([f for f in merged_dssfiles])
                                        )
                                cumulus_logger.info(msg)
                                MessageBox.showInformation(msg,
                                    "Successful Processing"
                                )
                            else:
                                msg = "DSS file merge unsuccessful"
                                cumulus_logger.warning(msg)
                                MessageBox.showWarning(msg,
                                    "Unsuccessful Merge"
                                )
                        else:
                            msg = "Downloading and processing the DSS file failed!"
                            cumulus_logger.error(msg)
                            MessageBox.showError(msg,
                                "Failed Processing"
                                )
                        break
                    else:
                        Thread.sleep(2000)
                    max_timeout -= 1

            cumulus_logger. info(
                "Submit time duration (milliseconds): {}".format(
                    (end_timer - start_timer)
                )
            )
        # Try to clean up any dss6 and dss7 files in the temp
        try:
            tempdir = tempfile.gettempdir()
            dss_temp_files = os.listdir(tempdir)
            for f in dss_temp_files:
                if (f.endswith(".dss") or f.endswith(".dss")):
                    os.remove(os.path.join(tempdir, f))
        except OSError as ex:
            cumulus_logger.warning(str(ex))
예제 #8
0
class BurpExtender(IBurpExtender, ITab, IScannerCheck, IContextMenuFactory, IParameter, IIntruderPayloadGeneratorFactory):
    def registerExtenderCallbacks(self, callbacks):
        self.callbacks = callbacks
        self.helpers = callbacks.getHelpers()
        callbacks.setExtensionName("Session Authentication Tool")
        self.out = callbacks.getStdout()

        # definition of suite tab
        self.tab = JPanel(GridBagLayout())
        self.tabledata = MappingTableModel(callbacks)
        self.table = JTable(self.tabledata)
        #self.table.getColumnModel().getColumn(0).setPreferredWidth(50);
        #self.table.getColumnModel().getColumn(1).setPreferredWidth(100);
        self.tablecont = JScrollPane(self.table)
        c = GridBagConstraints()
        c.fill = GridBagConstraints.HORIZONTAL
        c.anchor = GridBagConstraints.FIRST_LINE_START
        c.gridx = 0
        c.gridy = 0
        c.gridheight = 6
        c.weightx = 0.3
        c.weighty = 0.5
        self.tab.add(self.tablecont, c)

        c = GridBagConstraints()
        c.weightx = 0.1
        c.anchor = GridBagConstraints.FIRST_LINE_START
        c.gridx = 1

        c.gridy = 0
        label_id = JLabel("Identifier:")
        self.tab.add(label_id, c)
        self.input_id = JTextField(20)
        self.input_id.setToolTipText("Enter the identifier which is used by the application to identifiy a particular test user account, e.g. a numerical user id or a user name.")
        c.gridy = 1
        self.tab.add(self.input_id, c)

        c.gridy = 2
        label_content = JLabel("Content:")
        self.tab.add(label_content, c)
        self.input_content = JTextField(20, actionPerformed=self.btn_add_id)
        self.input_content.setToolTipText("Enter some content which is displayed in responses of the application and shows that the current session belongs to a particular user, e.g. the full name of the user.")
        c.gridy = 3
        self.tab.add(self.input_content, c)

        self.btn_add = JButton("Add/Edit Identity", actionPerformed=self.btn_add_id)
        c.gridy = 4
        self.tab.add(self.btn_add, c)

        self.btn_del = JButton("Delete Identity", actionPerformed=self.btn_del_id)
        c.gridy = 5
        self.tab.add(self.btn_del, c)

        callbacks.customizeUiComponent(self.tab)
        callbacks.customizeUiComponent(self.table)
        callbacks.customizeUiComponent(self.tablecont)
        callbacks.customizeUiComponent(self.btn_add)
        callbacks.customizeUiComponent(self.btn_del)
        callbacks.customizeUiComponent(label_id)
        callbacks.customizeUiComponent(self.input_id)
        callbacks.addSuiteTab(self)
        callbacks.registerScannerCheck(self)
        callbacks.registerIntruderPayloadGeneratorFactory(self)
        callbacks.registerContextMenuFactory(self)

    def btn_add_id(self, e):
        ident = self.input_id.text
        self.input_id.text = ""
        content = self.input_content.text
        self.input_content.text = ""
        self.tabledata.add_mapping(ident, content)
        self.input_id.requestFocusInWindow()

    def btn_del_id(self, e):
        rows = self.table.getSelectedRows().tolist()
        self.tabledata.del_rows(rows)

    ### ITab ###
    def getTabCaption(self):
        return("SessionAuth")

    def getUiComponent(self):
        return self.tab

    ### IContextMenuFactory ###
    def createMenuItems(self, invocation):
        menuitems = list()
        msgs = invocation.getSelectedMessages()
        if msgs != None:
            if len(msgs) == 1:              # "add as object id/as content to last id" context menu items
                bounds = invocation.getSelectionBounds()
                if bounds != None and bounds[0] != bounds[1]:
                    msg = None
                    if invocation.getInvocationContext() == IContextMenuInvocation.CONTEXT_MESSAGE_EDITOR_REQUEST or invocation.getInvocationContext() == IContextMenuInvocation.CONTEXT_MESSAGE_VIEWER_REQUEST:
                        msg = msgs[0].getRequest().tostring()
                    if invocation.getInvocationContext() == IContextMenuInvocation.CONTEXT_MESSAGE_EDITOR_RESPONSE or invocation.getInvocationContext() == IContextMenuInvocation.CONTEXT_MESSAGE_VIEWER_RESPONSE:
                        msg = msgs[0].getResponse().tostring()
                    if msg != None:
                        selection = msg[bounds[0]:bounds[1]]
                        shortSelection = selection[:20]
                        if len(selection) > len(shortSelection):
                            shortSelection += "..."
                        menuitems.append(JMenuItem("Add '" + shortSelection + "' as object id", actionPerformed=self.gen_menu_add_id(selection)))
                        if self.tabledata.lastadded != None:
                            menuitems.append(JMenuItem("Add '" + shortSelection + "' as content to last added id", actionPerformed=self.gen_menu_add_content(selection)))
            if len(msgs) > 0:             # "Send to Intruder" context menu items
                requestsWithIds = list()
                for msg in msgs:
                    if isinstance(msg.getRequest(), array) and self.tabledata.containsId(msg.getRequest().tostring()):
                        requestsWithIds.append(msg)
                if len(requestsWithIds) > 0:
                    menuitems.append(JMenuItem("Send to Intruder and preconfigure id injection points", actionPerformed=self.gen_menu_send_intruder(requestsWithIds)))

        return menuitems

    def gen_menu_add_id(self, ident):
        def menu_add_id(e):
            self.tabledata.add_mapping(ident, "")
        return menu_add_id

    def gen_menu_add_content(self, content):
        def menu_add_content(e):
            self.tabledata.set_lastadded_content(content)
        return menu_add_content

    def gen_menu_send_intruder(self, requestResponses):
        def menu_send_intruder(e):
            for requestResponse in requestResponses:
                httpService = requestResponse.getHttpService()
                request = requestResponse.getRequest()
                injectionPoints = list()
                for ident in self.tabledata.getIds():
                    newInjectionPoints = findAll(request.tostring(), ident)
                    if newInjectionPoints != None:
                        injectionPoints += newInjectionPoints
                if len(injectionPoints) > 0:
                    self.callbacks.sendToIntruder(httpService.getHost(), httpService.getPort(), httpService.getProtocol() == "https", request, injectionPoints)
        return menu_send_intruder

    ### IIntruderPayloadGeneratorFactory ###
    def getGeneratorName(self):
        return "SessionAuth Identifiers"

    def createNewInstance(self, attack):
        return IdentifiersPayloadGenerator(self.tabledata)

    ### IScannerCheck ###
    def doPassiveScan(self, baseRequestResponse):
        analyzedRequest = self.helpers.analyzeRequest(baseRequestResponse)
        params = analyzedRequest.getParameters()
        ids = self.tabledata.getIds()
        issues = list()

        for param in params:
            value = param.getValue()
            for ident in ids:
                if value == ident:
                    issues.append(SessionAuthPassiveScanIssue(
                        analyzedRequest.getUrl(),
                        baseRequestResponse,
                        param,
                        ident,
                        self.tabledata.getValue(ident),
                        SessionAuthPassiveScanIssue.foundEqual,
                        self.callbacks
                        ))
                elif value.find(ident) >= 0:
                    issues.append(SessionAuthPassiveScanIssue(
                        analyzedRequest.getUrl(),
                        baseRequestResponse,
                        param,
                        ident,
                        self.tabledata.getValue(ident),
                        SessionAuthPassiveScanIssue.foundInside,
                        self.callbacks
                        ))
        if len(issues) > 0:
            return issues
        else:
            return None

    def doActiveScan(self, baseRequestResponse, insertionPoint):
        ids = self.tabledata.getIds()
        if len(ids) <= 1:                 # active check only possible if multiple ids were given
            return None
        baseVal = insertionPoint.getBaseValue()
        url = baseRequestResponse.getUrl()

        idFound = list()
        for ident in ids:                 # find all identifiers in base value
            if baseVal.find(ident) >= 0:
                idFound.append(ident)
        if len(idFound) == 0:             # no given identifier found, nothing to do
            return None

        baseResponse = baseRequestResponse.getResponse().tostring()
        baseResponseBody = baseResponse[self.helpers.analyzeResponse(baseResponse).getBodyOffset():]
        issues = list()
        scannedCombos = list()
        for replaceId in idFound:         # scanner checks: replace found id by other given ids
            for scanId in ids:
                if replaceId == scanId or set([replaceId, scanId]) in scannedCombos:
                    continue
                scannedCombos.append(set([replaceId, scanId]))

                scanPayload = baseVal.replace(replaceId, scanId)
                scanRequest = insertionPoint.buildRequest(scanPayload)
                scanRequestResponse = self.callbacks.makeHttpRequest(baseRequestResponse.getHttpService(), scanRequest)
                scanResponse = scanRequestResponse.getResponse().tostring()
                scanResponseBody = scanResponse[self.helpers.analyzeResponse(scanResponse).getBodyOffset():]

                if baseResponseBody == scanResponseBody:   # response hasn't changed - no issue
                    continue

                # Analyze responses
                replaceValue = self.tabledata.getValue(replaceId)
                scanValue = self.tabledata.getValue(scanId)
                # naming convention:
                # first word: base || scan (response)
                # second word: Replace || Scan (value)
                if replaceValue != "":
                    baseReplaceValueCount = len(baseResponseBody.split(replaceValue)) - 1
                    scanReplaceValueCount = len(scanResponseBody.split(replaceValue)) - 1
                else:
                    baseReplaceValueCount = 0
                    scanReplaceValueCount = 0

                if scanValue != "":
                    baseScanValueCount = len(baseResponseBody.split(scanValue)) - 1
                    scanScanValueCount = len(scanResponseBody.split(scanValue)) - 1
                else:
                    baseScanValueCount = 0
                    scanScanValueCount = 0

                if scanScanValueCount == 0:
                    # Scan identifier content value doesn't appears, but responses differ
                    issueCase = SessionAuthActiveScanIssue.caseScanValueNotFound
                elif baseReplaceValueCount > 0 and baseScanValueCount == 0 and scanReplaceValueCount == 0 and scanScanValueCount == baseReplaceValueCount:
                    # Scan identifier replaces all occurrences of the original identifier in the response
                    issueCase = SessionAuthActiveScanIssue.caseScanValueAppearsExactly
                elif baseReplaceValueCount > 0 and baseScanValueCount == 0 and scanReplaceValueCount == 0 and scanScanValueCount > 0:
                    # Scan identfiers value appears, replaced ids value disappears
                    issueCase = SessionAuthActiveScanIssue.caseScanValueAppearsFuzzy
                elif baseReplaceValueCount > scanReplaceValueCount and baseScanValueCount < scanScanValueCount:
                    # Occurence count of replaced id value decreases, scan id value increases
                    issueCase = SessionAuthActiveScanIssue.caseDecreaseIncrease
                elif baseScanValueCount < scanScanValueCount:
                    # Occurence count of scan id value increases
                    issueCase = SessionAuthActiveScanIssue.caseScanValueIncrease
                else:
                    # Remainingg cases
                    issueCase = SessionAuthActiveScanIssue.caseOther

                issues.append(SessionAuthActiveScanIssue(
                    url,
                    baseRequestResponse,
                    insertionPoint,
                    scanPayload,
                    scanRequestResponse,
                    replaceId,
                    replaceValue,
                    scanId,
                    scanValue,
                    issueCase,
                    self.callbacks
                    ))

        if len(issues) > 0:
            return issues
        else:
            return None

    def consolidateDuplicateIssues(self, existingIssue, newIssue):
        if existingIssue.getIssueDetail() == newIssue.getIssueDetail():
            return 1
        else:
            return 0
예제 #9
0
class NewZoneDialog(JDialog, ActionListener, WindowListener):
    """Dialog for favourite zone editing
    """
    def __init__(self, app):
        from java.awt import Dialog
        from java.awt import CardLayout
        JDialog.__init__(self,
                         app.preferencesFrame,
                         app.strings.getString("Create_a_new_favourite_zone"),
                         Dialog.ModalityType.DOCUMENT_MODAL)
        self.app = app
        border = BorderFactory.createEmptyBorder(5, 7, 7, 7)
        self.getContentPane().setBorder(border)
        self.setLayout(BoxLayout(self.getContentPane(), BoxLayout.Y_AXIS))

        self.FAVAREALAYERNAME = "Favourite zone editing"

        info = JLabel(self.app.strings.getString("Create_a_new_favourite_zone"))
        info.setAlignmentX(Component.LEFT_ALIGNMENT)

        #Name
        nameLbl = JLabel(self.app.strings.getString("fav_zone_name"))
        self.nameTextField = JTextField(20)
        self.nameTextField.setMaximumSize(self.nameTextField.getPreferredSize())
        self.nameTextField.setToolTipText(self.app.strings.getString("fav_zone_name_tooltip"))
        namePanel = JPanel()
        namePanel.setLayout(BoxLayout(namePanel, BoxLayout.X_AXIS))
        namePanel.add(nameLbl)
        namePanel.add(Box.createHorizontalGlue())
        namePanel.add(self.nameTextField)

        #Country
        countryLbl = JLabel(self.app.strings.getString("fav_zone_country"))
        self.countryTextField = JTextField(20)
        self.countryTextField.setMaximumSize(self.countryTextField.getPreferredSize())
        self.countryTextField.setToolTipText(self.app.strings.getString("fav_zone_country_tooltip"))
        countryPanel = JPanel()
        countryPanel.setLayout(BoxLayout(countryPanel, BoxLayout.X_AXIS))
        countryPanel.add(countryLbl)
        countryPanel.add(Box.createHorizontalGlue())
        countryPanel.add(self.countryTextField)

        #Type
        modeLbl = JLabel(self.app.strings.getString("fav_zone_type"))
        RECTPANEL = "rectangle"
        POLYGONPANEL = "polygon"
        BOUNDARYPANEL = "boundary"
        self.modesStrings = [RECTPANEL, POLYGONPANEL, BOUNDARYPANEL]
        modesComboModel = DefaultComboBoxModel()
        for i in (self.app.strings.getString("rectangle"),
                  self.app.strings.getString("delimited_by_a_closed_way"),
                  self.app.strings.getString("delimited_by_an_administrative_boundary")):
            modesComboModel.addElement(i)
        self.modesComboBox = JComboBox(modesComboModel,
                                       actionListener=self,
                                       editable=False)

        #- Rectangle
        self.rectPanel = JPanel()
        self.rectPanel.setLayout(BoxLayout(self.rectPanel, BoxLayout.Y_AXIS))

        capturePane = JPanel()
        capturePane.setLayout(BoxLayout(capturePane, BoxLayout.X_AXIS))
        capturePane.setAlignmentX(Component.LEFT_ALIGNMENT)

        josmP = JPanel()
        self.captureRBtn = JRadioButton(self.app.strings.getString("capture_area"))
        self.captureRBtn.addActionListener(self)
        self.captureRBtn.setSelected(True)
        self.bboxFromJosmBtn = JButton(self.app.strings.getString("get_current_area"),
                                       actionPerformed=self.on_bboxFromJosmBtn_clicked)
        self.bboxFromJosmBtn.setToolTipText(self.app.strings.getString("get_capture_area_tooltip"))
        josmP.add(self.bboxFromJosmBtn)
        capturePane.add(self.captureRBtn)
        capturePane.add(Box.createHorizontalGlue())
        capturePane.add(self.bboxFromJosmBtn)

        manualPane = JPanel()
        manualPane.setLayout(BoxLayout(manualPane, BoxLayout.X_AXIS))
        manualPane.setAlignmentX(Component.LEFT_ALIGNMENT)
        self.manualRBtn = JRadioButton(self.app.strings.getString("use_this_bbox"))
        self.manualRBtn.addActionListener(self)
        self.bboxTextField = JTextField(20)
        self.bboxTextField.setMaximumSize(self.bboxTextField.getPreferredSize())
        self.bboxTextField.setToolTipText(self.app.strings.getString("fav_bbox_tooltip"))
        self.bboxTextFieldDefaultBorder = self.bboxTextField.getBorder()
        self.bboxTextField.getDocument().addDocumentListener(TextListener(self))
        manualPane.add(self.manualRBtn)
        manualPane.add(Box.createHorizontalGlue())
        manualPane.add(self.bboxTextField)

        group = ButtonGroup()
        group.add(self.captureRBtn)
        group.add(self.manualRBtn)

        previewPane = JPanel()
        previewPane.setLayout(BoxLayout(previewPane, BoxLayout.X_AXIS))
        previewPane.setAlignmentX(Component.LEFT_ALIGNMENT)
        bboxPreviewInfo = JTextField(self.app.strings.getString("coordinates"),
                                     editable=0,
                                     border=None)
        bboxPreviewInfo.setMaximumSize(bboxPreviewInfo.getPreferredSize())
        self.bboxPreviewTextField = JTextField(20,
                                               editable=0,
                                               border=None)
        self.bboxPreviewTextField.setMaximumSize(self.bboxPreviewTextField.getPreferredSize())
        previewPane.add(bboxPreviewInfo)
        previewPane.add(Box.createHorizontalGlue())
        previewPane.add(self.bboxPreviewTextField)

        self.rectPanel.add(capturePane)
        self.rectPanel.add(Box.createRigidArea(Dimension(0, 10)))
        self.rectPanel.add(manualPane)
        self.rectPanel.add(Box.createRigidArea(Dimension(0, 20)))
        self.rectPanel.add(previewPane)

        #- Polygon (closed way) drawn by hand
        self.polygonPanel = JPanel(BorderLayout())
        self.polygonPanel.setLayout(BoxLayout(self.polygonPanel, BoxLayout.Y_AXIS))

        polyInfo = JLabel("<html>%s</html>" % self.app.strings.getString("polygon_info"))
        polyInfo.setFont(polyInfo.getFont().deriveFont(Font.ITALIC))
        polyInfo.setAlignmentX(Component.LEFT_ALIGNMENT)

        editPolyPane = JPanel()
        editPolyPane.setAlignmentX(Component.LEFT_ALIGNMENT)
        editPolyBtn = JButton(self.app.strings.getString("create_fav_layer"),
                              actionPerformed=self.create_new_zone_editing_layer)
        editPolyBtn.setToolTipText(self.app.strings.getString("create_fav_layer_tooltip"))
        editPolyPane.add(editPolyBtn)

        self.polygonPanel.add(polyInfo)
        self.polygonPanel.add(Box.createRigidArea(Dimension(0, 15)))
        self.polygonPanel.add(editPolyPane)
        self.polygonPanel.add(Box.createRigidArea(Dimension(0, 15)))

        #- Administrative Boundary
        self.boundaryPanel = JPanel()
        self.boundaryPanel.setLayout(BoxLayout(self.boundaryPanel, BoxLayout.Y_AXIS))

        boundaryInfo = JLabel("<html>%s</html>" % app.strings.getString("boundary_info"))
        boundaryInfo.setFont(boundaryInfo.getFont().deriveFont(Font.ITALIC))
        boundaryInfo.setAlignmentX(Component.LEFT_ALIGNMENT)

        boundaryTagsPanel = JPanel(GridLayout(3, 3, 5, 5))
        boundaryTagsPanel.setAlignmentX(Component.LEFT_ALIGNMENT)
        boundaryTagsPanel.add(JLabel("name ="))
        self.nameTagTextField = JTextField(20)
        boundaryTagsPanel.add(self.nameTagTextField)
        boundaryTagsPanel.add(UrlLabel("http://wiki.openstreetmap.org/wiki/Key:admin_level#admin_level", "admin_level ="))
        self.adminLevelTagTextField = JTextField(20)
        self.adminLevelTagTextField.setToolTipText(self.app.strings.getString("adminLevel_tooltip"))
        boundaryTagsPanel.add(self.adminLevelTagTextField)
        boundaryTagsPanel.add(JLabel(self.app.strings.getString("other_tag")))
        self.optionalTagTextField = JTextField(20)
        self.optionalTagTextField.setToolTipText("key=value")
        boundaryTagsPanel.add(self.optionalTagTextField)

        downloadBoundariesPane = JPanel()
        downloadBoundariesPane.setAlignmentX(Component.LEFT_ALIGNMENT)
        downloadBoundariesBtn = JButton(self.app.strings.getString("download_boundary"),
                                        actionPerformed=self.on_downloadBoundariesBtn_clicked)
        downloadBoundariesBtn.setToolTipText(self.app.strings.getString("download_boundary_tooltip"))
        downloadBoundariesPane.add(downloadBoundariesBtn)

        self.boundaryPanel.add(boundaryInfo)
        self.boundaryPanel.add(Box.createRigidArea(Dimension(0, 15)))
        self.boundaryPanel.add(boundaryTagsPanel)
        self.boundaryPanel.add(Box.createRigidArea(Dimension(0, 10)))
        self.boundaryPanel.add(downloadBoundariesPane)

        self.editingPanels = {"rectangle": self.rectPanel,
                              "polygon": self.polygonPanel,
                              "boundary": self.boundaryPanel}

        #Main buttons
        self.okBtn = JButton(self.app.strings.getString("OK"),
                             ImageProvider.get("ok"),
                             actionPerformed=self.on_okBtn_clicked)
        self.cancelBtn = JButton(self.app.strings.getString("cancel"),
                                 ImageProvider.get("cancel"),
                                 actionPerformed=self.close_dialog)
        self.previewBtn = JButton(self.app.strings.getString("Preview_zone"),
                                  actionPerformed=self.on_previewBtn_clicked)
        self.previewBtn.setToolTipText(self.app.strings.getString("preview_zone_tooltip"))
        okBtnSize = self.okBtn.getPreferredSize()
        viewBtnSize = self.previewBtn.getPreferredSize()
        viewBtnSize.height = okBtnSize.height
        self.previewBtn.setPreferredSize(viewBtnSize)

        #layout
        self.add(info)
        self.add(Box.createRigidArea(Dimension(0, 15)))

        namePanel.setAlignmentX(Component.LEFT_ALIGNMENT)
        self.add(namePanel)
        self.add(Box.createRigidArea(Dimension(0, 15)))

        countryPanel.setAlignmentX(Component.LEFT_ALIGNMENT)
        self.add(countryPanel)
        self.add(Box.createRigidArea(Dimension(0, 15)))

        modeLbl.setAlignmentX(Component.LEFT_ALIGNMENT)
        self.add(modeLbl)
        self.add(Box.createRigidArea(Dimension(0, 5)))

        self.add(self.modesComboBox)
        self.modesComboBox.setAlignmentX(Component.LEFT_ALIGNMENT)
        self.add(Box.createRigidArea(Dimension(0, 15)))

        self.configPanel = JPanel(CardLayout())
        self.configPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5))
        self.configPanel.add(self.rectPanel, RECTPANEL)
        self.configPanel.add(self.polygonPanel, POLYGONPANEL)
        self.configPanel.add(self.boundaryPanel, BOUNDARYPANEL)
        self.configPanel.setAlignmentX(Component.LEFT_ALIGNMENT)
        self.add(self.configPanel)
        buttonsPanel = JPanel()
        buttonsPanel.add(self.okBtn)
        buttonsPanel.add(self.cancelBtn)
        buttonsPanel.add(self.previewBtn)
        buttonsPanel.setAlignmentX(Component.LEFT_ALIGNMENT)
        self.add(buttonsPanel)

        self.addWindowListener(self)
        self.pack()

    def update_gui_from_preferences(self):
        self.nameTextField.setText(self.app.newZone.name)
        #Reset rectangle mode
        bboxStr = ",".join(["%0.4f" % x for x in self.app.newZone.bbox])
        self.bboxTextField.setText(bboxStr)
        self.bboxPreviewTextField.setText(bboxStr)
        self.bboxFromJosmBtn.setEnabled(True)
        self.bboxTextField.setEnabled(False)

        #Reset polygon mode
        self.polygonAsString = ""

        #Reset boundary mode
        self.boundaryAsString = ""

        self.modesComboBox.setSelectedIndex(0)

    def actionPerformed(self, e):
        #Show the panel for configuring the favourite area of the
        #selected type
        if e.getSource() == self.modesComboBox:
            cl = self.configPanel.getLayout()
            selectedMode = self.modesStrings[self.modesComboBox.selectedIndex]
            cl.show(self.configPanel, selectedMode)
        #Activate bbox input for rectangular favourite zone mode
        elif e.getSource() == self.captureRBtn:
            self.bboxFromJosmBtn.setEnabled(True)
            self.bboxTextField.setEnabled(False)
        else:
            self.bboxFromJosmBtn.setEnabled(False)
            self.bboxTextField.setEnabled(True)

    def on_bboxFromJosmBtn_clicked(self, widget):
        """Read bbox currently shown in JOSM
        """
        bbox = self.app.get_frame_bounds()
        self.bboxPreviewTextField.setText(",".join(["%0.4f" % x for x in bbox]))

### Manage layer for creating a new favourite zone from polygon or boundary
    def create_new_zone_editing_layer(self, e=None):
        """Open a new dataset where the user can draw a closed way to
           delimit the favourite area
        """
        layer = self.get_new_zone_editing_layer()
        if layer is not None:
            self.app.mv.setActiveLayer(layer)
        else:
            Main.main.addLayer(OsmDataLayer(DataSet(), self.FAVAREALAYERNAME, None))
        Main.main.parent.toFront()

    def get_new_zone_editing_layer(self):
        """Check if the layer for editing the favourite area yet exists
        """
        for layer in self.app.mv.getAllLayers():
            if layer.getName() == self.FAVAREALAYERNAME:
                return layer
        return None

    def remove_new_zone_editing_layer(self):
        layer = self.get_new_zone_editing_layer()
        if layer is not None:
            self.app.mv.removeLayer(layer)

    def on_zone_edited(self):
        """Read ways that delimit the favourite area and convert them to
           jts geometry
        """
        if self.modesComboBox.getSelectedIndex() == 0:
            mode = "rectangle"
        elif self.modesComboBox.getSelectedIndex() == 1:
            mode = "polygon"
        elif self.modesComboBox.getSelectedIndex() == 2:
            mode = "boundary"

        if mode in ("polygon", "boundary"):
            layer = self.get_new_zone_editing_layer()
            if layer is not None:
                self.app.mv.setActiveLayer(layer)
            else:
                if mode == "polygon":
                    msg = self.app.strings.getString("polygon_fav_layer_missing_msg")
                else:
                    msg = self.app.strings.getString("boundary_fav_layer_missing_msg")
                JOptionPane.showMessageDialog(self,
                                              msg,
                                              self.app.strings.getString("Warning"),
                                              JOptionPane.WARNING_MESSAGE)
                return

            dataset = self.app.mv.editLayer.data
            areaWKT = self.read_area_from_osm_ways(mode, dataset)
            if areaWKT is None:
                print "I could not read the new favourite area."
            else:
                if mode == "polygon":
                    self.polygonAsString = areaWKT
                else:
                    self.boundaryAsString = areaWKT
        return mode

    def read_area_from_osm_ways(self, mode, dataset):
        """Read way in favourite area editing layer and convert them to
           WKT
        """
        converter = JTSConverter(False)
        lines = [converter.convert(way) for way in dataset.ways]
        polygonizer = Polygonizer()
        polygonizer.add(lines)
        polygons = polygonizer.getPolygons()
        multipolygon = GeometryFactory().createMultiPolygon(list(polygons))
        multipolygonWKT = WKTWriter().write(multipolygon)
        if multipolygonWKT == "MULTIPOLYGON EMPTY":
            if mode == "polygon":
                msg = self.app.strings.getString("empty_ways_polygon_msg")
            else:
                msg = self.app.strings.getString("empty_ways_boundaries_msg")
            JOptionPane.showMessageDialog(self,
                msg,
                self.app.strings.getString("Warning"),
                JOptionPane.WARNING_MESSAGE)
            return
        return multipolygonWKT

    def on_downloadBoundariesBtn_clicked(self, e):
        """Download puter ways of administrative boundaries from
           Overpass API
        """
        adminLevel = self.adminLevelTagTextField.getText()
        name = self.nameTagTextField.getText()
        optional = self.optionalTagTextField.getText()
        if (adminLevel, name, optional) == ("", "", ""):
            JOptionPane.showMessageDialog(self,
                                          self.app.strings.getString("enter_a_tag_msg"),
                                          self.app.strings.getString("Warning"),
                                          JOptionPane.WARNING_MESSAGE)
            return
        optTag = ""
        if optional.find("=") != -1:
            if len(optional.split("=")) == 2:
                key, value = optional.split("=")
                optTag = '["%s"="%s"]' % (URLEncoder.encode(key, "UTF-8"),
                                          URLEncoder.encode(value.replace(" ", "%20"), "UTF-8"))
        self.create_new_zone_editing_layer()
        overpassurl = 'http://127.0.0.1:8111/import?url='
        overpassurl += 'http://overpass-api.de/api/interpreter?data='
        overpassquery = 'relation["admin_level"="%s"]' % adminLevel
        overpassquery += '["name"="%s"]' % URLEncoder.encode(name, "UTF-8")
        overpassquery += '%s;(way(r:"outer");node(w););out meta;' % optTag
        overpassurl += overpassquery.replace(" ", "%20")
        print overpassurl
        self.app.send_to_josm(overpassurl)

### Buttons ############################################################
    def create_new_zone(self, mode):
        """Read data entered on gui and create a new zone
        """
        name = self.nameTextField.getText()
        country = self.countryTextField.getText().upper()

        #error: name
        if name.replace(" ", "") == "":
            JOptionPane.showMessageDialog(self,
                                          self.app.strings.getString("missing_name_warning"),
                                          self.app.strings.getString("missing_name_warning_title"),
                                          JOptionPane.WARNING_MESSAGE)
            return False
        if name in [z.name for z in self.app.tempZones]:
            JOptionPane.showMessageDialog(self,
                                          self.app.strings.getString("duplicate_name_warning"),
                                          self.app.strings.getString("duplicate_name_warning_title"),
                                          JOptionPane.WARNING_MESSAGE)
            return False

        #zone type
        zType = mode
        #error: geometry type not defined
        if zType == "polygon" and self.polygonAsString == ""\
            or zType == "boundary" and self.boundaryAsString == "":
            JOptionPane.showMessageDialog(self,
                                          self.app.strings.getString("zone_not_correctly_build_warning"),
                                          self.app.strings.getString("zone_not_correctly_build_warning_title"),
                                          JOptionPane.WARNING_MESSAGE)
            return False

        #geometry string
        if zType == "rectangle":
            geomString = self.bboxPreviewTextField.getText()
        elif zType == "polygon":
            geomString = self.polygonAsString
        else:
            geomString = self.boundaryAsString

        self.app.newZone = Zone(self.app, name, zType, geomString, country)
        #self.app.newZone.print_info()
        return True

    def on_okBtn_clicked(self, event):
        """Add new zone to temp zones
        """
        mode = self.on_zone_edited()
        if self.create_new_zone(mode):
            self.app.tempZones.append(self.app.newZone)
            self.app.preferencesFrame.zonesTable.getModel().addRow([self.app.newZone.country,
                                                                    self.app.newZone.icon,
                                                                    self.app.newZone.name])
            maxIndex = len(self.app.tempZones) - 1
            self.app.preferencesFrame.zonesTable.setRowSelectionInterval(maxIndex,
                                                                         maxIndex)
            self.close_dialog()
            self.app.preferencesFrame.check_removeBtn_status()
            self.app.preferencesFrame.zonesTable.scrollRectToVisible(
                self.app.preferencesFrame.zonesTable.getCellRect(
                    self.app.preferencesFrame.zonesTable.getRowCount() - 1, 0, True))

    def on_previewBtn_clicked(self, e):
        """Show the favourite area on a map
        """
        mode = self.on_zone_edited()
        if not self.create_new_zone(mode):
            return
        zone = self.app.newZone

        if zone.zType == "rectangle":
            wktString = zone.bbox_to_wkt_string()
        else:
            wktString = zone.wktGeom
        script = '/*http://stackoverflow.com/questions/11954401/wkt-and-openlayers*/'
        script += '\nfunction init() {'
        script += '\n    var map = new OpenLayers.Map({'
        script += '\n        div: "map",'
        script += '\n        projection: new OpenLayers.Projection("EPSG:900913"),'
        script += '\n        displayProjection: new OpenLayers.Projection("EPSG:4326"),'
        script += '\n        layers: ['
        script += '\n            new OpenLayers.Layer.OSM()'
        script += '\n            ]'
        script += '\n    });'
        script += '\n    var wkt = new OpenLayers.Format.WKT();'
        script += '\n    var polygonFeature = wkt.read("%s");' % wktString
        script += '\n    var vectors = new OpenLayers.Layer.Vector("Favourite area");'
        script += '\n    map.addLayer(vectors);'
        script += '\n    polygonFeature.geometry.transform(map.displayProjection, map.getProjectionObject());'
        script += '\n    vectors.addFeatures([polygonFeature]);'
        script += '\n    map.zoomToExtent(vectors.getDataExtent());'
        script += '\n};'
        scriptFile = open(File.separator.join([self.app.SCRIPTDIR,
                                              "html",
                                              "script.js"]), "w")
        scriptFile.write(script)
        scriptFile.close()
        OpenBrowser.displayUrl(File.separator.join([self.app.SCRIPTDIR,
                                                   "html",
                                                   "favourite_area.html"]))

    def windowClosing(self, windowEvent):
        self.close_dialog()

    def close_dialog(self, e=None):
        #delete favourite zone editing layer if present
        self.remove_new_zone_editing_layer()
        self.dispose()
        self.app.preferencesFrame.toFront()
예제 #10
0
class PluginUI():
    def __init__(self, extender):
        self.extender = extender
        self.initComponents()

    def showMessage(self, msg):
        JOptionPane.showMessageDialog(self.mainPanel, msg)

    def getProcessorTechName(self):
        return self.comboProcessorTech.getSelectedItem()

    def getGeneratorTechsName(self):
        techList = []
        if self.chkGeneral.isSelected(): techList.append('General')
        if self.chkMAXDB.isSelected(): techList.append('SAP_MaxDB')
        if self.chkMSSQL.isSelected(): techList.append('MSSQL')
        if self.chkMSAccess.isSelected(): techList.append('MSAccess')
        if self.chkPostgres.isSelected(): techList.append('PostgreSQL')
        if self.chkOracle.isSelected(): techList.append('Oracle')
        if self.chkSqlite.isSelected(): techList.append('SQLite')
        if self.chkMysql.isSelected(): techList.append('MySQL')
        return techList

    def pastePayloadButtonAction(self, event):
        clpbrd = Toolkit.getDefaultToolkit().getSystemClipboard()
        content = clpbrd.getContents(None)
        if content and content.isDataFlavorSupported(DataFlavor.stringFlavor):
            items = content.getTransferData(DataFlavor.stringFlavor)
            items = items.splitlines()
            for item in items:
                self.extender.PayloadList.append(item)
            self.listPayloads.setListData(self.extender.PayloadList)
        self.writePayloadsListFile()

    def loadPayloadButtonAction(self, event):
        fileChooser = JFileChooser()
        fileChooser.dialogTitle = 'Choose Payload List'
        fileChooser.fileSelectionMode = JFileChooser.FILES_ONLY
        if (fileChooser.showOpenDialog(
                self.mainPanel) == JFileChooser.APPROVE_OPTION):
            file = fileChooser.getSelectedFile()
            with open(file.getAbsolutePath(), 'r') as reader:
                for line in reader.readlines():
                    self.extender.PayloadList.append(line.strip('\n'))
            self.listPayloads.setListData(self.extender.PayloadList)
            self.showMessage('{} payloads loaded'.format(
                len(self.extender.PayloadList)))
            self.writePayloadsListFile()

    def removePayloadButtonAction(self, event):
        for item in self.listPayloads.getSelectedValuesList():
            self.extender.PayloadList.remove(item)
        self.listPayloads.setListData(self.extender.PayloadList)
        self.writePayloadsListFile()

    def clearPayloadButtonAction(self, event):
        self.extender.PayloadList[:] = []
        self.listPayloads.setListData(self.extender.PayloadList)
        self.writePayloadsListFile()

    def addPayloadButtonAction(self, event):
        if str(self.textNewPayload.text).strip():
            self.extender.PayloadList.append(self.textNewPayload.text)
            self.textNewPayload.text = ''
            self.listPayloads.setListData(self.extender.PayloadList)
        self.writePayloadsListFile()

    def toClipboardButtonAction(self, event):
        self.extender.generatePayloads()
        result = '\n'.join(self.extender.tamperedPayloads)
        result = StringSelection(result)
        clpbrd = Toolkit.getDefaultToolkit().getSystemClipboard()
        clpbrd.setContents(result, None)
        self.showMessage('{} url encoded payload copied to clipboard'.format(
            len(self.extender.tamperedPayloads)))

    def toFileButtonAction(self, event):
        fileChooser = JFileChooser()
        fileChooser.dialogTitle = 'Save Payloads'
        fileChooser.fileSelectionMode = JFileChooser.FILES_ONLY
        if (fileChooser.showSaveDialog(
                self.mainPanel) == JFileChooser.APPROVE_OPTION):
            file = fileChooser.getSelectedFile()
            self.extender.generatePayloads()
            result = '\n'
            result = result.join(self.extender.tamperedPayloads)
            with open(file.getAbsolutePath(), 'w') as writer:
                writer.writelines(result)
            self.showMessage('{} url encoded payload written to file'.format(
                len(self.extender.tamperedPayloads)))

    def tamperPayloadButtonAction(self, event):
        tamperedPayloads = []
        tamperFunction = self.comboProcessorTech.getSelectedItem()
        payloads = self.textPlainPayload.text
        payloads = payloads.splitlines()
        for payload in payloads:
            tamperedPayloads.append(
                self.extender.tamperSinglePayload(tamperFunction, payload))

        result = '\n'.join(tamperedPayloads)
        self.textTamperedPayload.text = result

    def comboProcessorTechAction(self, event):
        varName = 'SQLiQueryTampering_comboProcessorTech'
        state = str(self.comboProcessorTech.getSelectedIndex())
        self.extender.callbacks.saveExtensionSetting(varName, state)

    def OnCheck(self, event):
        chk = event.getSource()
        varName = 'SQLiQueryTampering_{}'.format(chk.text)
        state = str(1 if chk.isSelected() else 0)
        self.extender.callbacks.saveExtensionSetting(varName, state)

    def writePayloadsListFile(self):
        payloads = '\n'.join(self.extender.PayloadList)
        payloads = payloads.encode('utf-8')
        with open('payloads.lst', 'w') as writer:
            writer.write(payloads)

    def readPayloadsListFile(self):
        result = []
        with open('payloads.lst', 'r') as reader:
            for line in reader.readlines():
                result.append(line.strip('\n'))
        return result

    def initComponents(self):
        TabbedPane1 = JTabbedPane()
        GeneratorScrollPane = JScrollPane()
        GeneratorPanel = JPanel()
        jlbl1 = JLabel()
        jlbl2 = JLabel()
        spanePayloadList = JScrollPane()
        self.listPayloads = JList()
        pastePayloadButton = JButton(
            actionPerformed=self.pastePayloadButtonAction)
        loadPayloadButton = JButton(
            actionPerformed=self.loadPayloadButtonAction)
        removePayloadButton = JButton(
            actionPerformed=self.removePayloadButtonAction)
        clearPayloadButton = JButton(
            actionPerformed=self.clearPayloadButtonAction)
        self.textNewPayload = JTextField()
        addPayloadButton = JButton(actionPerformed=self.addPayloadButtonAction)
        jSeparator1 = JSeparator()
        jlbl3 = JLabel()
        jlbl4 = JLabel()
        self.chkGeneral = JCheckBox(actionPerformed=self.OnCheck)
        self.chkMAXDB = JCheckBox(actionPerformed=self.OnCheck)
        self.chkMSSQL = JCheckBox(actionPerformed=self.OnCheck)
        self.chkMSAccess = JCheckBox(actionPerformed=self.OnCheck)
        self.chkPostgres = JCheckBox(actionPerformed=self.OnCheck)
        self.chkOracle = JCheckBox(actionPerformed=self.OnCheck)
        self.chkSqlite = JCheckBox(actionPerformed=self.OnCheck)
        self.chkMysql = JCheckBox(actionPerformed=self.OnCheck)
        jlbl5 = JLabel()
        toClipboardButton = JButton(
            actionPerformed=self.toClipboardButtonAction)
        toFileButton = JButton(actionPerformed=self.toFileButtonAction)
        ProcessorScrollPane = JScrollPane()
        ProcessorPanel = JPanel()
        jLabel1 = JLabel()
        self.comboProcessorTech = JComboBox(
            itemStateChanged=self.comboProcessorTechAction)
        jSeparator2 = JSeparator()
        jLabel2 = JLabel()
        jLabel3 = JLabel()
        jScrollPane1 = JScrollPane()
        self.textPlainPayload = JTextArea()
        jLabel4 = JLabel()
        jScrollPane2 = JScrollPane()
        self.textTamperedPayload = JTextArea()
        tamperPayloadButton = JButton(
            actionPerformed=self.tamperPayloadButtonAction)

        jlbl1.setForeground(Color(255, 102, 51))
        jlbl1.setFont(Font(jlbl1.getFont().toString(), 1, 14))
        jlbl1.setText("User-Defiend Payloads")

        jlbl2.setText(
            "This payload type lets you configure a simple list of strings that are used as payloads."
        )

        spanePayloadList.setViewportView(self.listPayloads)
        self.extender.PayloadList = self.readPayloadsListFile()
        self.listPayloads.setListData(self.extender.PayloadList)

        pastePayloadButton.setText("Paste")

        loadPayloadButton.setText("Load")

        removePayloadButton.setText("Remove")

        clearPayloadButton.setText("Clear")

        self.textNewPayload.setToolTipText("")

        addPayloadButton.setText("Add")

        jlbl3.setForeground(Color(255, 102, 51))
        jlbl3.setFont(Font(jlbl3.getFont().toString(), 1, 14))
        jlbl3.setText("Tamper Techniques")

        jlbl4.setText(
            "You can select the techniques that you want to perform processing tasks on each user-defined payload"
        )

        self.chkGeneral.setText("General")
        varName = 'SQLiQueryTampering_{}'.format(self.chkGeneral.text)
        state = self.extender.callbacks.loadExtensionSetting(varName)
        if state: self.chkGeneral.setSelected(int(state))

        self.chkMAXDB.setText("SAP MAX DB")
        varName = 'SQLiQueryTampering_{}'.format(self.chkMAXDB.text)
        state = self.extender.callbacks.loadExtensionSetting(varName)
        if state: self.chkMAXDB.setSelected(int(state))

        self.chkMSSQL.setText("MS SQL Server")
        varName = 'SQLiQueryTampering_{}'.format(self.chkMSSQL.text)
        state = self.extender.callbacks.loadExtensionSetting(varName)
        if state: self.chkMSSQL.setSelected(int(state))

        self.chkMSAccess.setText("MS Access")
        varName = 'SQLiQueryTampering_{}'.format(self.chkMSAccess.text)
        state = self.extender.callbacks.loadExtensionSetting(varName)
        if state: self.chkMSAccess.setSelected(int(state))

        self.chkPostgres.setText("Postgres SQL")
        varName = 'SQLiQueryTampering_{}'.format(self.chkPostgres.text)
        state = self.extender.callbacks.loadExtensionSetting(varName)
        if state: self.chkPostgres.setSelected(int(state))

        self.chkOracle.setText("Oracle")
        varName = 'SQLiQueryTampering_{}'.format(self.chkOracle.text)
        state = self.extender.callbacks.loadExtensionSetting(varName)
        if state: self.chkOracle.setSelected(int(state))

        self.chkSqlite.setText("Sqlite")
        varName = 'SQLiQueryTampering_{}'.format(self.chkSqlite.text)
        state = self.extender.callbacks.loadExtensionSetting(varName)
        if state: self.chkSqlite.setSelected(int(state))

        self.chkMysql.setText("MySql")
        varName = 'SQLiQueryTampering_{}'.format(self.chkMysql.text)
        state = self.extender.callbacks.loadExtensionSetting(varName)
        if state: self.chkMysql.setSelected(int(state))

        jlbl5.setText("[?] Save the Generated/Tampered Payloads to :")

        toClipboardButton.setText("Clipboard")

        toFileButton.setText("File")

        GeneratorPanelLayout = GroupLayout(GeneratorPanel)
        GeneratorPanel.setLayout(GeneratorPanelLayout)
        GeneratorPanelLayout.setHorizontalGroup(
            GeneratorPanelLayout.createParallelGroup(
                GroupLayout.Alignment.LEADING).
            addGroup(GeneratorPanelLayout.createSequentialGroup(
            ).addContainerGap().addGroup(
                GeneratorPanelLayout.createParallelGroup(
                    GroupLayout.Alignment.TRAILING).addComponent(
                        jlbl2, GroupLayout.DEFAULT_SIZE,
                        GroupLayout.DEFAULT_SIZE,
                        Short.MAX_VALUE).addComponent(
                            jlbl4, GroupLayout.Alignment.LEADING,
                            GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE,
                            Short.MAX_VALUE).addComponent(
                                jSeparator1, GroupLayout.Alignment.LEADING).
                addGroup(GeneratorPanelLayout.createSequentialGroup().addGap(
                    6, 6, 6).addGroup(
                        GeneratorPanelLayout.createParallelGroup(
                            GroupLayout.Alignment.LEADING).addGroup(
                                GeneratorPanelLayout.createSequentialGroup(
                                ).addGroup(
                                    GeneratorPanelLayout.createParallelGroup(
                                        GroupLayout.Alignment.LEADING,
                                        False).addComponent(
                                            removePayloadButton,
                                            GroupLayout.DEFAULT_SIZE,
                                            GroupLayout.DEFAULT_SIZE,
                                            Short.MAX_VALUE).addComponent(
                                                clearPayloadButton,
                                                GroupLayout.DEFAULT_SIZE,
                                                GroupLayout.DEFAULT_SIZE,
                                                Short.MAX_VALUE).addComponent(
                                                    loadPayloadButton,
                                                    GroupLayout.DEFAULT_SIZE,
                                                    GroupLayout.DEFAULT_SIZE,
                                                    Short.MAX_VALUE).
                                    addComponent(pastePayloadButton,
                                                 GroupLayout.DEFAULT_SIZE,
                                                 GroupLayout.DEFAULT_SIZE,
                                                 Short.MAX_VALUE).addComponent(
                                                     addPayloadButton,
                                                     GroupLayout.DEFAULT_SIZE,
                                                     GroupLayout.DEFAULT_SIZE,
                                                     Short.MAX_VALUE)).
                                addGap(21, 21, 21).addGroup(
                                    GeneratorPanelLayout.createParallelGroup(
                                        GroupLayout.Alignment.LEADING).
                                    addComponent(
                                        self.textNewPayload).addComponent(
                                            spanePayloadList))).addComponent(
                                                jlbl1).addComponent(jlbl3).
                        addGroup(GeneratorPanelLayout.createSequentialGroup(
                        ).addGroup(
                            GeneratorPanelLayout.createParallelGroup(
                                GroupLayout.Alignment.LEADING).addComponent(
                                    self.chkGeneral).addComponent(
                                        self.chkMSSQL)
                        ).addGap(18, 18, 18).addGroup(
                            GeneratorPanelLayout.createParallelGroup(
                                GroupLayout.Alignment.LEADING).addComponent(
                                    self.chkPostgres).addComponent(
                                        self.chkMAXDB)
                        ).addGap(18, 18, 18).addGroup(
                            GeneratorPanelLayout.createParallelGroup(
                                GroupLayout.Alignment.LEADING).addComponent(
                                    self.chkMSAccess).addComponent(
                                        self.chkOracle)
                        ).addGap(18, 18, 18).addGroup(
                            GeneratorPanelLayout.createParallelGroup(
                                GroupLayout.Alignment.LEADING).addComponent(
                                    self.chkSqlite).addComponent(self.chkMysql)
                        )).addGroup(GeneratorPanelLayout.createSequentialGroup(
                        ).addComponent(jlbl5).addPreferredGap(
                            LayoutStyle.ComponentPlacement.
                            UNRELATED).addComponent(toClipboardButton).addGap(
                                18, 18,
                                18).addComponent(toFileButton,
                                                 GroupLayout.PREFERRED_SIZE,
                                                 97, GroupLayout.PREFERRED_SIZE
                                                 ))))).addContainerGap()))
        GeneratorPanelLayout.setVerticalGroup(
            GeneratorPanelLayout.createParallelGroup(
                GroupLayout.Alignment.LEADING).
            addGroup(GeneratorPanelLayout.createSequentialGroup(
            ).addContainerGap().addComponent(jlbl1).addPreferredGap(
                LayoutStyle.ComponentPlacement.RELATED).addComponent(
                    jlbl2, GroupLayout.PREFERRED_SIZE, 21,
                    GroupLayout.PREFERRED_SIZE).addGap(18, 18, 18).addGroup(
                        GeneratorPanelLayout.createParallelGroup(
                            GroupLayout.Alignment.LEADING).addComponent(
                                spanePayloadList, GroupLayout.PREFERRED_SIZE,
                                GroupLayout.DEFAULT_SIZE,
                                GroupLayout.PREFERRED_SIZE).
                        addGroup(GeneratorPanelLayout.createSequentialGroup(
                        ).addComponent(pastePayloadButton).addPreferredGap(
                            LayoutStyle.ComponentPlacement.RELATED
                        ).addComponent(loadPayloadButton).addPreferredGap(
                            LayoutStyle.ComponentPlacement.RELATED
                        ).addComponent(removePayloadButton).addPreferredGap(
                            LayoutStyle.ComponentPlacement.RELATED).
                                 addComponent(clearPayloadButton))).
                     addPreferredGap(
                         LayoutStyle.ComponentPlacement.RELATED).addGroup(
                             GeneratorPanelLayout.createParallelGroup(
                                 GroupLayout.Alignment.BASELINE).addComponent(
                                     self.textNewPayload,
                                     GroupLayout.PREFERRED_SIZE,
                                     GroupLayout.DEFAULT_SIZE,
                                     GroupLayout.PREFERRED_SIZE).
                             addComponent(addPayloadButton)).addPreferredGap(
                                 LayoutStyle.ComponentPlacement.UNRELATED).
                     addComponent(jSeparator1, GroupLayout.PREFERRED_SIZE, 10,
                                  GroupLayout.PREFERRED_SIZE).addPreferredGap(
                                      LayoutStyle.ComponentPlacement.RELATED).
                     addComponent(jlbl3).addPreferredGap(
                         LayoutStyle.ComponentPlacement.UNRELATED
                     ).addComponent(jlbl4).addPreferredGap(
                         LayoutStyle.ComponentPlacement.UNRELATED).addGroup(
                             GeneratorPanelLayout.createParallelGroup(
                                 GroupLayout.Alignment.BASELINE).addComponent(
                                     self.chkGeneral).addComponent(
                                         self.chkMAXDB).addComponent(
                                             self.chkOracle).addComponent(
                                                 self.chkSqlite)).
                     addPreferredGap(
                         LayoutStyle.ComponentPlacement.UNRELATED).addGroup(
                             GeneratorPanelLayout.createParallelGroup(
                                 GroupLayout.Alignment.BASELINE).addComponent(
                                     self.chkMSSQL).addComponent(
                                         self.chkPostgres).addComponent(
                                             self.chkMSAccess).addComponent(
                                                 self.chkMysql)
                         ).addGap(18, 18, 18).addGroup(
                             GeneratorPanelLayout.createParallelGroup(
                                 GroupLayout.Alignment.BASELINE).addComponent(
                                     jlbl5).addComponent(toClipboardButton).
                             addComponent(toFileButton)).addGap(20, 20, 20)))

        GeneratorScrollPane.setViewportView(GeneratorPanel)

        TabbedPane1.addTab("Generator", GeneratorScrollPane)

        varName = 'SQLiQueryTampering_comboProcessorTech'
        state = self.extender.callbacks.loadExtensionSetting(varName)

        for item in self.extender.getTamperFuncsName():
            self.comboProcessorTech.addItem(item)

        if state: self.comboProcessorTech.setSelectedIndex(int(state))

        jLabel1.setText("Processor Technique :")

        jLabel2.setText(
            "Modify Plain Payloads based on the selected Processor Technique. Write one payload per line."
        )

        jLabel3.setText("Plain Payloads:")

        self.textPlainPayload.setColumns(20)
        self.textPlainPayload.setRows(5)
        jScrollPane1.setViewportView(self.textPlainPayload)

        jLabel4.setText("Tampered Payloads:")

        self.textTamperedPayload.setColumns(20)
        self.textTamperedPayload.setRows(5)
        jScrollPane2.setViewportView(self.textTamperedPayload)

        tamperPayloadButton.setText("Tamper Payloads")

        ProcessorPanelLayout = GroupLayout(ProcessorPanel)
        ProcessorPanel.setLayout(ProcessorPanelLayout)
        ProcessorPanelLayout.setHorizontalGroup(
            ProcessorPanelLayout.
            createParallelGroup(GroupLayout.Alignment.LEADING).addGroup(
                GroupLayout.Alignment.TRAILING,
                ProcessorPanelLayout.createSequentialGroup().addContainerGap(
                    GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE).addComponent(
                        tamperPayloadButton).addContainerGap(
                            GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            ).addGroup(ProcessorPanelLayout.createSequentialGroup(
            ).addContainerGap().addGroup(
                ProcessorPanelLayout.createParallelGroup(
                    GroupLayout.Alignment.LEADING).addComponent(jSeparator2).
                addComponent(jScrollPane1).addComponent(jScrollPane2).addGroup(
                    ProcessorPanelLayout.createSequentialGroup().addGroup(
                        ProcessorPanelLayout.createParallelGroup(
                            GroupLayout.Alignment.LEADING).addComponent(
                                jLabel3).addComponent(jLabel4).addGroup(
                                    ProcessorPanelLayout.createSequentialGroup(
                                    ).addComponent(jLabel1).addPreferredGap(
                                        LayoutStyle.ComponentPlacement.
                                        UNRELATED).addComponent(
                                            self.comboProcessorTech,
                                            GroupLayout.PREFERRED_SIZE, 286,
                                            GroupLayout.PREFERRED_SIZE)).
                        addComponent(jLabel2)).addGap(
                            0, 78, Short.MAX_VALUE))).addContainerGap()))
        ProcessorPanelLayout.setVerticalGroup(
            ProcessorPanelLayout.createParallelGroup(
                GroupLayout.Alignment.LEADING).addGroup(
                    ProcessorPanelLayout.createSequentialGroup().addGap(
                        33, 33, 33).addGroup(
                            ProcessorPanelLayout.createParallelGroup(
                                GroupLayout.Alignment.BASELINE).
                            addComponent(jLabel1).addComponent(
                                self.comboProcessorTech,
                                GroupLayout.PREFERRED_SIZE,
                                GroupLayout.DEFAULT_SIZE,
                                GroupLayout.PREFERRED_SIZE)).addGap(
                                    18, 18, 18).addComponent(
                                        jSeparator2,
                                        GroupLayout.PREFERRED_SIZE, 10,
                                        GroupLayout.PREFERRED_SIZE).addGap(
                                            12, 12,
                                            12).addComponent(jLabel2).addGap(
                                                18, 18, 18).
                    addComponent(jLabel3).addPreferredGap(
                        LayoutStyle.ComponentPlacement.UNRELATED).addComponent(
                            jScrollPane1, GroupLayout.PREFERRED_SIZE,
                            GroupLayout.DEFAULT_SIZE,
                            GroupLayout.PREFERRED_SIZE).addPreferredGap(
                                LayoutStyle.ComponentPlacement.UNRELATED).
                    addComponent(jLabel4).addPreferredGap(
                        LayoutStyle.ComponentPlacement.UNRELATED).addComponent(
                            jScrollPane2, GroupLayout.PREFERRED_SIZE,
                            GroupLayout.DEFAULT_SIZE,
                            GroupLayout.PREFERRED_SIZE).addPreferredGap(
                                LayoutStyle.ComponentPlacement.UNRELATED).
                    addComponent(tamperPayloadButton).addGap(36, 36, 36)))

        ProcessorScrollPane.setViewportView(ProcessorPanel)

        TabbedPane1.addTab("Processor", ProcessorScrollPane)

        self.mainPanel = JPanel()
        layout = GroupLayout(self.mainPanel)
        self.mainPanel.setLayout(layout)
        layout.setHorizontalGroup(
            layout.createParallelGroup(
                GroupLayout.Alignment.LEADING).addComponent(
                    TabbedPane1, GroupLayout.DEFAULT_SIZE, 701,
                    Short.MAX_VALUE))
        layout.setVerticalGroup(
            layout.createParallelGroup(
                GroupLayout.Alignment.LEADING).addComponent(TabbedPane1))

        TabbedPane1.getAccessibleContext().setAccessibleName("Generator")
예제 #11
0
class PreferencesFrame(JFrame, ActionListener, WindowListener, ItemListener, HyperlinkListener):
    """Dialog with preferences
    """
    def __init__(self, parent, title, app):
        from javax.swing import JCheckBox, JRadioButton, ButtonGroup
        self.app = app
        border = BorderFactory.createEmptyBorder(5, 7, 5, 7)
        self.getContentPane().setBorder(border)
        self.getContentPane().setLayout(BorderLayout(0, 5))
        self.tabbedPane = JTabbedPane()

        #1 Tab: general
        panel1 = JPanel()
        panel1.setBorder(BorderFactory.createEmptyBorder(7, 7, 7, 7))
        panel1.setLayout(BoxLayout(panel1, BoxLayout.PAGE_AXIS))

        #Checkbutton to enable/disable update check when script starts
        self.updateCBtn = JCheckBox(self.app.strings.getString("updateCBtn"))
        self.updateCBtn.setToolTipText(self.app.strings.getString("updateCBtn_tooltip"))

        #Download tools
        downloadBtn = JButton(self.app.strings.getString("updatesBtn"),
                              ImageProvider.get("dialogs", "refresh"),
                              actionPerformed=self.on_downloadBtn_clicked)
        downloadBtn.setToolTipText(self.app.strings.getString("updatesBtn_tooltip"))

        #Checkbuttons for enabling/disabling tools
        toolsPanel = JPanel(BorderLayout(0, 5))
        title = self.app.strings.getString("enable_disable_tools")
        toolsPanel.setBorder(BorderFactory.createTitledBorder(title))
        infoLbl = JLabel(self.app.strings.getString("JOSM_restart_warning"))
        infoLbl.setFont(infoLbl.getFont().deriveFont(Font.ITALIC))
        toolsPanel.add(infoLbl, BorderLayout.PAGE_START)

        toolsStatusPane = JPanel(GridLayout(len(self.app.realTools), 0))
        self.toolsCBtns = []
        for tool in self.app.realTools:
            toolCBtn = JCheckBox()
            toolCBtn.addItemListener(self)
            toolLbl = JLabel(tool.title, tool.bigIcon, JLabel.LEFT)
            self.toolsCBtns.append(toolCBtn)

            toolPane = JPanel()
            toolPane.setLayout(BoxLayout(toolPane, BoxLayout.X_AXIS))
            toolPane.add(toolCBtn)
            toolPane.add(toolLbl)
            toolsStatusPane.add(toolPane)
        toolsPanel.add(toolsStatusPane, BorderLayout.CENTER)

        #Radiobuttons for enabling/disabling layers when a new one
        #is added
        layersPanel = JPanel(GridLayout(0, 1))
        title = self.app.strings.getString("errors_layers_manager")
        layersPanel.setBorder(BorderFactory.createTitledBorder(title))
        errorLayersLbl = JLabel(self.app.strings.getString("errors_layers_info"))
        errorLayersLbl.setFont(errorLayersLbl.getFont().deriveFont(Font.ITALIC))
        layersPanel.add(errorLayersLbl)
        self.layersRBtns = {}
        group = ButtonGroup()
        for mode in self.app.layersModes:
            layerRBtn = JRadioButton(self.app.strings.getString("%s" % mode))
            group.add(layerRBtn)
            layersPanel.add(layerRBtn)
            self.layersRBtns[mode] = layerRBtn

        #Max number of errors text field
        self.maxErrorsNumberTextField = JTextField()
        self.maxErrorsNumberTextField.setToolTipText(self.app.strings.getString("maxErrorsNumberTextField_tooltip"))
        self.maxErrorsNumberTFieldDefaultBorder = self.maxErrorsNumberTextField.getBorder()
        self.maxErrorsNumberTextField.getDocument().addDocumentListener(ErrNumTextListener(self))

        #layout
        self.updateCBtn.setAlignmentX(Component.LEFT_ALIGNMENT)
        panel1.add(self.updateCBtn)
        panel1.add(Box.createRigidArea(Dimension(0, 15)))
        downloadBtn.setAlignmentX(Component.LEFT_ALIGNMENT)
        panel1.add(downloadBtn)
        panel1.add(Box.createRigidArea(Dimension(0, 15)))
        toolsPanel.setAlignmentX(Component.LEFT_ALIGNMENT)
        panel1.add(toolsPanel)
        panel1.add(Box.createRigidArea(Dimension(0, 15)))
        layersPanel.setAlignmentX(Component.LEFT_ALIGNMENT)
        panel1.add(layersPanel)
        panel1.add(Box.createRigidArea(Dimension(0, 15)))
        maxErrP = JPanel(BorderLayout(5, 0))
        maxErrP.add(JLabel(self.app.strings.getString("max_errors_number")), BorderLayout.LINE_START)
        maxErrP.add(self.maxErrorsNumberTextField, BorderLayout.CENTER)
        p = JPanel(BorderLayout())
        p.add(maxErrP, BorderLayout.PAGE_START)
        p.setAlignmentX(Component.LEFT_ALIGNMENT)
        panel1.add(p)

        self.tabbedPane.addTab(self.app.strings.getString("tab_1_title"),
                          None,
                          panel1,
                          None)

        #2 Tab: favourite zones
        panel2 = JPanel(BorderLayout(5, 15))
        panel2.setBorder(BorderFactory.createEmptyBorder(7, 7, 7, 7))

        #status
        topPanel = JPanel()
        topPanel.setLayout(BoxLayout(topPanel, BoxLayout.Y_AXIS))
        infoPanel = HtmlPanel(self.app.strings.getString("fav_zones_info"))
        infoPanel.getEditorPane().addHyperlinkListener(self)
        infoPanel.setAlignmentX(Component.LEFT_ALIGNMENT)
        self.favZoneStatusCBtn = JCheckBox(self.app.strings.getString("activate_fav_area"),
                                           actionListener=self)
        self.favZoneStatusCBtn.setToolTipText(self.app.strings.getString("activate_fav_area_tooltip"))
        self.favZoneStatusCBtn.setAlignmentX(Component.LEFT_ALIGNMENT)
        topPanel.add(infoPanel)
        topPanel.add(Box.createRigidArea(Dimension(0, 10)))
        topPanel.add(self.favZoneStatusCBtn)
        #table
        self.zonesTable = JTable()
        tableSelectionModel = self.zonesTable.getSelectionModel()
        tableSelectionModel.addListSelectionListener(ZonesTableListener(self))
        columns = ["",
                   self.app.strings.getString("Type"),
                   self.app.strings.getString("Name")]
        tableModel = ZonesTableModel([], columns)
        self.zonesTable.setModel(tableModel)
        self.scrollPane = JScrollPane(self.zonesTable)
        #map
        self.zonesMap = JMapViewer()
        self.zonesMap.setZoomContolsVisible(False)
        self.zonesMap.setMinimumSize(Dimension(100, 200))

        #buttons
        self.removeBtn = JButton(self.app.strings.getString("Remove"),
                            ImageProvider.get("dialogs", "delete"),
                            actionPerformed=self.on_removeBtn_clicked)
        self.removeBtn.setToolTipText(self.app.strings.getString("remove_tooltip"))
        newBtn = JButton(self.app.strings.getString("New"),
                         ImageProvider.get("dialogs", "add"),
                         actionPerformed=self.on_newBtn_clicked)
        newBtn.setToolTipText(self.app.strings.getString("new_tooltip"))

        #layout
        panel2.add(topPanel, BorderLayout.PAGE_START)
        panel2.add(self.scrollPane, BorderLayout.LINE_START)
        panel2.add(self.zonesMap, BorderLayout.CENTER)
        self.buttonsPanel = JPanel()
        self.buttonsPanel.add(self.removeBtn)
        self.buttonsPanel.add(newBtn)
        panel2.add(self.buttonsPanel, BorderLayout.PAGE_END)

        self.tabbedPane.addTab(self.app.strings.getString("tab_2_title"),
                          None,
                          panel2,
                          None)

        #3 Tab Tools options
        panel3 = JPanel()
        panel3.setLayout(BoxLayout(panel3, BoxLayout.Y_AXIS))
        panel3.setBorder(BorderFactory.createEmptyBorder(7, 7, 7, 7))
        for tool in self.app.realTools:
            if hasattr(tool, 'prefs'):
                p = JPanel(FlowLayout(FlowLayout.LEFT))
                p.setBorder(BorderFactory.createTitledBorder(tool.title))
                p.add(tool.prefsGui)
                panel3.add(p)

        self.tabbedPane.addTab(self.app.strings.getString("tab_3_title"),
                          None,
                          panel3,
                          None)

        self.add(self.tabbedPane, BorderLayout.CENTER)

        exitPanel = JPanel()
        saveBtn = JButton(self.app.strings.getString("OK"),
                          ImageProvider.get("ok"),
                          actionPerformed=self.on_saveBtn_clicked)
        cancelBtn = JButton(self.app.strings.getString("cancel"),
                            ImageProvider.get("cancel"),
                            actionPerformed=self.on_cancelBtn_clicked)
        saveBtn.setToolTipText(self.app.strings.getString("save_preferences"))
        saveBtn.setAlignmentX(0.5)
        exitPanel.add(saveBtn)
        exitPanel.add(cancelBtn)
        self.add(exitPanel, BorderLayout.PAGE_END)

        self.addWindowListener(self)
        self.pack()

    def windowClosing(self, windowEvent):
        self.on_cancelBtn_clicked()

    def hyperlinkUpdate(self, e):
        if e.getEventType() == HyperlinkEvent.EventType.ACTIVATED:
            OpenBrowser.displayUrl(e.getURL().toString())

    def itemStateChanged(self, e):
        """A ttol has been activated/deactivated.
           Check if at least one tool is on.
        """
        if all(not button.isSelected() for button in self.toolsCBtns):
            JOptionPane.showMessageDialog(
                Main.parent,
                self.app.strings.getString("tools_disabled_warning"),
                self.app.strings.getString("tools_disabled_warning_title"),
                JOptionPane.WARNING_MESSAGE)
            source = e.getItemSelectable()
            source.setSelected(True)

    def actionPerformed(self, e=None):
        """Enable/disable favourite zones panel
        """
        for container in (self.scrollPane, self.buttonsPanel):
            self.enableComponents(container, self.favZoneStatusCBtn.isSelected())
        if self.favZoneStatusCBtn.isSelected():
            self.check_removeBtn_status()

    def enableComponents(self, container, enable):
        components = container.getComponents()
        for component in components:
            component.setEnabled(enable)
            if isinstance(component, Container):
                self.enableComponents(component, enable)

    def on_downloadBtn_clicked(self, e):
        update_checker.Updater(self.app, "manual")

    def clean_map(self):
        """Remove all rectangles and polygons from the map
        """
        self.zonesMap.removeAllMapRectangles()
        self.zonesMap.removeAllMapPolygons()

    def update_gui_from_preferences(self):
        """Update gui status of preferences frame from config file
        """
        #print "\n- updating Preferences gui"
        onOff = {"on": True, "off": False}
        #1 Tab
        #check for update
        self.updateCBtn.setSelected(onOff[self.app.checkUpdate])

        #tools status, enabled or not
        for toolIndex, tool in enumerate(self.app.realTools):
            if "tool.%s" % tool.name in self.app.properties.keys():
                configstatus = self.app.properties.getProperty("tool.%s" % tool.name)
            else:
                configstatus = "on"     # new tool
            self.toolsCBtns[toolIndex].setSelected(onOff[configstatus])

        #layers preferences
        for mode, button in self.layersRBtns.iteritems():
            button.setSelected(mode == self.app.layersMode)

        #max errors number
        self.maxErrorsNumberTextField.setText(str(self.app.maxErrorsNumber))

        #stats panel
        self.app.dlg.update_favourite_zone_indicator()

        #2 Tab
        #favourite area
        self.update_favourite_area_gui_from_preferences()
        self.app.dlg.update_statsPanel_status()

        #3 Tab
        #tools preferences
        for tool in self.app.allTools:
            if hasattr(tool, 'prefs') and tool.prefsGui is not None:
                tool.prefsGui.update_gui(tool.prefs)

    def update_favourite_area_gui_from_preferences(self):
        #status
        self.favZoneStatusCBtn.setSelected(self.app.favouriteZoneStatus)
        #table
        #store zones to a temporary list, used to store changes
        #and save them when preferences dialog is closed
        self.app.tempZones = list(self.app.zones)
        self.zonesTable.getModel().setNumRows(0)
        for zone in self.app.tempZones:
            self.zonesTable.getModel().addRow([zone.country,
                                               zone.icon,
                                               zone.name])
        if self.app.favZone is not None:
            selectedRow = self.app.tempZones.index(self.app.favZone)
            self.zonesTable.setRowSelectionInterval(selectedRow, selectedRow)
        self.zonesTable.getColumnModel().getColumn(0).setMaxWidth(30)
        self.zonesTable.getColumnModel().getColumn(1).setMaxWidth(50)
        #enable or disable favourite zone buttons
        self.actionPerformed()

### fav area editing buttons ###########################################
    def on_removeBtn_clicked(self, e):
        rowsNum = self.zonesTable.getSelectedRows()
        rowsNum.reverse()
        for rowNum in rowsNum:
            del self.app.tempZones[rowNum]
            self.zonesTable.getModel().removeRow(rowNum)
        if len(self.app.tempZones) != 0:
            if rowNum == 0:
                self.zonesTable.setRowSelectionInterval(0, 0)
            else:
                self.zonesTable.setRowSelectionInterval(rowNum - 1, rowNum - 1)
        self.check_removeBtn_status()

    def check_removeBtn_status(self):
        if self.app.tempZones != [] and len(self.zonesTable.getSelectedRows()) != 0:
            self.removeBtn.setEnabled(True)
        else:
            self.removeBtn.setEnabled(False)
            self.clean_map()

    def on_newBtn_clicked(self, e):
        try:
            self.newZoneDialog
        except AttributeError:
            self.newZoneDialog = NewZoneDialog(self.app)
        bbox = self.app.get_frame_bounds()
        self.app.newZone = Zone(self.app,
                                self.app.strings.getString("New_zone"),
                                "rectangle",
                                ",".join(["%0.4f" % x for x in bbox]),
                                "")
        self.newZoneDialog.update_gui_from_preferences()
        self.newZoneDialog.show()

### Exit from preferences ##############################################
    def on_cancelBtn_clicked(self, event=None):
        if hasattr(self, "newZoneDialog") and self.newZoneDialog.isVisible():
            self.newZoneDialog.close_dialog()
        self.dispose()

    def on_saveBtn_clicked(self, event):
        """Read preferences from gui and save them to config.properties
           file
        """
        #print "\n- saving preferences to config file"
        onOff = {True: "on", False: "off"}

        #1 Tab
        #check for update
        self.app.properties.setProperty("check_for_update",
                                        onOff[self.updateCBtn.isSelected()])
        #tools status
        for toolIndex, tool in enumerate(self.app.realTools):
            prop = "tool.%s" % tool.name
            toolCBtn = self.toolsCBtns[toolIndex]
            self.app.properties.setProperty(prop,
                                            onOff[toolCBtn.isSelected()])

        #layers preferences
        for mode, button in self.layersRBtns.iteritems():
            if button.isSelected():
                self.app.properties.setProperty("layers_mode", mode)
                break

        #max errors number
        try:
            num = Integer.parseInt(self.maxErrorsNumberTextField.getText())
        except NumberFormatException:
            num = ""
        self.app.properties.setProperty("max_errors_number", str(num))

        #2 Tab
        #Favourite zones
        changes = {"new": [z for z in self.app.tempZones if not z in self.app.zones],
                   "deleted": [z for z in self.app.zones if not z in self.app.tempZones]}
        #delete files of removed favourite zones
        for zone in changes["deleted"]:
            f = File(File.separator.join([self.app.SCRIPTDIR,
                                          "configuration",
                                          "favourite_zones",
                                          "%s.txt" % zone.name]))
            f.delete()
        #create files for new favourite zones
        for zone in changes["new"]:
            print "\nsave new zone", zone.name
            fileName = File.separator.join([self.app.SCRIPTDIR,
                                            "configuration",
                                            "favourite_zones",
                                            "%s.txt" % zone.name])
            f = open(fileName, "w")
            zoneData = zone.geomString
            if zone.country != "":
                zoneData += "|" + zone.country
            f.write(zoneData.encode("utf-8"))
            f.close()

        self.app.zones = self.app.tempZones
        if len(self.app.zones) == 0:
            self.app.favZone = None
            self.app.properties.setProperty("favourite_area.name",
                                            "")
            self.favZoneStatusCBtn.setSelected(False)
        else:
            if len(self.zonesTable.getSelectedRows()) == 0:
                self.app.favZone = self.app.zones[0]
            else:
                self.app.favZone = self.app.zones[self.zonesTable.getSelectedRows()[0]]
            self.app.properties.setProperty("favourite_area.name",
                                            self.app.favZone.name)
        favZoneStatus = self.favZoneStatusCBtn.isSelected()
        self.app.properties.setProperty("favourite_area.status", onOff[favZoneStatus])
        self.app.favouriteZoneStatus = favZoneStatus

        #stats panel
        self.app.dlg.update_favourite_zone_indicator()
        self.app.dlg.update_statsPanel_status()

        #3 Tab
        #tools preferences
        for tool in self.app.allTools:
            if hasattr(tool, 'prefs') and tool.prefsGui is not None:
                for pref, value in tool.prefsGui.read_gui().iteritems():
                    prefKey = "tool.%s.%s" % (tool.name, pref)
                    self.app.properties.setProperty(prefKey, value)

        self.app.save_config()
        self.dispose()
예제 #12
0
class Config(ITab):
    """Defines the Configuration tab"""

    def __init__(self, callbacks, parent):
        # Initialze self stuff
        self._callbacks = callbacks
        self.config = {}
        self.ext_stats = {}
        self.url_reqs = []
        self.parse_files = False
        self.tab = JPanel(GridBagLayout())
        self.view_port_text = JTextArea("===SpyDir===")
        self.delim = JTextField(30)
        self.ext_white_list = JTextField(30)
        # I'm not sure if these fields are necessary still
        # why not just use Burp func to handle this?
        # leaving them in case I need it for the HTTP handler later
        # self.cookies = JTextField(30)
        # self.headers = JTextField(30)
        self.url = JTextField(30)
        self.parent_window = parent
        self.plugins = {}
        self.loaded_p_list = set()
        self.loaded_plugins = False
        self.config['Plugin Folder'] = None
        self.double_click = False
        self.source_input = ""
        self.print_stats = True
        self.curr_conf = JLabel()
        self.window = JFrame("Select plugins",
                             preferredSize=(200, 250),
                             windowClosing=self.p_close)
        self.window.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE)
        self.window.setVisible(False)
        self.path_vars = JTextField(30)


        # Initialize local stuff
        tab_constraints = GridBagConstraints()
        status_field = JScrollPane(self.view_port_text)

        # Configure view port
        self.view_port_text.setEditable(False)

        labels = self.build_ui()

        # Add things to rows
        tab_constraints.anchor = GridBagConstraints.FIRST_LINE_END
        tab_constraints.gridx = 1
        tab_constraints.gridy = 0
        tab_constraints.fill = GridBagConstraints.HORIZONTAL
        self.tab.add(JButton(
            "Resize screen", actionPerformed=self.resize),
                     tab_constraints)
        tab_constraints.gridx = 0
        tab_constraints.gridy = 1
        tab_constraints.anchor = GridBagConstraints.FIRST_LINE_START
        self.tab.add(labels, tab_constraints)

        tab_constraints.gridx = 1
        tab_constraints.gridy = 1
        tab_constraints.fill = GridBagConstraints.BOTH
        tab_constraints.weightx = 1.0
        tab_constraints.weighty = 1.0

        tab_constraints.anchor = GridBagConstraints.FIRST_LINE_END
        self.tab.add(status_field, tab_constraints)
        try:
            self._callbacks.customizeUiComponent(self.tab)
        except Exception:
            pass

    def build_ui(self):
        """Builds the configuration screen"""
        labels = JPanel(GridLayout(21, 1))
        checkbox = JCheckBox("Attempt to parse files for URL patterns?",
                             False, actionPerformed=self.set_parse)
        stats_box = JCheckBox("Show stats?", True,
                              actionPerformed=self.set_show_stats)
        # The two year old in me is laughing heartily
        plug_butt = JButton("Specify plugins location",
                            actionPerformed=self.set_plugin_loc)
        load_plug_butt = JButton("Select plugins",
                                 actionPerformed=self.p_build_ui)
        parse_butt = JButton("Parse directory", actionPerformed=self.parse)
        clear_butt = JButton("Clear text", actionPerformed=self.clear)
        spider_butt = JButton("Send to Spider", actionPerformed=self.scan)
        save_butt = JButton("Save config", actionPerformed=self.save)
        rest_butt = JButton("Restore config", actionPerformed=self.restore)
        source_butt = JButton("Input Source File/Directory",
                              actionPerformed=self.get_source_input)

        # Build grid
        labels.add(source_butt)
        labels.add(self.curr_conf)
        labels.add(JLabel("String Delimiter:"))
        labels.add(self.delim)
        labels.add(JLabel("Extension Whitelist:"))
        labels.add(self.ext_white_list)
        labels.add(JLabel("URL:"))
        labels.add(self.url)
        labels.add(JLabel("Path Variables"))
        labels.add(self.path_vars)
        # Leaving these here for now.
        # labels.add(JLabel("Cookies:"))
        # labels.add(self.cookies)
        # labels.add(JLabel("HTTP Headers:"))
        # labels.add(self.headers)
        labels.add(checkbox)
        labels.add(stats_box)
        labels.add(plug_butt)
        labels.add(parse_butt)
        labels.add(JButton("Show all endpoints",
                           actionPerformed=self.print_endpoints))
        labels.add(clear_butt)
        labels.add(spider_butt)
        labels.add(JLabel(""))
        labels.add(save_butt)
        labels.add(rest_butt)
        labels.add(load_plug_butt)
        # Tool tips!
        self.delim.setToolTipText("Use to manipulate the final URL. "
                                  "See About tab for example.")
        self.ext_white_list.setToolTipText("Define a comma delimited list of"
                                           " file extensions to parse. Use *"
                                           " to parse all files.")
        self.url.setToolTipText("Enter the target URL")
        checkbox.setToolTipText("Parse files line by line using plugins"
                                " to enumerate language/framework specific"
                                " endpoints")
        parse_butt.setToolTipText("Attempt to enumerate application endpoints")
        clear_butt.setToolTipText("Clear status window and the parse results")
        spider_butt.setToolTipText("Process discovered endpoints")
        save_butt.setToolTipText("Saves the current config settings")
        rest_butt.setToolTipText("<html>Restores previous config settings:"
                                 "<br/>-Input Directory<br/>-String Delim"
                                 "<br/>-Ext WL<br/>-URL<br/>-Plugins")
        source_butt.setToolTipText("Select the application's "
                                   "source directory or file to parse")
        self.path_vars.setToolTipText("Supply a JSON object with values"
                                      "for dynamically enumerated query"
                                      "string variables")

        return labels

    def set_url(self, menu_url):
        """Changes the configuration URL to the one from the menu event"""
        self.url.setText(menu_url)

    # Event functions
    def set_parse(self, event):
        """
        Handles the click event from the UI checkbox
        to attempt code level parsing
        """
        self.parse_files = not self.parse_files
        if self.parse_files:
            if not self.loaded_plugins:
                self._plugins_missing_warning()

    def restore(self, event):
        """Attempts to restore the previously saved configuration."""
        jdump = None
        try:
            jdump = loads(self._callbacks.loadExtensionSetting("config"))
        except Exception as exc:  # Generic exception thrown directly to user
            self.update_scroll(
                "[!!] Error during restore!\n\tException: %s" % str(exc))
        if jdump is not None:
            self.url.setText(jdump.get('URL'))
            # self.cookies.setText(jdump.get('Cookies'))
            # self.headers.setText(jdump.get("Headers"))
            ewl = ""
            for ext in jdump.get('Extension Whitelist'):
                ewl += ext + ", "
            self.ext_white_list.setText(ewl[:-2])
            self.delim.setText(jdump.get('String Delimiter'))
            self.source_input = jdump.get("Input Directory")
            self.config['Plugin Folder'] = jdump.get("Plugin Folder")
            if (self.config['Plugin Folder'] is not None and
                    (len(self.plugins.values()) < 1)):
                self._load_plugins(self.config['Plugin Folder'])
            self._update()
            self.update_scroll("[^] Restore complete!")
        else:
            self.update_scroll("[!!] Restore failed!")

    def save(self, event=None):
        """
        Saves the configuration details to a Burp Suite's persistent store.
        """
        self._update()
        try:
            if not self._callbacks.isInScope(URL(self.url.getText())):
                self.update_scroll("[!!] URL provided is NOT in Burp Scope!")
        except MalformedURLException:  # If url field is blank we'll
            pass                       # still save the settings.
        try:
            self._callbacks.saveExtensionSetting("config", dumps(self.config))
            self.update_scroll("[^] Settings saved!")
        except Exception:
            self.update_scroll("[!!] Error saving settings to Burp Suite!")

    def parse(self, event):
        """
        Handles the click event from the UI.
        Attempts to parse the given directory
            (and/or source files) for url endpoints
        Saves the items found within the url_reqs list
        """
        self._update()

        file_set = set()
        fcount = 0
        other_dirs = set()
        self.ext_stats = {}
        if self.loaded_plugins:
            self.update_scroll("[^] Attempting to parse files" +
                               " for URL patterns. This might take a minute.")
        if path.isdir(self.source_input):
            for dirname, _, filenames in walk(self.source_input):
                for filename in filenames:
                    fcount += 1
                    ext = path.splitext(filename)[1]
                    count = self.ext_stats.get(ext, 0) + 1
                    filename = "%s/%s" % (dirname, filename)
                    self.ext_stats.update({ext: count})
                    if self.parse_files and self._ext_test(ext):
                        # i can haz threading?
                        file_set.update(self._code_as_endpoints(filename, ext))
                    elif self._ext_test(ext):
                        r_files, oths = self._files_as_endpoints(filename, ext)
                        file_set.update(r_files)
                        other_dirs.update(oths)
        elif path.isfile(self.source_input):
            ext = path.splitext(self.source_input)[1]
            file_set.update(self._code_as_endpoints(self.source_input, ext))
        else:
            self.update_scroll("[!!] Input Directory is not valid!")
        if len(other_dirs) > 0:
            self.update_scroll("[*] Found files matching file extension in:\n")
            for other_dir in other_dirs:
                self.update_scroll(" " * 4 + "%s\n" % other_dir)
        self._handle_path_vars(file_set)
        self._print_parsed_status(fcount)
        return (other_dirs, self.url_reqs)

    def _handle_path_vars(self, file_set):
        proto = 'http://'
        for item in file_set:
            if item.startswith("http://") or item.startswith("https://"):
                proto = item.split("//")[0] + '//'
                item = item.replace(proto, "")
                item = self._path_vars(item)
            self.url_reqs.append(proto + item.replace('//', '/'))

    def _path_vars(self, item):
        p_vars = None
        if self.path_vars.getText():
            try:
                p_vars = loads(str(self.path_vars.getText()))
            except:
                self.update_scroll("[!] Error reading supplied Path Variables!")
        if p_vars is not None:
            rep_str = ""
            try:
                for k in p_vars.keys():
                    rep_str += "[^] Replacing %s with %s!\n" % (k, str(p_vars.get(k)))
                self.update_scroll(rep_str)
                for k in p_vars.keys():
                    if str(k) in item:
                        item = item.replace(k, str(p_vars.get(k)))
            except AttributeError:
                self.update_scroll("[!] Error reading supplied Path Variables! This needs to be a JSON dictionary!")
        return item
            
            
    def scan(self, event):
        """
        handles the click event from the UI.
        Adds the given URL to the burp scope and sends the requests
        to the burp spider
        """
        temp_url = self.url.getText()
        if not self._callbacks.isInScope(URL(temp_url)):
            if not self.double_click:
                self.update_scroll("[!!] URL is not in scope! Press Send to "
                                   "Spider again to add to scope and scan!")
                self.double_click = True
                return
            else:
                self._callbacks.sendToSpider(URL(temp_url))
        self.update_scroll(
            "[^] Sending %d requests to Spider" % len(self.url_reqs))
        for req in self.url_reqs:
            self._callbacks.sendToSpider(URL(req))

    def clear(self, event):
        """Clears the viewport and the current parse exts"""
        self.view_port_text.setText("===SpyDir===")
        self.ext_stats = {}

    def print_endpoints(self, event):
        """Prints the discovered endpoints to the status window."""
        req_str = ""
        if len(self.url_reqs) > 0:
            self.update_scroll("[*] Printing all discovered endpoints:")
            for req in sorted(self.url_reqs):
                req_str += "    %s\n" % req
        else:
            req_str = "[!!] No endpoints discovered"
        self.update_scroll(req_str)

    def set_show_stats(self, event):
        """Modifies the show stats setting"""
        self.print_stats = not self.print_stats

    def get_source_input(self, event):
        """Sets the source dir/file for parsing"""
        source_chooser = JFileChooser()
        source_chooser.setFileSelectionMode(
            JFileChooser.FILES_AND_DIRECTORIES)
        source_chooser.showDialog(self.tab, "Choose Source Location")
        chosen_source = source_chooser.getSelectedFile()
        try:
            self.source_input = chosen_source.getAbsolutePath()
        except AttributeError:
            pass
        if self.source_input is not None:
            self.update_scroll("[*] Source location: %s" % self.source_input)
            self.curr_conf.setText(self.source_input)

    # Plugin functions
    def _parse_file(self, filename, file_url):
        """
        Attempts to parse a file with the loaded plugins
        Returns set of endpoints
        """
        file_set = set()
        with open(filename, 'r') as plug_in:
            lines = plug_in.readlines()
        ext = path.splitext(filename)[1].upper()
        if ext in self.plugins.keys() and self._ext_test(ext):
            for plug in self.plugins.get(ext):
                if plug.enabled:
                    res = plug.run(lines)
                    if len(res) > 0:
                        for i in res:
                            i = file_url + i
                            file_set.add(i)
        elif ext == '.TXT' and self._ext_test(ext):
            for i in lines:
                i = file_url + i
                file_set.add(i.strip())
        return file_set

    def set_plugin_loc(self, event):
        """Attempts to load plugins from a specified location"""
        if self.config['Plugin Folder'] is not None:
            choose_plugin_location = JFileChooser(self.config['Plugin Folder'])
        else:
            choose_plugin_location = JFileChooser()
        choose_plugin_location.setFileSelectionMode(
            JFileChooser.DIRECTORIES_ONLY)
        choose_plugin_location.showDialog(self.tab, "Choose Folder")
        chosen_folder = choose_plugin_location.getSelectedFile()
        self.config['Plugin Folder'] = chosen_folder.getAbsolutePath()
        self._load_plugins(self.config['Plugin Folder'])

    def _load_plugins(self, folder):
        """
        Parses a local directory to get the plugins
            related to code level scanning
        """
        report = ""
        if len(self.plugins.keys()) > 0:
            report = "[^] Plugins reloaded!"
        for _, _, filenames in walk(folder):
            for p_name in filenames:
                n_e = path.splitext(p_name)  # n_e = name_extension
                if n_e[1] == ".py":
                    f_loc = "%s/%s" % (folder, p_name)
                    loaded_plug = self._validate_plugin(n_e[0], f_loc)
                    if loaded_plug:
                        for p in self.loaded_p_list:
                            if p.get_name() == loaded_plug.get_name():
                                self.loaded_p_list.discard(p)
                        self.loaded_p_list.add(loaded_plug)
                        if not report.startswith("[^]"):
                            report += "%s loaded\n" % loaded_plug.get_name()

        self._dictify(self.loaded_p_list)
        if len(self.plugins.keys()) > 0:
            self.loaded_plugins = True
        else:
            report = "[!!] Plugins load failure"
            self.loaded_plugins = False
        self.update_scroll(report)
        return report

    def _validate_plugin(self, p_name, f_loc):
        """
        Attempts to verify the manditory plugin functions to prevent broken
        plugins from loading.
        Generates an error message if plugin does not contain an appropriate
        function.
        """
        # Load the plugin
        try:
            plug = load_source(p_name, f_loc)
        except Exception as exc:  # this needs to be generic.
            self.update_scroll(
                "[!!] Error loading: %s\n\tType:%s Error: %s"
                % (f_loc, type(exc), str(exc)))
        # Verify the plugin's functions
        funcs = dir(plug)
        err = []
        if "get_name" not in funcs:
            err.append("get_name()")
        if "get_ext" not in funcs:
            err.append("get_ext()")
        if "run" not in funcs:
            err.append("run()")

        # Report errors & return
        if len(err) < 1:
            return Plugin(plug, True)
        for issue in err:
            self.update_scroll("[!!] %s is missing: %s func" %
                               (p_name, issue))
        return None

    def _dictify(self, plist):
        """Converts the list of loaded plugins (plist) into a dictionary"""
        for p in plist:
            exts = p.get_ext().upper()
            for ext in exts.split(","):
                prev_load = self.plugins.get(ext, [])
                prev_load.append(p)
                self.plugins[ext] = prev_load

    # Status window functions
    def _print_parsed_status(self, fcount):
        """Prints the parsed directory status information"""
        if self.parse_files and not self.loaded_plugins:
            self._plugins_missing_warning()
        if len(self.url_reqs) > 0:
            self.update_scroll("[*] Example URL: %s" % self.url_reqs[0])

        if self.print_stats:
            report = (("[*] Found: %r files to be requested.\n\n" +
                       "[*] Stats: \n    " +
                       "Found: %r files.\n") % (len(self.url_reqs), fcount))
            if len(self.ext_stats) > 0:
                report += ("[*] Extensions found: %s"
                           % str(dumps(self.ext_stats,
                                       sort_keys=True, indent=4)))
        else:
            report = ("[*] Found: %r files to be requested.\n" %
                      len(self.url_reqs))
        self.update_scroll(report)
        return report

    def _plugins_missing_warning(self):
        """Prints a warning message"""
        self.update_scroll("[!!] No plugins loaded!")

    def update_scroll(self, text):
        """Updates the view_port_text with the new information"""
        temp = self.view_port_text.getText().strip()
        if text not in temp or text[0:4] == "[!!]":
            self.view_port_text.setText("%s\n%s" % (temp, text))
        elif not temp.endswith("[^] Status unchanged"):
            self.view_port_text.setText("%s\n[^] Status unchanged" % temp)

    # Internal functions
    def _code_as_endpoints(self, filename, ext):
        file_set = set()
        file_url = self.config.get("URL")
        if self.loaded_plugins or ext == '.txt':
            if self._ext_test(ext):
                file_set.update(
                    self._parse_file(filename, file_url))
            else:
                file_set.update(
                    self._parse_file(filename, file_url))
        return file_set

    def _files_as_endpoints(self, filename, ext):
        """Generates endpoints via files with the appropriate extension(s)"""
        file_url = self.config.get("URL")
        broken_splt = ""
        other_dirs = set()  # directories outside of the String Delim.
        file_set = set()
        str_del = self.config.get("String Delimiter")
        if not str_del:
            self.update_scroll("[!!] No available String Delimiter!")
            return
        spl_str = filename.split(str_del)

        try:
            # Fix for index out of bounds exception while parsing
            # subfolders _not_ included by the split
            if len(spl_str) > 1:
                file_url += ((spl_str[1])
                             .replace('\\', '/'))
            else:
                broken_splt = filename.split(self.source_input)[1]
                other_dirs.add(broken_splt)
        except Exception as exc:  # Generic exception thrown directly to user
            self.update_scroll("[!!] Error parsing: " +
                               "%s\n\tException: %s"
                               % (filename, str(exc)))
        if self._ext_test(ext):
            if file_url != self.config.get("URL"):
                file_set.add(file_url)
        else:
            other_dirs.discard(broken_splt)
        return file_set, other_dirs

    def _ext_test(self, ext):
        """Litmus test for extension whitelist"""
        val = False
        if "*" in self.config.get("Extension Whitelist"):
            val = True
        else:
            val = (len(ext) > 0 and
                   (ext.strip().upper()
                    in self.config.get("Extension Whitelist")))
        return val

    def _update(self):
        """Updates internal data"""
        self.config["Input Directory"] = self.source_input
        self.config["String Delimiter"] = self.delim.getText()

        white_list_text = self.ext_white_list.getText()
        self.config["Extension Whitelist"] = white_list_text.upper().split(',')
        file_url = self.url.getText()
        if not (file_url.startswith('https://') or file_url.startswith('http://')):
            self.update_scroll("[!] Assuming protocol! Default value: 'http://'")
            file_url = 'http://' + file_url
            self.url.setText(file_url)

        if not file_url.endswith('/') and file_url != "":
            file_url += '/'

        self.config["URL"] = file_url
        # self.config["Cookies"] = self.cookies.getText()
        # self.config["Headers"] = self.headers.getText()
        del self.url_reqs[:]
        self.curr_conf.setText(self.source_input)

    # Window sizing functions
    def resize(self, event):
        """Resizes the window to better fit Burp"""
        if self.parent_window is not None:
            par_size = self.parent_window.getSize()
            par_size.setSize(par_size.getWidth() * .99,
                             par_size.getHeight() * .9)
            self.tab.setPreferredSize(par_size)
            self.parent_window.validate()
            self.parent_window.switch_focus()

    def p_close(self, event):
        """
        Handles the window close event.
        """
        self.window.setVisible(False)
        self.window.dispose()

    def p_build_ui(self, event):
        """
        Adds a list of checkboxes, one for each loaded plugin
        to the Selct plugins window
        """
        if not self.loaded_p_list:
            self.update_scroll("[!!] No plugins loaded!")
            return

        scroll_pane = JScrollPane()
        scroll_pane.setPreferredSize(Dimension(200, 250))
        check_frame = JPanel(GridBagLayout())
        constraints = GridBagConstraints()
        constraints.fill = GridBagConstraints.HORIZONTAL
        constraints.gridy = 0
        constraints.anchor = GridBagConstraints.FIRST_LINE_START

        for plug in self.loaded_p_list:
            check_frame.add(JCheckBox(plug.get_name(), plug.enabled,
                                      actionPerformed=self.update_box),
                            constraints)
            constraints.gridy += 1

        vport = JViewport()
        vport.setView(check_frame)
        scroll_pane.setViewport(vport)
        self.window.contentPane.add(scroll_pane)
        self.window.pack()
        self.window.setVisible(True)

    def update_box(self, event):
        """
        Handles the check/uncheck event for the plugin's box.
        """
        for plug in self.loaded_p_list:
            if plug.get_name() == event.getActionCommand():
                plug.enabled = not plug.enabled
                if plug.enabled:
                    self.update_scroll("[^] Enabled: %s" %
                                       event.getActionCommand())
                else:
                    self.update_scroll("[^] Disabled: %s" %
                                       event.getActionCommand())

    # ITab required functions
    @staticmethod
    def getTabCaption():
        """Returns the name of the Burp Suite Tab"""
        return "SpyDir"

    def getUiComponent(self):
        """Returns the UI component for the Burp Suite tab"""
        return self.tab
예제 #13
0
class Config(ITab):
    """Defines the Configuration tab"""

    def __init__(self, callbacks, parent):
        # Initialze self stuff
        self._callbacks = callbacks
        self.config = {}
        self.ext_stats = {}
        self.url_reqs = []
        self.parse_files = False
        self.tab = JPanel(GridBagLayout())
        self.view_port_text = JTextArea("===SpyDir===")
        self.delim = JTextField(30)
        self.ext_white_list = JTextField(30)
        # I'm not sure if these fields are necessary still
        # why not just use Burp func to handle this?
        # leaving them in case I need it for the HTTP handler later
        # self.cookies = JTextField(30)
        # self.headers = JTextField(30)
        self.url = JTextField(30)
        self.parent_window = parent
        self.plugins = {}
        self.loaded_p_list = set()
        self.loaded_plugins = False
        self.config['Plugin Folder'] = None
        self.double_click = False
        self.source_input = ""
        self.print_stats = True
        self.curr_conf = JLabel()
        self.window = JFrame("Select plugins",
                             preferredSize=(200, 250),
                             windowClosing=self.p_close)
        self.window.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE)
        self.window.setVisible(False)

        # Initialize local stuff
        tab_constraints = GridBagConstraints()
        status_field = JScrollPane(self.view_port_text)

        # Configure view port
        self.view_port_text.setEditable(False)

        labels = self.build_ui()

        # Add things to rows
        tab_constraints.anchor = GridBagConstraints.FIRST_LINE_END
        tab_constraints.gridx = 1
        tab_constraints.gridy = 0
        tab_constraints.fill = GridBagConstraints.HORIZONTAL
        self.tab.add(JButton(
            "Resize screen", actionPerformed=self.resize),
                     tab_constraints)
        tab_constraints.gridx = 0
        tab_constraints.gridy = 1
        tab_constraints.anchor = GridBagConstraints.FIRST_LINE_START
        self.tab.add(labels, tab_constraints)

        tab_constraints.gridx = 1
        tab_constraints.gridy = 1
        tab_constraints.fill = GridBagConstraints.BOTH
        tab_constraints.weightx = 1.0
        tab_constraints.weighty = 1.0

        tab_constraints.anchor = GridBagConstraints.FIRST_LINE_END
        self.tab.add(status_field, tab_constraints)
        try:
            self._callbacks.customizeUiComponent(self.tab)
        except Exception:
            pass

    def build_ui(self):
        """Builds the configuration screen"""
        labels = JPanel(GridLayout(21, 1))
        checkbox = JCheckBox("Attempt to parse files for URL patterns?",
                             False, actionPerformed=self.set_parse)
        stats_box = JCheckBox("Show stats?", True,
                              actionPerformed=self.set_show_stats)
        # The two year old in me is laughing heartily
        plug_butt = JButton("Specify plugins location",
                            actionPerformed=self.set_plugin_loc)
        load_plug_butt = JButton("Select plugins",
                                 actionPerformed=self.p_build_ui)
        parse_butt = JButton("Parse directory", actionPerformed=self.parse)
        clear_butt = JButton("Clear text", actionPerformed=self.clear)
        spider_butt = JButton("Send to Spider", actionPerformed=self.scan)
        save_butt = JButton("Save config", actionPerformed=self.save)
        rest_butt = JButton("Restore config", actionPerformed=self.restore)
        source_butt = JButton("Input Source File/Directory",
                              actionPerformed=self.get_source_input)

        # Build grid
        labels.add(source_butt)
        labels.add(self.curr_conf)
        labels.add(JLabel("String Delimiter:"))
        labels.add(self.delim)
        labels.add(JLabel("Extension Whitelist:"))
        labels.add(self.ext_white_list)
        labels.add(JLabel("URL:"))
        labels.add(self.url)
        # Leaving these here for now.
        # labels.add(JLabel("Cookies:"))
        # labels.add(self.cookies)
        # labels.add(JLabel("HTTP Headers:"))
        # labels.add(self.headers)
        labels.add(checkbox)
        labels.add(stats_box)
        labels.add(plug_butt)
        labels.add(parse_butt)
        labels.add(JButton("Show all endpoints",
                           actionPerformed=self.print_endpoints))
        labels.add(clear_butt)
        labels.add(spider_butt)
        labels.add(JLabel(""))
        labels.add(save_butt)
        labels.add(rest_butt)
        labels.add(load_plug_butt)
        # Tool tips!
        self.delim.setToolTipText("Use to manipulate the final URL. "
                                  "See About tab for example.")
        self.ext_white_list.setToolTipText("Define a comma delimited list of"
                                           " file extensions to parse. Use *"
                                           " to parse all files.")
        self.url.setToolTipText("Enter the target URL")
        checkbox.setToolTipText("Parse files line by line using plugins"
                                " to enumerate language/framework specific"
                                " endpoints")
        parse_butt.setToolTipText("Attempt to enumerate application endpoints")
        clear_butt.setToolTipText("Clear status window and the parse results")
        spider_butt.setToolTipText("Process discovered endpoints")
        save_butt.setToolTipText("Saves the current config settings")
        rest_butt.setToolTipText("<html>Restores previous config settings:"
                                 "<br/>-Input Directory<br/>-String Delim"
                                 "<br/>-Ext WL<br/>-URL<br/>-Plugins")
        source_butt.setToolTipText("Select the application's "
                                   "source directory or file to parse")

        return labels

    def set_url(self, menu_url):
        """Changes the configuration URL to the one from the menu event"""
        self.url.setText(menu_url)

    # Event functions
    def set_parse(self, event):
        """
        Handles the click event from the UI checkbox
        to attempt code level parsing
        """
        self.parse_files = not self.parse_files
        if self.parse_files:
            if not self.loaded_plugins:
                self._plugins_missing_warning()

    def restore(self, event):
        """Attempts to restore the previously saved configuration."""
        jdump = None
        try:
            jdump = loads(self._callbacks.loadExtensionSetting("config"))
        except Exception as exc:  # Generic exception thrown directly to user
            self.update_scroll(
                "[!!] Error during restore!\n\tException: %s" % str(exc))
        if jdump is not None:
            self.url.setText(jdump.get('URL'))
            # self.cookies.setText(jdump.get('Cookies'))
            # self.headers.setText(jdump.get("Headers"))
            ewl = ""
            for ext in jdump.get('Extension Whitelist'):
                ewl += ext + ", "
            self.ext_white_list.setText(ewl[:-2])
            self.delim.setText(jdump.get('String Delimiter'))
            self.source_input = jdump.get("Input Directory")
            self.config['Plugin Folder'] = jdump.get("Plugin Folder")
            if (self.config['Plugin Folder'] is not None and
                    (len(self.plugins.values()) < 1)):
                self._load_plugins(self.config['Plugin Folder'])
            self._update()
            self.update_scroll("[^] Restore complete!")
        else:
            self.update_scroll("[!!] Restore failed!")

    def save(self, event=None):
        """
        Saves the configuration details to a Burp Suite's persistent store.
        """
        self._update()
        try:
            if not self._callbacks.isInScope(URL(self.url.getText())):
                self.update_scroll("[!!] URL provided is NOT in Burp Scope!")
        except MalformedURLException:  # If url field is blank we'll
            pass                       # still save the settings.

        try:
            self._callbacks.saveExtensionSetting("config", dumps(self.config))
            self.update_scroll("[^] Settings saved!")
        except Exception:
            self.update_scroll("[!!] Error saving settings to Burp Suite!")

    def parse(self, event):
        """
        Handles the click event from the UI.
        Attempts to parse the given directory
            (and/or source files) for url endpoints
        Saves the items found within the url_reqs list
        """
        self._update()

        file_set = set()
        fcount = 0
        other_dirs = set()
        self.ext_stats = {}
        if self.loaded_plugins:
            self.update_scroll("[^] Attempting to parse files" +
                               " for URL patterns. This might take a minute.")
        if path.isdir(self.source_input):
            for dirname, _, filenames in walk(self.source_input):
                for filename in filenames:
                    fcount += 1
                    ext = path.splitext(filename)[1]
                    count = self.ext_stats.get(ext, 0) + 1
                    filename = "%s/%s" % (dirname, filename)
                    self.ext_stats.update({ext: count})
                    if self.parse_files:
                        # i can haz threading?
                        file_set.update(self._code_as_endpoints(filename, ext))
                    elif self._ext_test(ext):
                        r_files, oths = self._files_as_endpoints(filename, ext)
                        file_set.update(r_files)
                        other_dirs.update(oths)
        elif path.isfile(self.source_input):
            ext = path.splitext(self.source_input)[1]
            file_set.update(self._code_as_endpoints(self.source_input, ext))
        else:
            self.update_scroll("[!!] Input Directory is not valid!")
        if len(other_dirs) > 0:
            self.update_scroll("[*] Found files matching file extension in:\n")
            for other_dir in other_dirs:
                self.update_scroll(" " * 4 + "%s\n" % other_dir)
        for item in file_set:
            if item.startswith("http://") or item.startswith("https://"):
                proto = item.split("//")[0] + '//'
                item = item.replace(proto, "")
            self.url_reqs.append(proto + item.replace('//', '/'))
        self._print_parsed_status(fcount)
        return (other_dirs, self.url_reqs)

    def scan(self, event):
        """
        handles the click event from the UI.
        Adds the given URL to the burp scope and sends the requests
        to the burp spider
        """
        temp_url = self.url.getText()
        if not self._callbacks.isInScope(URL(temp_url)):
            if not self.double_click:
                self.update_scroll("[!!] URL is not in scope! Press Send to "
                                   "Spider again to add to scope and scan!")
                self.double_click = True
                return
            else:
                self._callbacks.sendToSpider(URL(temp_url))
        self.update_scroll(
            "[^] Sending %d requests to Spider" % len(self.url_reqs))
        for req in self.url_reqs:
            self._callbacks.sendToSpider(URL(req))

    def clear(self, event):
        """Clears the viewport and the current parse exts"""
        self.view_port_text.setText("===SpyDir===")
        self.ext_stats = {}

    def print_endpoints(self, event):
        """Prints the discovered endpoints to the status window."""
        req_str = ""
        if len(self.url_reqs) > 0:
            self.update_scroll("[*] Printing all discovered endpoints:")
            for req in self.url_reqs:
                req_str += "    %s\n" % req
        else:
            req_str = "[!!] No endpoints discovered"
        self.update_scroll(req_str)

    def set_show_stats(self, event):
        """Modifies the show stats setting"""
        self.print_stats = not self.print_stats

    def get_source_input(self, event):
        """Sets the source dir/file for parsing"""
        source_chooser = JFileChooser()
        source_chooser.setFileSelectionMode(
            JFileChooser.FILES_AND_DIRECTORIES)
        source_chooser.showDialog(self.tab, "Choose Source Location")
        chosen_source = source_chooser.getSelectedFile()
        try:
            self.source_input = chosen_source.getAbsolutePath()
        except AttributeError:
            pass
        if self.source_input is not None:
            self.update_scroll("[*] Source location: %s" % self.source_input)
            self.curr_conf.setText(self.source_input)

    # Plugin functions
    def _parse_file(self, filename, file_url):
        """
        Attempts to parse a file with the loaded plugins
        Returns set of endpoints
        """
        file_set = set()
        with open(filename, 'r') as plug_in:
            lines = plug_in.readlines()
        ext = path.splitext(filename)[1].upper()
        if ext in self.plugins.keys():
            for plug in self.plugins.get(ext):
                if plug.enabled:
                    res = plug.run(lines)
                    if len(res) > 0:
                        for i in res:
                            i = file_url + i
                            file_set.add(i)
        elif ext == '.TXT' and self._ext_test(ext):
            for i in lines:
                i = file_url + i
                file_set.add(i.strip())
        return file_set

    def set_plugin_loc(self, event):
        """Attempts to load plugins from a specified location"""
        if self.config['Plugin Folder'] is not None:
            choose_plugin_location = JFileChooser(self.config['Plugin Folder'])
        else:
            choose_plugin_location = JFileChooser()
        choose_plugin_location.setFileSelectionMode(
            JFileChooser.DIRECTORIES_ONLY)
        choose_plugin_location.showDialog(self.tab, "Choose Folder")
        chosen_folder = choose_plugin_location.getSelectedFile()
        self.config['Plugin Folder'] = chosen_folder.getAbsolutePath()
        self._load_plugins(self.config['Plugin Folder'])

    def _load_plugins(self, folder):
        """
        Parses a local directory to get the plugins
            related to code level scanning
        """
        report = ""
        if len(self.plugins.keys()) > 0:
            report = "[^] Plugins reloaded!"
        for _, _, filenames in walk(folder):
            for p_name in filenames:
                n_e = path.splitext(p_name)  # n_e = name_extension
                if n_e[1] == ".py":
                    f_loc = "%s/%s" % (folder, p_name)
                    loaded_plug = self._validate_plugin(n_e[0], f_loc)
                    if loaded_plug:
                        self.loaded_p_list.add(loaded_plug)
                        if not report.startswith("[^]"):
                            report += "%s loaded\n" % loaded_plug.get_name()

        self._dictify(self.loaded_p_list)
        if len(self.plugins.keys()) > 0:
            self.loaded_plugins = True
        else:
            report = "[!!] Plugins load failure"
            self.loaded_plugins = False
        self.update_scroll(report)
        return report

    def _validate_plugin(self, p_name, f_loc):
        """
        Attempts to verify the manditory plugin functions to prevent broken
        plugins from loading.
        Generates an error message if plugin does not contain an appropriate
        function.
        """
        # Load the plugin
        try:
            plug = load_source(p_name, f_loc)
        except Exception as exc:  # this needs to be generic.
            self.update_scroll(
                "[!!] Error loading: %s\n\tType:%s Error: %s"
                % (f_loc, type(exc), str(exc)))
        # Verify the plugin's functions
        funcs = dir(plug)
        err = []
        if "get_name" not in funcs:
            err.append("get_name()")
        if "get_ext" not in funcs:
            err.append("get_ext()")
        if "run" not in funcs:
            err.append("run()")

        # Report errors & return
        if len(err) < 1:
            return Plugin(plug, True)
        else:
            for issue in err:
                self.update_scroll("[!!] %s is missing: %s func" %
                                   (p_name, issue))
            return None

    def _dictify(self, plist):
        """Converts the list of loaded plugins (plist) into a dictionary"""
        for p in plist:
            exts = p.get_ext().upper()
            for ext in exts.split(","):
                prev_load = self.plugins.get(ext, [])
                prev_load.append(p)
                self.plugins[ext] = prev_load

    # Status window functions
    def _print_parsed_status(self, fcount):
        """Prints the parsed directory status information"""
        if self.parse_files and not self.loaded_plugins:
            self._plugins_missing_warning()
        if len(self.url_reqs) > 0:
            self.update_scroll("[*] Example URL: %s" % self.url_reqs[0])

        if self.print_stats:
            report = (("[*] Found: %r files to be requested.\n\n" +
                       "[*] Stats: \n    " +
                       "Found: %r files.\n") % (len(self.url_reqs), fcount))
            if len(self.ext_stats) > 0:
                report += ("[*] Extensions found: %s"
                           % str(dumps(self.ext_stats,
                                       sort_keys=True, indent=4)))
        else:
            report = ("[*] Found: %r files to be requested.\n" %
                      len(self.url_reqs))
        self.update_scroll(report)
        return report

    def _plugins_missing_warning(self):
        """Prints a warning message"""
        self.update_scroll("[!!] No plugins loaded!")

    def update_scroll(self, text):
        """Updates the view_port_text with the new information"""
        temp = self.view_port_text.getText().strip()
        if text not in temp or text[0:4] == "[!!]":
            self.view_port_text.setText("%s\n%s" % (temp, text))
        elif not temp.endswith("[^] Status unchanged"):
            self.view_port_text.setText("%s\n[^] Status unchanged" % temp)

    # Internal functions
    def _code_as_endpoints(self, filename, ext):
        file_set = set()
        file_url = self.config.get("URL")
        if self.loaded_plugins:
            if self._ext_test(ext):
                file_set.update(
                    self._parse_file(filename, file_url))
            else:
                file_set.update(
                    self._parse_file(filename, file_url))
        return file_set

    def _files_as_endpoints(self, filename, ext):
        """Generates endpoints via files with the appropriate extension(s)"""
        file_url = self.config.get("URL")
        broken_splt = ""
        other_dirs = set()  # directories outside of the String Delim.
        file_set = set()
        str_del = self.config.get("String Delimiter")
        if not str_del:
            self.update_scroll("[!!] No available String Delimiter!")
            return
        spl_str = filename.split(str_del)

        try:
            # Fix for index out of bounds exception while parsing
            # subfolders _not_ included by the split
            if len(spl_str) > 1:
                file_url += ((spl_str[1])
                             .replace('\\', '/'))
            else:
                broken_splt = filename.split(self.source_input)[1]
                other_dirs.add(broken_splt)
        except Exception as exc:  # Generic exception thrown directly to user
            self.update_scroll("[!!] Error parsing: " +
                               "%s\n\tException: %s"
                               % (filename, str(exc)))
        if self._ext_test(ext):
            if file_url != self.config.get("URL"):
                file_set.add(file_url)
        else:
            other_dirs.discard(broken_splt)
        return file_set, other_dirs

    def _ext_test(self, ext):
        """Litmus test for extension whitelist"""
        val = False
        if len(self.config.get("Extension Whitelist")) > 0:
            val = (len(ext) > 0 and
                   (ext.strip().upper()
                    in self.config.get("Extension Whitelist")))
        elif "*" in self.config.get("Extension Whitelist"):
            val = True
        return val

    def _update(self):
        """Updates internal data"""
        self.config["Input Directory"] = self.source_input
        self.config["String Delimiter"] = self.delim.getText()

        white_list_text = self.ext_white_list.getText()
        self.config["Extension Whitelist"] = white_list_text.upper().split(',')
        file_url = self.url.getText()
        if not file_url.endswith('/') and file_url != "":
            file_url += '/'

        self.config["URL"] = file_url
        # self.config["Cookies"] = self.cookies.getText()
        # self.config["Headers"] = self.headers.getText()
        del self.url_reqs[:]
        self.curr_conf.setText(self.source_input)

    # Window sizing functions
    def resize(self, event):
        """Resizes the window to better fit Burp"""
        if self.parent_window is not None:
            par_size = self.parent_window.getSize()
            par_size.setSize(par_size.getWidth() * .99,
                             par_size.getHeight() * .9)
            self.tab.setPreferredSize(par_size)
            self.parent_window.validate()
            self.parent_window.switch_focus()

    def p_close(self, event):
        """
        Handles the window close event.
        """
        self.window.setVisible(False)
        self.window.dispose()

    def p_build_ui(self, event):
        """
        Adds a list of checkboxes, one for each loaded plugin
        to the Selct plugins window
        """
        if not self.loaded_p_list:
            self.update_scroll("[!!] No plugins loaded!")
            return

        scroll_pane = JScrollPane()
        scroll_pane.setPreferredSize(Dimension(200, 250))
        check_frame = JPanel(GridBagLayout())
        constraints = GridBagConstraints()
        constraints.fill = GridBagConstraints.HORIZONTAL
        constraints.gridy = 0
        constraints.anchor = GridBagConstraints.FIRST_LINE_START

        for plug in self.loaded_p_list:
            check_frame.add(JCheckBox(plug.get_name(), plug.enabled,
                                      actionPerformed=self.update_box),
                            constraints)
            constraints.gridy += 1

        vport = JViewport()
        vport.setView(check_frame)
        scroll_pane.setViewport(vport)
        self.window.contentPane.add(scroll_pane)
        self.window.pack()
        self.window.setVisible(True)

    def update_box(self, event):
        """
        Handles the check/uncheck event for the plugin's box.
        """
        for plug in self.loaded_p_list:
            if plug.get_name() == event.getActionCommand():
                plug.enabled = not plug.enabled
                if plug.enabled:
                    self.update_scroll("[^] Enabled: %s" %
                                       event.getActionCommand())
                else:
                    self.update_scroll("[^] Disabled: %s" %
                                       event.getActionCommand())

    # ITab required functions
    @staticmethod
    def getTabCaption():
        """Returns the name of the Burp Suite Tab"""
        return "SpyDir"

    def getUiComponent(self):
        """Returns the UI component for the Burp Suite tab"""
        return self.tab
예제 #14
0
파일: test.py 프로젝트: Azyl/WorkHelper
class WorkHelper(JFrame):

    def __init__(self):
        super(WorkHelper, self).__init__()

        self.clipboard = Toolkit.getDefaultToolkit().getSystemClipboard()
        #self.initUI()

    #def initUI(self):

        #panel = JPanel()
        #self.getContentPane().add(panel)
        
#############################################################
# Layout
        layout = GroupLayout(self.getContentPane())
        self.getContentPane().setLayout(layout)
        layout.setAutoCreateGaps(True)
        layout.setAutoCreateContainerGaps(True)
#############################################################

#############################################################
# Scroll Area Input + Output
        Larea1 = JLabel("InputArea:")
        Larea2 = JLabel("OutputArea:")
        
        Sarea1 = JScrollPane()
        Sarea2 = JScrollPane()
        
        self.area1 = JTextArea()
        self.area1.setToolTipText("Input Area")
        self.area1.setEditable(True)
        self.area1.setBorder(BorderFactory.createLineBorder(Color.gray))
        
        Sarea1.setPreferredSize(Dimension(300,100))
        Sarea1.getViewport().setView((self.area1))
        
        self.area2 = JTextArea()
        self.area2.setToolTipText("Output Area")
        self.area2.setEditable(False)
        self.area2.setBorder(BorderFactory.createLineBorder(Color.gray))
        
        Sarea2.setPreferredSize(Dimension(300,100))
        Sarea2.getViewport().setView((self.area2))
#############################################################

#############################################################
# Buttons

        self.cCurly = JCheckBox("Curly");
        self.cCurly.setToolTipText("When 'Checked' Curly Brackets will surround the Categories")
        self.cCurly.setSelected(1)
        

        self.cCtClipB = JCheckBox("Auto-Copy");
        self.cCtClipB.setToolTipText("When 'Checked' after the Categories are created they will added to the clipboard")
        self.cCtClipB.setSelected(1)

        self.cSemiC = JCheckBox("SemiColumn");
        self.cSemiC.setToolTipText("When 'Checked' after the Categories are created at the end will be a semicolomn")
        self.cSemiC.setSelected(1)        
        
        bRemoveNBSP_L = JButton("Clean LText", actionPerformed=self.bRemoveNBSP_L)
        bRemoveNBSP_L.setToolTipText("Removes Spaces, Tabs from the start of every text line from the input Area")
        bRemoveNBSP_R = JButton("Clean RText", actionPerformed=self.bRemoveNBSP_R)
        bRemoveNBSP_R.setToolTipText("Removes Spaces, Tabs from the end of every text line from the input Area")
        bCopyToInput = JButton("Copy to Input", actionPerformed=self.bCopyToInput)
        bCopyToInput.setToolTipText("Copy the text from the Output Area to the Input Area for further Operations")
        
        bClear = JButton("Clear", actionPerformed=self.bClear)
        bClear.setToolTipText("Clears the text form both Input and Output text Areas")
        
        self.iStart = JTextField(maximumSize=Dimension(40,25))
        self.iStart.setToolTipText("The Start Index for the Making of the Categories")
        
        self.RThis = JTextField()
        self.RThis = JTextField(maximumSize=Dimension(120,25))
        self.RThis.setToolTipText("Text to be replaced or The Starting C_Index")
        
        self.RThat = JTextField()
        self.RThat = JTextField(maximumSize=Dimension(120,25))
        self.RThat.setToolTipText("Text to be placed or The Finish C_Index")
        
        
        bSandReplace = JButton("Replace Text", actionPerformed=self.bSandReplace)
        bSandReplace.setToolTipText("Replace the text from This with Thext from That in the Text from the Input Area and displays it in the Output Area")
        
        bcCat = JButton("CreatCateg", actionPerformed=self.bcCat)
        bcCat.setToolTipText("Create a categorical form starting C_Index to finish C_Index; Use the above text boxes to define the indexes")
        
        
        bC_S = JButton("Create _Series", actionPerformed=self.bC_S)
        bC_S.setToolTipText("Create a series form starting C_Index to finish C_Index; Use the above text boxes to define the indexes; It will create a series for every row in the Input Area")

        
        
        bM_Categories = JButton("Categories", actionPerformed=self.mCategories)
        bM_Categories.setToolTipText("Make Categories using the lines from the Input Area")
        #bM_Categories = JButton(maximumSize=Dimension(40,25))
        # de incercat daca merge cu ; sa grupezi in [dsa] elementele
#############################################################


#############################################################
# Aplication Layout 2 groups one Horizontal and one Vertical
        layout.setHorizontalGroup(layout.createSequentialGroup()
            .addGroup(layout.createParallelGroup()
                .addComponent(Larea1)
                .addComponent(Sarea1)

                .addComponent(Sarea2)
                .addComponent(bCopyToInput)
                .addComponent(Larea2))
            .addGroup(layout.createParallelGroup()
            .addGroup(layout.createSequentialGroup()
                .addComponent(bM_Categories)
                .addComponent(self.iStart))
            .addGroup(layout.createSequentialGroup()
                .addComponent(self.cCurly)
                .addComponent(self.cSemiC)
                .addComponent(self.cCtClipB))
            .addGroup(layout.createSequentialGroup()
                .addComponent(bRemoveNBSP_L)
                .addComponent(bRemoveNBSP_R))
            .addGroup(layout.createSequentialGroup()
                .addComponent(self.RThis)
                .addComponent(self.RThat))
            .addGroup(layout.createSequentialGroup()
                .addComponent(bSandReplace)
                .addComponent(bcCat))
            .addGroup(layout.createSequentialGroup()
                .addComponent(bC_S))
                
                .addComponent(bClear))
            
        )

        layout.setVerticalGroup(layout.createSequentialGroup()
            .addComponent(Larea1)
            
            .addGroup(layout.createParallelGroup()
                .addComponent(Sarea1)
                
                .addGroup(layout.createSequentialGroup()
                    .addGroup(layout.createParallelGroup()
                        .addComponent(bM_Categories)
                        .addComponent(self.iStart))
                    .addGroup(layout.createParallelGroup()
                        .addComponent(self.cCurly)
                        .addComponent(self.cSemiC)
                        .addComponent(self.cCtClipB))
                    .addGroup(layout.createParallelGroup()
                        .addComponent(bRemoveNBSP_L)
                        .addComponent(bRemoveNBSP_R))
                    .addGroup(layout.createParallelGroup()
                        .addComponent(self.RThis)
                        .addComponent(self.RThat))
                    .addGroup(layout.createParallelGroup()   
                        .addComponent(bSandReplace)
                        .addComponent(bcCat))
                    .addGroup(layout.createParallelGroup()
                        .addComponent(bC_S))
                        
                        
                        )
                    )
                
            .addGroup(layout.createParallelGroup()
                .addComponent(bCopyToInput)
                .addComponent(bClear))
            .addComponent(Larea2)
            .addGroup(layout.createParallelGroup()
                .addComponent(Sarea2))
        )
        
        #layout.linkSize(SwingConstants.HORIZONTAL, [ok, bCopyToInput, close, bM_Categories])
        layout.linkSize(SwingConstants.HORIZONTAL, [self.RThis,self.RThat,bRemoveNBSP_L,bRemoveNBSP_R,bCopyToInput,bM_Categories,bSandReplace,bcCat,bC_S])
        
        #layout.linkSize(SwingConstants.HORIZONTAL, [self.cCurly,bM_Categories])
#############################################################

#############################################################
# Aplication Settings
        self.pack()
        #self.setPreferredSize(Dimension(1000, 1000))
        self.setTitle("Workhelper")
        self.setSize(800, 500)
        self.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
        self.setLocationRelativeTo(None)
        self.setVisible(True)
#############################################################
        
#############################################################
# WorkHelper class methods:
    def onQuit(self, e):
        "@sig public void setExpression(java.lang.String e)"
        System.exit(0)


# def addToClipBoard(self, text):
# "@sig public void setExpression(java.lang.String text)"
# command = 'echo ' + text.strip() + '| clip'
# os.system(command)
# brute method for pasting into clipboard on windows



        
    def mCategories(self, e):
        "@sig public void setExpression(java.lang.String e)"
        """
Takes every line of text form the Input Area and by using a
string composotion it creates the output in the SPSS dimension
categories format.
"""
        try:
            StartIndex = int(self.iStart.getText())
        except ValueError:
            StartIndex=1




        text=self.area1.getText().rstrip()
        
        
        counter=StartIndex
        lastindex=0
        textO=""
        
        for i in range(0,len(text)):
                if text[i]=='\n':
                        textO=textO+("_"+str(counter)+' "'+text[lastindex:i]+'",\n')
                        lastindex=i+1
                        counter=counter+1

        if len(text[lastindex:len(text)])>0:
                textO=textO+("_"+str(counter)+' "'+text[lastindex:len(text)]+'"')


        if len(textO)>0:
            if self.cCurly.isSelected():
                textO = "{\n"+ textO + "\n}"
                if self.cSemiC.isSelected():
                    textO = textO + ";"
            self.copyToClipboard(textO)    
            self.area2.setText(textO)
    
    def copyToClipboard(self, text):
            if self.cCtClipB.isSelected():
                stringSelection = StringSelection(text)
                self.clipboard.setContents(stringSelection, None)
            
        
        
    def bCopyToInput(self, e):
        "@sig public void setExpression(java.lang.String e)"
        """Copy the Text from the Output Area to the input Area for further operations"""
        
        self.area1.setText(self.area2.getText())
    
    def bRemoveNBSP_L(self, e):
        "@sig public void setExpression(java.lang.String e)"
        text=self.area1.getText().rstrip()
        textO=""
        lastindex=0
        
        for i in range(0,len(text)):
            if text[i] == '\n':
                textO = textO+text[lastindex:i].lstrip()+"\n"
                lastindex=i+1
                #print(text[0:i].lstrip()+'\n')
        if len(text[lastindex:len(text)])>0:
                textO=textO+text[lastindex:len(text)].lstrip()
        self.area2.setText(textO)
    
    def bRemoveNBSP_R(self, e):
        "@sig public void setExpression(java.lang.String e)"
        text=self.area1.getText().rstrip()
        textO=""
        lastindex=0
        
        for i in range(0,len(text)):
            if text[i] == '\n':
                textO = textO+text[lastindex:i].rstrip()+"\n"
                lastindex=i+1
                #print(text[0:i].lstrip()+'\n')
        if len(text[lastindex:len(text)])>0:
                textO=textO+text[lastindex:len(text)].rstrip()
        self.area2.setText(textO)
        
    def bClear(self, e):
        "@sig public void setExpression(java.lang.String e)"
        self.area1.setText("")
        self.area2.setText("")
    
    def bcCat(self, e):
        "@sig public void setExpression(java.lang.String e)"
        try:
            StartIndex = int(self.RThis.getText())
        except ValueError:
            StartIndex=1
        
        try:
            FinishIndex = int(self.RThat.getText())
        except ValueError:
            FinishIndex=1
        cCats=""
        for i in range(StartIndex,FinishIndex+1):
            if i<>FinishIndex:
                cCats=cCats+"_"+str(i)+","
            else:
                cCats=cCats+"_"+str(i)
            
        if StartIndex<FinishIndex:
            cCats="{"+cCats+"}"
            self.copyToClipboard(cCats)
            self.area2.setText(cCats)
        
    def bSandReplace(self, e):
        self.area2.setText(self.area1.getText().replace(self.RThis.getText(),self.RThat.getText()))
        
    def bC_S(self, e):
        "@sig public void setExpression(java.lang.String e)"
        try:
            StartIndex = int(self.RThis.getText())
        except ValueError:
            StartIndex=1
        
        try:
            FinishIndex = int(self.RThat.getText())
        except ValueError:
            FinishIndex=1
        
        if StartIndex<FinishIndex:
            text=self.area1.getText().rstrip()
            lastindex=0
            textO=""
            
            for i in range(0,len(text)):
                    if text[i]=='\n':
                        counter=StartIndex
                        for j in range(StartIndex,FinishIndex+1):
                            textO=textO+(text[lastindex:i]+"_"+str(counter)+" ")
                            counter=counter+1
                        lastindex=i+1
                        textO=textO+'\n'

            #if len(text[lastindex:len(text)])>0:
            #        textO=textO+("_"+str(counter)+' "'+text[lastindex:len(text)]+'"')

            if lastindex==0 and len(text)>0:
                counter=StartIndex
                for j in range(StartIndex,FinishIndex+1):
                    textO=textO+(text[lastindex:i]+"_"+str(counter)+" ")
                    counter=counter+1
            
            if len(textO)>0:
                self.copyToClipboard(textO)    
                self.area2.setText(textO)
예제 #15
0
class BurpExtender(IBurpExtender, ITab, IScannerCheck, IContextMenuFactory,
                   IParameter, IIntruderPayloadGeneratorFactory):
    def registerExtenderCallbacks(self, callbacks):
        self.callbacks = callbacks
        self.helpers = callbacks.getHelpers()
        callbacks.setExtensionName("Session Authentication Tool")
        self.out = callbacks.getStdout()

        # definition of suite tab
        self.tab = JPanel(GridBagLayout())
        self.tabledata = MappingTableModel(callbacks)
        self.table = JTable(self.tabledata)
        #self.table.getColumnModel().getColumn(0).setPreferredWidth(50);
        #self.table.getColumnModel().getColumn(1).setPreferredWidth(100);
        self.tablecont = JScrollPane(self.table)
        c = GridBagConstraints()
        c.fill = GridBagConstraints.HORIZONTAL
        c.anchor = GridBagConstraints.FIRST_LINE_START
        c.gridx = 0
        c.gridy = 0
        c.gridheight = 6
        c.weightx = 0.3
        c.weighty = 0.5
        self.tab.add(self.tablecont, c)

        c = GridBagConstraints()
        c.weightx = 0.1
        c.anchor = GridBagConstraints.FIRST_LINE_START
        c.gridx = 1

        c.gridy = 0
        label_id = JLabel("Identifier:")
        self.tab.add(label_id, c)
        self.input_id = JTextField(20)
        self.input_id.setToolTipText(
            "Enter the identifier which is used by the application to identifiy a particular test user account, e.g. a numerical user id or a user name."
        )
        c.gridy = 1
        self.tab.add(self.input_id, c)

        c.gridy = 2
        label_content = JLabel("Content:")
        self.tab.add(label_content, c)
        self.input_content = JTextField(20, actionPerformed=self.btn_add_id)
        self.input_content.setToolTipText(
            "Enter some content which is displayed in responses of the application and shows that the current session belongs to a particular user, e.g. the full name of the user."
        )
        c.gridy = 3
        self.tab.add(self.input_content, c)

        self.btn_add = JButton("Add/Edit Identity",
                               actionPerformed=self.btn_add_id)
        c.gridy = 4
        self.tab.add(self.btn_add, c)

        self.btn_del = JButton("Delete Identity",
                               actionPerformed=self.btn_del_id)
        c.gridy = 5
        self.tab.add(self.btn_del, c)

        callbacks.customizeUiComponent(self.tab)
        callbacks.customizeUiComponent(self.table)
        callbacks.customizeUiComponent(self.tablecont)
        callbacks.customizeUiComponent(self.btn_add)
        callbacks.customizeUiComponent(self.btn_del)
        callbacks.customizeUiComponent(label_id)
        callbacks.customizeUiComponent(self.input_id)
        callbacks.addSuiteTab(self)
        callbacks.registerScannerCheck(self)
        callbacks.registerIntruderPayloadGeneratorFactory(self)
        callbacks.registerContextMenuFactory(self)

    def btn_add_id(self, e):
        ident = self.input_id.text
        self.input_id.text = ""
        content = self.input_content.text
        self.input_content.text = ""
        self.tabledata.add_mapping(ident, content)
        self.input_id.requestFocusInWindow()

    def btn_del_id(self, e):
        rows = self.table.getSelectedRows().tolist()
        self.tabledata.del_rows(rows)

    ### ITab ###
    def getTabCaption(self):
        return ("SessionAuth")

    def getUiComponent(self):
        return self.tab

    ### IContextMenuFactory ###
    def createMenuItems(self, invocation):
        menuitems = list()
        msgs = invocation.getSelectedMessages()
        if msgs != None:
            if len(
                    msgs
            ) == 1:  # "add as object id/as content to last id" context menu items
                bounds = invocation.getSelectionBounds()
                if bounds != None and bounds[0] != bounds[1]:
                    msg = None
                    if invocation.getInvocationContext(
                    ) == IContextMenuInvocation.CONTEXT_MESSAGE_EDITOR_REQUEST or invocation.getInvocationContext(
                    ) == IContextMenuInvocation.CONTEXT_MESSAGE_VIEWER_REQUEST:
                        msg = msgs[0].getRequest().tostring()
                    if invocation.getInvocationContext(
                    ) == IContextMenuInvocation.CONTEXT_MESSAGE_EDITOR_RESPONSE or invocation.getInvocationContext(
                    ) == IContextMenuInvocation.CONTEXT_MESSAGE_VIEWER_RESPONSE:
                        msg = msgs[0].getResponse().tostring()
                    if msg != None:
                        selection = msg[bounds[0]:bounds[1]]
                        shortSelection = selection[:20]
                        if len(selection) > len(shortSelection):
                            shortSelection += "..."
                        menuitems.append(
                            JMenuItem("Add '" + shortSelection +
                                      "' as object id",
                                      actionPerformed=self.gen_menu_add_id(
                                          selection)))
                        if self.tabledata.lastadded != None:
                            menuitems.append(
                                JMenuItem(
                                    "Add '" + shortSelection +
                                    "' as content to last added id",
                                    actionPerformed=self.gen_menu_add_content(
                                        selection)))
            if len(msgs) > 0:  # "Send to Intruder" context menu items
                requestsWithIds = list()
                for msg in msgs:
                    if isinstance(msg.getRequest(),
                                  array) and self.tabledata.containsId(
                                      msg.getRequest().tostring()):
                        requestsWithIds.append(msg)
                if len(requestsWithIds) > 0:
                    menuitems.append(
                        JMenuItem(
                            "Send to Intruder and preconfigure id injection points",
                            actionPerformed=self.gen_menu_send_intruder(
                                requestsWithIds)))

        return menuitems

    def gen_menu_add_id(self, ident):
        def menu_add_id(e):
            self.tabledata.add_mapping(ident, "")

        return menu_add_id

    def gen_menu_add_content(self, content):
        def menu_add_content(e):
            self.tabledata.set_lastadded_content(content)

        return menu_add_content

    def gen_menu_send_intruder(self, requestResponses):
        def menu_send_intruder(e):
            for requestResponse in requestResponses:
                httpService = requestResponse.getHttpService()
                request = requestResponse.getRequest()
                injectionPoints = list()
                for ident in self.tabledata.getIds():
                    newInjectionPoints = findAll(request.tostring(), ident)
                    if newInjectionPoints != None:
                        injectionPoints += newInjectionPoints
                if len(injectionPoints) > 0:
                    self.callbacks.sendToIntruder(
                        httpService.getHost(), httpService.getPort(),
                        httpService.getProtocol() == "https", request,
                        injectionPoints)

        return menu_send_intruder

    ### IIntruderPayloadGeneratorFactory ###
    def getGeneratorName(self):
        return "SessionAuth Identifiers"

    def createNewInstance(self, attack):
        return IdentifiersPayloadGenerator(self.tabledata)

    ### IScannerCheck ###
    def doPassiveScan(self, baseRequestResponse):
        analyzedRequest = self.helpers.analyzeRequest(baseRequestResponse)
        params = analyzedRequest.getParameters()
        ids = self.tabledata.getIds()
        issues = list()

        for param in params:
            value = param.getValue()
            for ident in ids:
                if value == ident:
                    issues.append(
                        SessionAuthPassiveScanIssue(
                            analyzedRequest.getUrl(), baseRequestResponse,
                            param, ident, self.tabledata.getValue(ident),
                            SessionAuthPassiveScanIssue.foundEqual,
                            self.callbacks))
                elif value.find(ident) >= 0:
                    issues.append(
                        SessionAuthPassiveScanIssue(
                            analyzedRequest.getUrl(), baseRequestResponse,
                            param, ident, self.tabledata.getValue(ident),
                            SessionAuthPassiveScanIssue.foundInside,
                            self.callbacks))
        if len(issues) > 0:
            return issues
        else:
            return None

    def doActiveScan(self, baseRequestResponse, insertionPoint):
        ids = self.tabledata.getIds()
        if len(ids
               ) <= 1:  # active check only possible if multiple ids were given
            return None
        baseVal = insertionPoint.getBaseValue()
        url = baseRequestResponse.getUrl()

        idFound = list()
        for ident in ids:  # find all identifiers in base value
            if baseVal.find(ident) >= 0:
                idFound.append(ident)
        if len(idFound) == 0:  # no given identifier found, nothing to do
            return None

        baseResponse = baseRequestResponse.getResponse().tostring()
        baseResponseBody = baseResponse[
            self.helpers.analyzeResponse(baseResponse).getBodyOffset():]
        issues = list()
        scannedCombos = list()
        for replaceId in idFound:  # scanner checks: replace found id by other given ids
            for scanId in ids:
                if replaceId == scanId or set([replaceId, scanId
                                               ]) in scannedCombos:
                    continue
                scannedCombos.append(set([replaceId, scanId]))

                scanPayload = baseVal.replace(replaceId, scanId)
                scanRequest = insertionPoint.buildRequest(scanPayload)
                scanRequestResponse = self.callbacks.makeHttpRequest(
                    baseRequestResponse.getHttpService(), scanRequest)
                scanResponse = scanRequestResponse.getResponse().tostring()
                scanResponseBody = scanResponse[self.helpers.analyzeResponse(
                    scanResponse).getBodyOffset():]

                if baseResponseBody == scanResponseBody:  # response hasn't changed - no issue
                    continue

                # Analyze responses
                replaceValue = self.tabledata.getValue(replaceId)
                scanValue = self.tabledata.getValue(scanId)
                # naming convention:
                # first word: base || scan (response)
                # second word: Replace || Scan (value)
                if replaceValue != "":
                    baseReplaceValueCount = len(
                        baseResponseBody.split(replaceValue)) - 1
                    scanReplaceValueCount = len(
                        scanResponseBody.split(replaceValue)) - 1
                else:
                    baseReplaceValueCount = 0
                    scanReplaceValueCount = 0

                if scanValue != "":
                    baseScanValueCount = len(
                        baseResponseBody.split(scanValue)) - 1
                    scanScanValueCount = len(
                        scanResponseBody.split(scanValue)) - 1
                else:
                    baseScanValueCount = 0
                    scanScanValueCount = 0

                if scanScanValueCount == 0:
                    # Scan identifier content value doesn't appears, but responses differ
                    issueCase = SessionAuthActiveScanIssue.caseScanValueNotFound
                elif baseReplaceValueCount > 0 and baseScanValueCount == 0 and scanReplaceValueCount == 0 and scanScanValueCount == baseReplaceValueCount:
                    # Scan identifier replaces all occurrences of the original identifier in the response
                    issueCase = SessionAuthActiveScanIssue.caseScanValueAppearsExactly
                elif baseReplaceValueCount > 0 and baseScanValueCount == 0 and scanReplaceValueCount == 0 and scanScanValueCount > 0:
                    # Scan identfiers value appears, replaced ids value disappears
                    issueCase = SessionAuthActiveScanIssue.caseScanValueAppearsFuzzy
                elif baseReplaceValueCount > scanReplaceValueCount and baseScanValueCount < scanScanValueCount:
                    # Occurence count of replaced id value decreases, scan id value increases
                    issueCase = SessionAuthActiveScanIssue.caseDecreaseIncrease
                elif baseScanValueCount < scanScanValueCount:
                    # Occurence count of scan id value increases
                    issueCase = SessionAuthActiveScanIssue.caseScanValueIncrease
                else:
                    # Remainingg cases
                    issueCase = SessionAuthActiveScanIssue.caseOther

                issues.append(
                    SessionAuthActiveScanIssue(url, baseRequestResponse,
                                               insertionPoint, scanPayload,
                                               scanRequestResponse, replaceId,
                                               replaceValue, scanId, scanValue,
                                               issueCase, self.callbacks))

        if len(issues) > 0:
            return issues
        else:
            return None

    def consolidateDuplicateIssues(self, existingIssue, newIssue):
        if existingIssue.getIssueDetail() == newIssue.getIssueDetail():
            return 1
        else:
            return 0
예제 #16
0
class PreferencesFrame(JFrame, ActionListener, WindowListener, ItemListener,
                       HyperlinkListener):
    """Dialog with preferences
    """
    def __init__(self, parent, title, app):
        from javax.swing import JCheckBox, JRadioButton, ButtonGroup
        self.app = app
        border = BorderFactory.createEmptyBorder(5, 7, 5, 7)
        self.getContentPane().setBorder(border)
        self.getContentPane().setLayout(BorderLayout(0, 5))
        self.tabbedPane = JTabbedPane()

        #1 Tab: general
        panel1 = JPanel()
        panel1.setBorder(BorderFactory.createEmptyBorder(7, 7, 7, 7))
        panel1.setLayout(BoxLayout(panel1, BoxLayout.PAGE_AXIS))

        #Checkbutton to enable/disable update check when script starts
        self.updateCBtn = JCheckBox(self.app.strings.getString("updateCBtn"))
        self.updateCBtn.setToolTipText(
            self.app.strings.getString("updateCBtn_tooltip"))

        #Download tools
        downloadBtn = JButton(self.app.strings.getString("updatesBtn"),
                              ImageProvider.get("dialogs", "refresh"),
                              actionPerformed=self.on_downloadBtn_clicked)
        downloadBtn.setToolTipText(
            self.app.strings.getString("updatesBtn_tooltip"))

        #Checkbuttons for enabling/disabling tools
        toolsPanel = JPanel(BorderLayout(0, 5))
        title = self.app.strings.getString("enable_disable_tools")
        toolsPanel.setBorder(BorderFactory.createTitledBorder(title))
        infoLbl = JLabel(self.app.strings.getString("JOSM_restart_warning"))
        infoLbl.setFont(infoLbl.getFont().deriveFont(Font.ITALIC))
        toolsPanel.add(infoLbl, BorderLayout.PAGE_START)

        toolsStatusPane = JPanel(GridLayout(len(self.app.realTools), 0))
        self.toolsCBtns = []
        for tool in self.app.realTools:
            toolCBtn = JCheckBox()
            toolCBtn.addItemListener(self)
            toolLbl = JLabel(tool.title, tool.bigIcon, JLabel.LEFT)
            self.toolsCBtns.append(toolCBtn)

            toolPane = JPanel()
            toolPane.setLayout(BoxLayout(toolPane, BoxLayout.X_AXIS))
            toolPane.add(toolCBtn)
            toolPane.add(toolLbl)
            toolsStatusPane.add(toolPane)
        toolsPanel.add(toolsStatusPane, BorderLayout.CENTER)

        #Radiobuttons for enabling/disabling layers when a new one
        #is added
        layersPanel = JPanel(GridLayout(0, 1))
        title = self.app.strings.getString("errors_layers_manager")
        layersPanel.setBorder(BorderFactory.createTitledBorder(title))
        errorLayersLbl = JLabel(
            self.app.strings.getString("errors_layers_info"))
        errorLayersLbl.setFont(errorLayersLbl.getFont().deriveFont(
            Font.ITALIC))
        layersPanel.add(errorLayersLbl)
        self.layersRBtns = {}
        group = ButtonGroup()
        for mode in self.app.layersModes:
            layerRBtn = JRadioButton(self.app.strings.getString("%s" % mode))
            group.add(layerRBtn)
            layersPanel.add(layerRBtn)
            self.layersRBtns[mode] = layerRBtn

        #Max number of errors text field
        self.maxErrorsNumberTextField = JTextField()
        self.maxErrorsNumberTextField.setToolTipText(
            self.app.strings.getString("maxErrorsNumberTextField_tooltip"))
        self.maxErrorsNumberTFieldDefaultBorder = self.maxErrorsNumberTextField.getBorder(
        )
        self.maxErrorsNumberTextField.getDocument().addDocumentListener(
            ErrNumTextListener(self))

        #layout
        self.updateCBtn.setAlignmentX(Component.LEFT_ALIGNMENT)
        panel1.add(self.updateCBtn)
        panel1.add(Box.createRigidArea(Dimension(0, 15)))
        downloadBtn.setAlignmentX(Component.LEFT_ALIGNMENT)
        panel1.add(downloadBtn)
        panel1.add(Box.createRigidArea(Dimension(0, 15)))
        toolsPanel.setAlignmentX(Component.LEFT_ALIGNMENT)
        panel1.add(toolsPanel)
        panel1.add(Box.createRigidArea(Dimension(0, 15)))
        layersPanel.setAlignmentX(Component.LEFT_ALIGNMENT)
        panel1.add(layersPanel)
        panel1.add(Box.createRigidArea(Dimension(0, 15)))
        maxErrP = JPanel(BorderLayout(5, 0))
        maxErrP.add(JLabel(self.app.strings.getString("max_errors_number")),
                    BorderLayout.LINE_START)
        maxErrP.add(self.maxErrorsNumberTextField, BorderLayout.CENTER)
        p = JPanel(BorderLayout())
        p.add(maxErrP, BorderLayout.PAGE_START)
        p.setAlignmentX(Component.LEFT_ALIGNMENT)
        panel1.add(p)

        self.tabbedPane.addTab(self.app.strings.getString("tab_1_title"), None,
                               panel1, None)

        #2 Tab: favourite zones
        panel2 = JPanel(BorderLayout(5, 15))
        panel2.setBorder(BorderFactory.createEmptyBorder(7, 7, 7, 7))

        #status
        topPanel = JPanel()
        topPanel.setLayout(BoxLayout(topPanel, BoxLayout.Y_AXIS))
        infoPanel = HtmlPanel(self.app.strings.getString("fav_zones_info"))
        infoPanel.getEditorPane().addHyperlinkListener(self)
        infoPanel.setAlignmentX(Component.LEFT_ALIGNMENT)
        self.favZoneStatusCBtn = JCheckBox(
            self.app.strings.getString("activate_fav_area"),
            actionListener=self)
        self.favZoneStatusCBtn.setToolTipText(
            self.app.strings.getString("activate_fav_area_tooltip"))
        self.favZoneStatusCBtn.setAlignmentX(Component.LEFT_ALIGNMENT)
        topPanel.add(infoPanel)
        topPanel.add(Box.createRigidArea(Dimension(0, 10)))
        topPanel.add(self.favZoneStatusCBtn)
        #table
        self.zonesTable = JTable()
        tableSelectionModel = self.zonesTable.getSelectionModel()
        tableSelectionModel.addListSelectionListener(ZonesTableListener(self))
        columns = [
            "",
            self.app.strings.getString("Type"),
            self.app.strings.getString("Name")
        ]
        tableModel = ZonesTableModel([], columns)
        self.zonesTable.setModel(tableModel)
        self.scrollPane = JScrollPane(self.zonesTable)
        #map
        self.zonesMap = JMapViewer()
        self.zonesMap.setZoomContolsVisible(False)
        self.zonesMap.setMinimumSize(Dimension(100, 200))

        #buttons
        self.removeBtn = JButton(self.app.strings.getString("Remove"),
                                 ImageProvider.get("dialogs", "delete"),
                                 actionPerformed=self.on_removeBtn_clicked)
        self.removeBtn.setToolTipText(
            self.app.strings.getString("remove_tooltip"))
        newBtn = JButton(self.app.strings.getString("New"),
                         ImageProvider.get("dialogs", "add"),
                         actionPerformed=self.on_newBtn_clicked)
        newBtn.setToolTipText(self.app.strings.getString("new_tooltip"))

        #layout
        panel2.add(topPanel, BorderLayout.PAGE_START)
        panel2.add(self.scrollPane, BorderLayout.LINE_START)
        panel2.add(self.zonesMap, BorderLayout.CENTER)
        self.buttonsPanel = JPanel()
        self.buttonsPanel.add(self.removeBtn)
        self.buttonsPanel.add(newBtn)
        panel2.add(self.buttonsPanel, BorderLayout.PAGE_END)

        self.tabbedPane.addTab(self.app.strings.getString("tab_2_title"), None,
                               panel2, None)

        #3 Tab Tools options
        panel3 = JPanel()
        panel3.setLayout(BoxLayout(panel3, BoxLayout.Y_AXIS))
        panel3.setBorder(BorderFactory.createEmptyBorder(7, 7, 7, 7))
        for tool in self.app.realTools:
            if hasattr(tool, 'prefs'):
                p = JPanel(FlowLayout(FlowLayout.LEFT))
                p.setBorder(BorderFactory.createTitledBorder(tool.title))
                p.add(tool.prefsGui)
                panel3.add(p)

        self.tabbedPane.addTab(self.app.strings.getString("tab_3_title"), None,
                               panel3, None)

        self.add(self.tabbedPane, BorderLayout.CENTER)

        exitPanel = JPanel()
        saveBtn = JButton(self.app.strings.getString("OK"),
                          ImageProvider.get("ok"),
                          actionPerformed=self.on_saveBtn_clicked)
        cancelBtn = JButton(self.app.strings.getString("cancel"),
                            ImageProvider.get("cancel"),
                            actionPerformed=self.on_cancelBtn_clicked)
        saveBtn.setToolTipText(self.app.strings.getString("save_preferences"))
        saveBtn.setAlignmentX(0.5)
        exitPanel.add(saveBtn)
        exitPanel.add(cancelBtn)
        self.add(exitPanel, BorderLayout.PAGE_END)

        self.addWindowListener(self)
        self.pack()

    def windowClosing(self, windowEvent):
        self.on_cancelBtn_clicked()

    def hyperlinkUpdate(self, e):
        if e.getEventType() == HyperlinkEvent.EventType.ACTIVATED:
            OpenBrowser.displayUrl(e.getURL().toString())

    def itemStateChanged(self, e):
        """A ttol has been activated/deactivated.
           Check if at least one tool is on.
        """
        if all(not button.isSelected() for button in self.toolsCBtns):
            JOptionPane.showMessageDialog(
                Main.parent,
                self.app.strings.getString("tools_disabled_warning"),
                self.app.strings.getString("tools_disabled_warning_title"),
                JOptionPane.WARNING_MESSAGE)
            source = e.getItemSelectable()
            source.setSelected(True)

    def actionPerformed(self, e=None):
        """Enable/disable favourite zones panel
        """
        for container in (self.scrollPane, self.buttonsPanel):
            self.enableComponents(container,
                                  self.favZoneStatusCBtn.isSelected())
        if self.favZoneStatusCBtn.isSelected():
            self.check_removeBtn_status()

    def enableComponents(self, container, enable):
        components = container.getComponents()
        for component in components:
            component.setEnabled(enable)
            if isinstance(component, Container):
                self.enableComponents(component, enable)

    def on_downloadBtn_clicked(self, e):
        update_checker.Updater(self.app, "manual")

    def clean_map(self):
        """Remove all rectangles and polygons from the map
        """
        self.zonesMap.removeAllMapRectangles()
        self.zonesMap.removeAllMapPolygons()

    def update_gui_from_preferences(self):
        """Update gui status of preferences frame from config file
        """
        #print "\n- updating Preferences gui"
        onOff = {"on": True, "off": False}
        #1 Tab
        #check for update
        self.updateCBtn.setSelected(onOff[self.app.checkUpdate])

        #tools status, enabled or not
        for toolIndex, tool in enumerate(self.app.realTools):
            if "tool.%s" % tool.name in self.app.properties.keys():
                configstatus = self.app.properties.getProperty("tool.%s" %
                                                               tool.name)
            else:
                configstatus = "on"  # new tool
            self.toolsCBtns[toolIndex].setSelected(onOff[configstatus])

        #layers preferences
        for mode, button in self.layersRBtns.iteritems():
            button.setSelected(mode == self.app.layersMode)

        #max errors number
        self.maxErrorsNumberTextField.setText(str(self.app.maxErrorsNumber))

        #stats panel
        self.app.dlg.update_favourite_zone_indicator()

        #2 Tab
        #favourite area
        self.update_favourite_area_gui_from_preferences()
        self.app.dlg.update_statsPanel_status()

        #3 Tab
        #tools preferences
        for tool in self.app.allTools:
            if hasattr(tool, 'prefs') and tool.prefsGui is not None:
                tool.prefsGui.update_gui(tool.prefs)

    def update_favourite_area_gui_from_preferences(self):
        #status
        self.favZoneStatusCBtn.setSelected(self.app.favouriteZoneStatus)
        #table
        #store zones to a temporary list, used to store changes
        #and save them when preferences dialog is closed
        self.app.tempZones = list(self.app.zones)
        self.zonesTable.getModel().setNumRows(0)
        for zone in self.app.tempZones:
            self.zonesTable.getModel().addRow(
                [zone.country, zone.icon, zone.name])
        if self.app.favZone is not None:
            selectedRow = self.app.tempZones.index(self.app.favZone)
            self.zonesTable.setRowSelectionInterval(selectedRow, selectedRow)
        self.zonesTable.getColumnModel().getColumn(0).setMaxWidth(30)
        self.zonesTable.getColumnModel().getColumn(1).setMaxWidth(50)
        #enable or disable favourite zone buttons
        self.actionPerformed()

### fav area editing buttons ###########################################

    def on_removeBtn_clicked(self, e):
        rowsNum = self.zonesTable.getSelectedRows()
        rowsNum.reverse()
        for rowNum in rowsNum:
            del self.app.tempZones[rowNum]
            self.zonesTable.getModel().removeRow(rowNum)
        if len(self.app.tempZones) != 0:
            if rowNum == 0:
                self.zonesTable.setRowSelectionInterval(0, 0)
            else:
                self.zonesTable.setRowSelectionInterval(rowNum - 1, rowNum - 1)
        self.check_removeBtn_status()

    def check_removeBtn_status(self):
        if self.app.tempZones != [] and len(
                self.zonesTable.getSelectedRows()) != 0:
            self.removeBtn.setEnabled(True)
        else:
            self.removeBtn.setEnabled(False)
            self.clean_map()

    def on_newBtn_clicked(self, e):
        try:
            self.newZoneDialog
        except AttributeError:
            self.newZoneDialog = NewZoneDialog(self.app)
        bbox = self.app.get_frame_bounds()
        self.app.newZone = Zone(self.app,
                                self.app.strings.getString("New_zone"),
                                "rectangle",
                                ",".join(["%0.4f" % x for x in bbox]), "")
        self.newZoneDialog.update_gui_from_preferences()
        self.newZoneDialog.show()

### Exit from preferences ##############################################

    def on_cancelBtn_clicked(self, event=None):
        if hasattr(self, "newZoneDialog") and self.newZoneDialog.isVisible():
            self.newZoneDialog.close_dialog()
        self.dispose()

    def on_saveBtn_clicked(self, event):
        """Read preferences from gui and save them to config.properties
           file
        """
        #print "\n- saving preferences to config file"
        onOff = {True: "on", False: "off"}

        #1 Tab
        #check for update
        self.app.properties.setProperty("check_for_update",
                                        onOff[self.updateCBtn.isSelected()])
        #tools status
        for toolIndex, tool in enumerate(self.app.realTools):
            prop = "tool.%s" % tool.name
            toolCBtn = self.toolsCBtns[toolIndex]
            self.app.properties.setProperty(prop, onOff[toolCBtn.isSelected()])

        #layers preferences
        for mode, button in self.layersRBtns.iteritems():
            if button.isSelected():
                self.app.properties.setProperty("layers_mode", mode)
                break

        #max errors number
        try:
            num = Integer.parseInt(self.maxErrorsNumberTextField.getText())
        except NumberFormatException:
            num = ""
        self.app.properties.setProperty("max_errors_number", str(num))

        #2 Tab
        #Favourite zones
        changes = {
            "new": [z for z in self.app.tempZones if not z in self.app.zones],
            "deleted":
            [z for z in self.app.zones if not z in self.app.tempZones]
        }
        #delete files of removed favourite zones
        for zone in changes["deleted"]:
            f = File(
                File.separator.join([
                    self.app.SCRIPTDIR, "configuration", "favourite_zones",
                    "%s.txt" % zone.name
                ]))
            f.delete()
        #create files for new favourite zones
        for zone in changes["new"]:
            print "\nsave new zone", zone.name
            fileName = File.separator.join([
                self.app.SCRIPTDIR, "configuration", "favourite_zones",
                "%s.txt" % zone.name
            ])
            f = open(fileName, "w")
            zoneData = zone.geomString
            if zone.country != "":
                zoneData += "|" + zone.country
            f.write(zoneData.encode("utf-8"))
            f.close()

        self.app.zones = self.app.tempZones
        if len(self.app.zones) == 0:
            self.app.favZone = None
            self.app.properties.setProperty("favourite_area.name", "")
            self.favZoneStatusCBtn.setSelected(False)
        else:
            if len(self.zonesTable.getSelectedRows()) == 0:
                self.app.favZone = self.app.zones[0]
            else:
                self.app.favZone = self.app.zones[
                    self.zonesTable.getSelectedRows()[0]]
            self.app.properties.setProperty("favourite_area.name",
                                            self.app.favZone.name)
        favZoneStatus = self.favZoneStatusCBtn.isSelected()
        self.app.properties.setProperty("favourite_area.status",
                                        onOff[favZoneStatus])
        self.app.favouriteZoneStatus = favZoneStatus

        #stats panel
        self.app.dlg.update_favourite_zone_indicator()
        self.app.dlg.update_statsPanel_status()

        #3 Tab
        #tools preferences
        for tool in self.app.allTools:
            if hasattr(tool, 'prefs') and tool.prefsGui is not None:
                for pref, value in tool.prefsGui.read_gui().iteritems():
                    prefKey = "tool.%s.%s" % (tool.name, pref)
                    self.app.properties.setProperty(prefKey, value)

        self.app.save_config()
        self.dispose()
예제 #17
0
class NewZoneDialog(JDialog, ActionListener, WindowListener):
    """Dialog for favourite zone editing
    """
    def __init__(self, parent, title, modal, app):
        from java.awt import CardLayout
        self.app = app
        border = BorderFactory.createEmptyBorder(5, 7, 7, 7)
        self.getContentPane().setBorder(border)
        self.setLayout(BoxLayout(self.getContentPane(), BoxLayout.Y_AXIS))

        self.FAVAREALAYERNAME = "Favourite zone editing"

        info = JLabel(self.app.strings.getString("Create_a_new_favourite_zone"))
        info.setAlignmentX(Component.LEFT_ALIGNMENT)

        #Name
        nameLbl = JLabel(self.app.strings.getString("fav_zone_name"))
        self.nameTextField = JTextField(20)
        self.nameTextField.setMaximumSize(self.nameTextField.getPreferredSize())
        self.nameTextField.setToolTipText(self.app.strings.getString("fav_zone_name_tooltip"))
        namePanel = JPanel()
        namePanel.setLayout(BoxLayout(namePanel, BoxLayout.X_AXIS))
        namePanel.add(nameLbl)
        namePanel.add(Box.createHorizontalGlue())
        namePanel.add(self.nameTextField)

        #Country
        countryLbl = JLabel(self.app.strings.getString("fav_zone_country"))
        self.countryTextField = JTextField(20)
        self.countryTextField.setMaximumSize(self.countryTextField.getPreferredSize())
        self.countryTextField.setToolTipText(self.app.strings.getString("fav_zone_country_tooltip"))
        countryPanel = JPanel()
        countryPanel.setLayout(BoxLayout(countryPanel, BoxLayout.X_AXIS))
        countryPanel.add(countryLbl)
        countryPanel.add(Box.createHorizontalGlue())
        countryPanel.add(self.countryTextField)

        #Type
        modeLbl = JLabel(self.app.strings.getString("fav_zone_type"))
        RECTPANEL = "rectangle"
        POLYGONPANEL = "polygon"
        BOUNDARYPANEL = "boundary"
        self.modesStrings = [RECTPANEL, POLYGONPANEL, BOUNDARYPANEL]
        modesComboModel = DefaultComboBoxModel()
        for i in (self.app.strings.getString("rectangle"),
                  self.app.strings.getString("delimited_by_a_closed_way"),
                  self.app.strings.getString("delimited_by_an_administrative_boundary")):
            modesComboModel.addElement(i)
        self.modesComboBox = JComboBox(modesComboModel,
                                       actionListener=self,
                                       editable=False)

        #- Rectangle
        self.rectPanel = JPanel()
        self.rectPanel.setLayout(BoxLayout(self.rectPanel, BoxLayout.Y_AXIS))

        capturePane = JPanel()
        capturePane.setLayout(BoxLayout(capturePane, BoxLayout.X_AXIS))
        capturePane.setAlignmentX(Component.LEFT_ALIGNMENT)

        josmP = JPanel()
        self.captureRBtn = JRadioButton(self.app.strings.getString("capture_area"))
        self.captureRBtn.addActionListener(self)
        self.captureRBtn.setSelected(True)
        self.bboxFromJosmBtn = JButton(self.app.strings.getString("get_current_area"),
                                       actionPerformed=self.on_bboxFromJosmBtn_clicked)
        self.bboxFromJosmBtn.setToolTipText(self.app.strings.getString("get_capture_area_tooltip"))
        josmP.add(self.bboxFromJosmBtn)
        capturePane.add(self.captureRBtn)
        capturePane.add(Box.createHorizontalGlue())
        capturePane.add(self.bboxFromJosmBtn)

        manualPane = JPanel()
        manualPane.setLayout(BoxLayout(manualPane, BoxLayout.X_AXIS))
        manualPane.setAlignmentX(Component.LEFT_ALIGNMENT)
        self.manualRBtn = JRadioButton(self.app.strings.getString("use_this_bbox"))
        self.manualRBtn.addActionListener(self)
        self.bboxTextField = JTextField(20)
        self.bboxTextField.setMaximumSize(self.bboxTextField.getPreferredSize())
        self.bboxTextField.setToolTipText(self.app.strings.getString("fav_bbox_tooltip"))
        self.bboxTextFieldDefaultBorder = self.bboxTextField.getBorder()
        self.bboxTextField.getDocument().addDocumentListener(TextListener(self))
        manualPane.add(self.manualRBtn)
        manualPane.add(Box.createHorizontalGlue())
        manualPane.add(self.bboxTextField)

        group = ButtonGroup()
        group.add(self.captureRBtn)
        group.add(self.manualRBtn)

        previewPane = JPanel()
        previewPane.setLayout(BoxLayout(previewPane, BoxLayout.X_AXIS))
        previewPane.setAlignmentX(Component.LEFT_ALIGNMENT)
        bboxPreviewInfo = JTextField(self.app.strings.getString("coordinates"),
                                     editable=0,
                                     border=None)
        bboxPreviewInfo.setMaximumSize(bboxPreviewInfo.getPreferredSize())
        self.bboxPreviewTextField = JTextField(20,
                                               editable=0,
                                               border=None)
        self.bboxPreviewTextField.setMaximumSize(self.bboxPreviewTextField.getPreferredSize())
        previewPane.add(bboxPreviewInfo)
        previewPane.add(Box.createHorizontalGlue())
        previewPane.add(self.bboxPreviewTextField)

        self.rectPanel.add(capturePane)
        self.rectPanel.add(Box.createRigidArea(Dimension(0, 10)))
        self.rectPanel.add(manualPane)
        self.rectPanel.add(Box.createRigidArea(Dimension(0, 20)))
        self.rectPanel.add(previewPane)

        #- Polygon (closed way) drawn by hand
        self.polygonPanel = JPanel(BorderLayout())
        self.polygonPanel.setLayout(BoxLayout(self.polygonPanel, BoxLayout.Y_AXIS))

        polyInfo = JLabel("<html>%s</html>" % self.app.strings.getString("polygon_info"))
        polyInfo.setFont(polyInfo.getFont().deriveFont(Font.ITALIC))
        polyInfo.setAlignmentX(Component.LEFT_ALIGNMENT)

        editPolyPane = JPanel()
        editPolyPane.setAlignmentX(Component.LEFT_ALIGNMENT)
        editPolyBtn = JButton(self.app.strings.getString("create_fav_layer"),
                              actionPerformed=self.create_new_zone_editing_layer)
        editPolyBtn.setToolTipText(self.app.strings.getString("create_fav_layer_tooltip"))
        editPolyPane.add(editPolyBtn)

        self.polygonPanel.add(polyInfo)
        self.polygonPanel.add(Box.createRigidArea(Dimension(0, 15)))
        self.polygonPanel.add(editPolyPane)
        self.polygonPanel.add(Box.createRigidArea(Dimension(0, 15)))

        #- Administrative Boundary
        self.boundaryPanel = JPanel()
        self.boundaryPanel.setLayout(BoxLayout(self.boundaryPanel, BoxLayout.Y_AXIS))

        boundaryInfo = JLabel("<html>%s</html>" % app.strings.getString("boundary_info"))
        boundaryInfo.setFont(boundaryInfo.getFont().deriveFont(Font.ITALIC))
        boundaryInfo.setAlignmentX(Component.LEFT_ALIGNMENT)

        boundaryTagsPanel = JPanel(GridLayout(3, 3, 5, 5))
        boundaryTagsPanel.setAlignmentX(Component.LEFT_ALIGNMENT)
        boundaryTagsPanel.add(JLabel("name ="))
        self.nameTagTextField = JTextField(20)
        boundaryTagsPanel.add(self.nameTagTextField)
        boundaryTagsPanel.add(JLabel("admin_level ="))
        self.adminLevelTagTextField = JTextField(20)
        self.adminLevelTagTextField.setToolTipText(self.app.strings.getString("adminLevel_tooltip"))
        boundaryTagsPanel.add(self.adminLevelTagTextField)
        boundaryTagsPanel.add(JLabel(self.app.strings.getString("other_tag")))
        self.optionalTagTextField = JTextField(20)
        self.optionalTagTextField.setToolTipText("key=value")
        boundaryTagsPanel.add(self.optionalTagTextField)

        downloadBoundariesPane = JPanel()
        downloadBoundariesPane.setAlignmentX(Component.LEFT_ALIGNMENT)
        downloadBoundariesBtn = JButton(self.app.strings.getString("download_boundary"),
                                        actionPerformed=self.on_downloadBoundariesBtn_clicked)
        downloadBoundariesBtn.setToolTipText(self.app.strings.getString("download_boundary_tooltip"))
        downloadBoundariesPane.add(downloadBoundariesBtn)

        self.boundaryPanel.add(boundaryInfo)
        self.boundaryPanel.add(Box.createRigidArea(Dimension(0, 15)))
        self.boundaryPanel.add(boundaryTagsPanel)
        self.boundaryPanel.add(Box.createRigidArea(Dimension(0, 10)))
        self.boundaryPanel.add(downloadBoundariesPane)

        self.editingPanels = {"rectangle": self.rectPanel,
                              "polygon": self.polygonPanel,
                              "boundary": self.boundaryPanel}

        #Main buttons
        self.okBtn = JButton(self.app.strings.getString("OK"),
                             ImageProvider.get("ok"),
                             actionPerformed=self.on_okBtn_clicked)
        self.cancelBtn = JButton(self.app.strings.getString("cancel"),
                                 ImageProvider.get("cancel"),
                                 actionPerformed=self.close_dialog)
        self.previewBtn = JButton(self.app.strings.getString("Preview_zone"),
                                  actionPerformed=self.on_previewBtn_clicked)
        self.previewBtn.setToolTipText(self.app.strings.getString("preview_zone_tooltip"))
        okBtnSize = self.okBtn.getPreferredSize()
        viewBtnSize = self.previewBtn.getPreferredSize()
        viewBtnSize.height = okBtnSize.height
        self.previewBtn.setPreferredSize(viewBtnSize)

        #layout
        self.add(info)
        self.add(Box.createRigidArea(Dimension(0, 15)))

        namePanel.setAlignmentX(Component.LEFT_ALIGNMENT)
        self.add(namePanel)
        self.add(Box.createRigidArea(Dimension(0, 15)))

        countryPanel.setAlignmentX(Component.LEFT_ALIGNMENT)
        self.add(countryPanel)
        self.add(Box.createRigidArea(Dimension(0, 15)))

        modeLbl.setAlignmentX(Component.LEFT_ALIGNMENT)
        self.add(modeLbl)
        self.add(Box.createRigidArea(Dimension(0, 5)))

        self.add(self.modesComboBox)
        self.modesComboBox.setAlignmentX(Component.LEFT_ALIGNMENT)
        self.add(Box.createRigidArea(Dimension(0, 15)))

        self.configPanel = JPanel(CardLayout())
        self.configPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5))
        self.configPanel.add(self.rectPanel, RECTPANEL)
        self.configPanel.add(self.polygonPanel, POLYGONPANEL)
        self.configPanel.add(self.boundaryPanel, BOUNDARYPANEL)
        self.configPanel.setAlignmentX(Component.LEFT_ALIGNMENT)
        self.add(self.configPanel)
        buttonsPanel = JPanel()
        buttonsPanel.add(self.okBtn)
        buttonsPanel.add(self.cancelBtn)
        buttonsPanel.add(self.previewBtn)
        buttonsPanel.setAlignmentX(Component.LEFT_ALIGNMENT)
        self.add(buttonsPanel)

        self.addWindowListener(self)
        self.pack()

    def update_gui_from_preferences(self):
        self.nameTextField.setText(self.app.newZone.name)
        #Reset rectangle mode
        bboxStr = ",".join(["%0.4f" % x for x in self.app.newZone.bbox])
        self.bboxTextField.setText(bboxStr)
        self.bboxPreviewTextField.setText(bboxStr)
        self.bboxFromJosmBtn.setEnabled(True)
        self.bboxTextField.setEnabled(False)

        #Reset polygon mode
        self.polygonAsString = ""

        #Reset boundary mode
        self.boundaryAsString = ""

        self.modesComboBox.setSelectedIndex(0)

    def actionPerformed(self, e):
        #Show the panel for configuring the favourite area of the
        #selected type
        if e.getSource() == self.modesComboBox:
            cl = self.configPanel.getLayout()
            selectedMode = self.modesStrings[self.modesComboBox.selectedIndex]
            cl.show(self.configPanel, selectedMode)
        #Activate bbox input for rectangular favourite zone mode
        elif e.getSource() == self.captureRBtn:
            self.bboxFromJosmBtn.setEnabled(True)
            self.bboxTextField.setEnabled(False)
        else:
            self.bboxFromJosmBtn.setEnabled(False)
            self.bboxTextField.setEnabled(True)

    def on_bboxFromJosmBtn_clicked(self, widget):
        """Read bbox currently shown in JOSM
        """
        bbox = self.app.get_frame_bounds()
        self.bboxPreviewTextField.setText(",".join(["%0.4f" % x for x in bbox]))

### Manage layer for creating a new favourite zone from polygon or boundary
    def create_new_zone_editing_layer(self, e=None):
        """Open a new dataset where the user can draw a closed way to
           delimit the favourite area
        """
        layer = self.get_new_zone_editing_layer()
        if layer is not None:
            self.app.mv.setActiveLayer(layer)
        else:
            Main.main.addLayer(OsmDataLayer(DataSet(), self.FAVAREALAYERNAME, None))
        Main.main.parent.toFront()

    def get_new_zone_editing_layer(self):
        """Check if the layer for editing the favourite area yet exists
        """
        for layer in self.app.mv.getAllLayers():
            if layer.getName() == self.FAVAREALAYERNAME:
                return layer
        return None

    def remove_new_zone_editing_layer(self):
        layer = self.get_new_zone_editing_layer()
        if layer is not None:
            self.app.mv.removeLayer(layer)

    def on_zone_edited(self):
        """Read ways that delimit the favourite area and convert them to
           jts geometry
        """
        if self.modesComboBox.getSelectedIndex() == 0:
            mode = "rectangle"
        elif self.modesComboBox.getSelectedIndex() == 1:
            mode = "polygon"
        elif self.modesComboBox.getSelectedIndex() == 2:
            mode = "boundary"

        if mode in ("polygon", "boundary"):
            layer = self.get_new_zone_editing_layer()
            if layer is not None:
                self.app.mv.setActiveLayer(layer)
            else:
                if mode == "polygon":
                    msg = self.app.strings.getString("polygon_fav_layer_missing_msg")
                else:
                    msg = self.app.strings.getString("boundary_fav_layer_missing_msg")
                JOptionPane.showMessageDialog(self,
                                              msg,
                                              self.app.strings.getString("Warning"),
                                              JOptionPane.WARNING_MESSAGE)
                return

            dataset = self.app.mv.editLayer.data
            areaWKT = self.read_area_from_osm_ways(mode, dataset)
            if areaWKT is None:
                print "I could not read the new favourite area."
            else:
                if mode == "polygon":
                    self.polygonAsString = areaWKT
                else:
                    self.boundaryAsString = areaWKT
        return mode

    def read_area_from_osm_ways(self, mode, dataset):
        """Read way in favourite area editing layer and convert them to
           WKT
        """
        converter = JTSConverter(False)
        lines = [converter.convert(way) for way in dataset.ways]
        polygonizer = Polygonizer()
        polygonizer.add(lines)
        polygons = polygonizer.getPolygons()
        multipolygon = GeometryFactory().createMultiPolygon(list(polygons))
        multipolygonWKT = WKTWriter().write(multipolygon)
        if multipolygonWKT == "MULTIPOLYGON EMPTY":
            if mode == "polygon":
                msg = self.app.strings.getString("empty_ways_polygon_msg")
            else:
                msg = self.app.strings.getString("empty_ways_boundaries_msg")
            JOptionPane.showMessageDialog(self,
                msg,
                self.app.strings.getString("Warning"),
                JOptionPane.WARNING_MESSAGE)
            return
        return multipolygonWKT

    def on_downloadBoundariesBtn_clicked(self, e):
        """Download puter ways of administrative boundaries from
           Overpass API
        """
        adminLevel = self.adminLevelTagTextField.getText()
        name = self.nameTagTextField.getText()
        optional = self.optionalTagTextField.getText()
        if (adminLevel, name, optional) == ("", "", ""):
            JOptionPane.showMessageDialog(self,
                                          self.app.strings.getString("enter_a_tag_msg"),
                                          self.app.strings.getString("Warning"),
                                          JOptionPane.WARNING_MESSAGE)
            return
        optTag = ""
        if optional.find("=") != -1:
            if len(optional.split("=")) == 2:
                key, value = optional.split("=")
                optTag = '["%s"="%s"]' % (URLEncoder.encode(key, "UTF-8"),
                                          URLEncoder.encode(value.replace(" ", "%20"), "UTF-8"))
        self.create_new_zone_editing_layer()
        overpassurl = 'http://127.0.0.1:8111/import?url='
        overpassurl += 'http://overpass-api.de/api/interpreter?data='
        overpassquery = 'relation["admin_level"="%s"]' % adminLevel
        overpassquery += '["name"="%s"]' % URLEncoder.encode(name, "UTF-8")
        overpassquery += '%s;(way(r:"outer");node(w););out meta;' % optTag
        overpassurl += overpassquery.replace(" ", "%20")
        print overpassurl
        self.app.send_to_josm(overpassurl)

### Buttons ############################################################
    def create_new_zone(self, mode):
        """Read data entered on gui and create a new zone
        """
        name = self.nameTextField.getText()
        country = self.countryTextField.getText().upper()

        #error: name
        if name.replace(" ", "") == "":
            JOptionPane.showMessageDialog(self,
                                          self.app.strings.getString("missing_name_warning"),
                                          self.app.strings.getString("missing_name_warning_title"),
                                          JOptionPane.WARNING_MESSAGE)
            return False
        if name in [z.name for z in self.app.tempZones]:
            JOptionPane.showMessageDialog(self,
                                          self.app.strings.getString("duplicate_name_warning"),
                                          self.app.strings.getString("duplicate_name_warning_title"),
                                          JOptionPane.WARNING_MESSAGE)
            return False

        #zone type
        zType = mode
        #error: geometry type not defined
        if zType == "polygon" and self.polygonAsString == ""\
            or zType == "boundary" and self.boundaryAsString == "":
            JOptionPane.showMessageDialog(self,
                                          self.app.strings.getString("zone_not_correctly_build_warning"),
                                          self.app.strings.getString("zone_not_correctly_build_warning_title"),
                                          JOptionPane.WARNING_MESSAGE)
            return False

        #geometry string
        if zType == "rectangle":
            geomString = self.bboxPreviewTextField.getText()
        elif zType == "polygon":
            geomString = self.polygonAsString
        else:
            geomString = self.boundaryAsString

        self.app.newZone = Zone(self.app, name, zType, geomString, country)
        #self.app.newZone.print_info()
        return True

    def on_okBtn_clicked(self, event):
        """Add new zone to temp zones
        """
        mode = self.on_zone_edited()
        if self.create_new_zone(mode):
            self.app.tempZones.append(self.app.newZone)
            self.app.preferencesFrame.zonesTable.getModel().addRow([self.app.newZone.country,
                                                                    self.app.newZone.icon,
                                                                    self.app.newZone.name])
            maxIndex = len(self.app.tempZones) - 1
            self.app.preferencesFrame.zonesTable.setRowSelectionInterval(maxIndex,
                                                                         maxIndex)
            self.close_dialog()
            self.app.preferencesFrame.check_removeBtn_status()
            self.app.preferencesFrame.zonesTable.scrollRectToVisible(
                self.app.preferencesFrame.zonesTable.getCellRect(
                    self.app.preferencesFrame.zonesTable.getRowCount() - 1, 0, True))

    def on_previewBtn_clicked(self, e):
        """Show the favourite area on a map
        """
        mode = self.on_zone_edited()
        if not self.create_new_zone(mode):
            return
        zone = self.app.newZone

        if zone.zType == "rectangle":
            wktString = zone.bbox_to_wkt_string()
        else:
            wktString = zone.wktGeom
        script = '/*http://stackoverflow.com/questions/11954401/wkt-and-openlayers*/'
        script += '\nfunction init() {'
        script += '\n    var map = new OpenLayers.Map({'
        script += '\n        div: "map",'
        script += '\n        projection: new OpenLayers.Projection("EPSG:900913"),'
        script += '\n        displayProjection: new OpenLayers.Projection("EPSG:4326"),'
        script += '\n        layers: ['
        script += '\n            new OpenLayers.Layer.OSM()'
        script += '\n            ]'
        script += '\n    });'
        script += '\n    var wkt = new OpenLayers.Format.WKT();'
        script += '\n    var polygonFeature = wkt.read("%s");' % wktString
        script += '\n    var vectors = new OpenLayers.Layer.Vector("Favourite area");'
        script += '\n    map.addLayer(vectors);'
        script += '\n    polygonFeature.geometry.transform(map.displayProjection, map.getProjectionObject());'
        script += '\n    vectors.addFeatures([polygonFeature]);'
        script += '\n    map.zoomToExtent(vectors.getDataExtent());'
        script += '\n};'
        scriptFile = open(File.separator.join([self.app.SCRIPTDIR,
                                              "html",
                                              "script.js"]), "w")
        scriptFile.write(script)
        scriptFile.close()
        OpenBrowser.displayUrl(File.separator.join([self.app.SCRIPTDIR,
                                                   "html",
                                                   "favourite_area.html"]))

    def windowClosing(self, windowEvent):
        self.close_dialog()

    def close_dialog(self, e=None):
        #delete favourite zone editing layer if present
        self.remove_new_zone_editing_layer()
        self.dispose()
        self.app.preferencesFrame.setEnabled(True)
        self.app.preferencesFrame.toFront()
예제 #18
0
class BurpExtender(IBurpExtender, ITab):
    socket_time_out = 3

    def registerExtenderCallbacks(self, callbacks):
        self.out = callbacks.getStdout()

        self.callbacks = callbacks
        self.helpers = callbacks.getHelpers()
        callbacks.setExtensionName("WhatsApp Decoder")

        self.banner = JLabel("WHATSAPP DECRYPTION AND ENCRYPTION EXTENSION BY DIKLA BARDA, ROMAN ZAIKIN", SwingConstants.CENTER)
        self.banner.setFont(Font("Serif", Font.PLAIN, 17))
        self.banner.setBorder(BorderFactory.createLineBorder(Color.BLACK))

        self.statusConn = JLabel("CONNECTION STATUS:  ")
        self.statusConnField = JLabel("NOT CONNECTED")
        self.statusAct = JLabel("ACTION STATUS:      ")
        self.statusActField = JLabel("OK")

        self.ref = JLabel("Ref object:  ")
        self.refField = JTextField("123", 80)
        self.refField.setToolTipText("Copy the Ref from burpsuit WebSocket, make sure that the parameter 'secret' is there and you copy only the 'ref' without the connection and other data, if not logout from your whatsapp web and login again.")

        self.privateKey = JLabel("Private Key:")
        self.privateKeyField = JTextField("123", 80)
        self.privateKeyField.setToolTipText("Copy the private key list from your whatsapp web according to our blog post ")

        self.publicKey = JLabel("Public Key: ")
        self.publicKeyField = JTextField("123", 80)
        self.publicKeyField.setToolTipText("Copy the public key list from your whatsapp web according to our blog post")

        self.statusPanel1 = JPanel()
        self.statusPanel1.add(self.statusConn)
        self.statusPanel1.add(self.statusConnField)

        self.statusPanel2 = JPanel()
        self.statusPanel2.add(self.statusAct)
        self.statusPanel2.add(self.statusActField)

        self.privateKeyPanel = JPanel()
        self.privateKeyPanel.add(self.privateKey)
        self.privateKeyPanel.add(self.privateKeyField)

        self.publicKeyPanel = JPanel()
        self.publicKeyPanel.add(self.publicKey)
        self.publicKeyPanel.add(self.publicKeyField)

        self.refPanel = JPanel()
        self.refPanel.add(self.ref)
        self.refPanel.add(self.refField)

        self.messageField = JTextArea("", 5, 90)
        self.messageField.setLineWrap(True)
        self.messageField.setToolTipText("If you putting in the incoming traffic you can copy it from burp suit, the outgoing is the list from aesCbcEncrypt")

        self.whatsAppMessagesPanel = JPanel()
        self.whatsAppMessagesPanel.add(self.messageField)

        self.btnSave = JButton("Connect", actionPerformed=self.saveConfig)
        self.btnRestore = JButton("Clear", actionPerformed=self.clearConfig)

        self.grpConfig = JPanel()
        self.grpConfig.add(self.btnSave)
        self.grpConfig.add(self.btnRestore)

        self.btnIncoming = JButton("Incoming", actionPerformed=self.performAction)
        self.btnOutgoing = JButton("Outgoing", actionPerformed=self.performAction)

        self.btnEncrypt = JButton("Encrypt", actionPerformed=self.performAction)
        self.btnEncrypt.setEnabled(False)  # Can't send data without a direction

        self.btnDecrypt = JButton("Decrypt", actionPerformed=self.performAction)
        self.btnDecrypt.setEnabled(False)  # Can't send data without a direction

        self.btnCrypt = JPanel()
        self.btnCrypt.add(self.btnIncoming)
        self.btnCrypt.add(self.btnEncrypt)
        self.btnCrypt.add(self.btnDecrypt)
        self.btnCrypt.add(self.btnOutgoing)

        self.tab = JPanel()
        layout = GridBagLayout()
        self.tab.setLayout(layout)

        c = GridBagConstraints()

        c.ipadx = 0
        c.ipady = 0

        c.fill = GridBagConstraints.BOTH
        #c.weightx = 0 # gap between the x items
        #c.weighty = 0 # gap between the y items

        c.anchor = GridBagConstraints.NORTHWEST

        c.gridx = 0
        c.gridy = 0
        self.tab.add(self.banner, c)

        c.gridx = 0
        c.gridy = 1
        self.tab.add(self.refPanel, c)

        c.gridx = 0
        c.gridy = 2
        self.tab.add(self.privateKeyPanel, c)

        c.gridx = 0
        c.gridy = 3
        self.tab.add(self.publicKeyPanel, c)

        c.gridx = 0
        c.gridy = 4
        c.anchor = GridBagConstraints.CENTER
        self.tab.add(self.grpConfig, c)

        c.gridx = 0
        c.gridy = 5
        self.tab.add(self.whatsAppMessagesPanel, c)

        c.gridx = 0
        c.gridy = 6
        self.tab.add(self.btnCrypt, c)

        c.gridx = 0
        c.gridy = 7
        self.tab.add(self.statusPanel1, c)

        c.gridx = 0
        c.gridy = 8
        self.tab.add(self.statusPanel2, c)

        # restore config
        self.restoreConfig()
        callbacks.addSuiteTab(self)

    def performAction(self, e=None):

        self.client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.client.settimeout(self.socket_time_out)

        self.data = self.messageField.getText()

        eventSource = e.getSource()
        eventSource.setEnabled(False)

        # Incoming data
        if eventSource == self.btnIncoming:
            self.direction = "in"
            self.btnOutgoing.setEnabled(True)
            self.btnEncrypt.setEnabled(True)
            self.btnDecrypt.setEnabled(True)

        # Outgoing data
        elif eventSource == self.btnOutgoing:
            self.direction = "out"
            self.btnIncoming.setEnabled(True)
            self.btnEncrypt.setEnabled(True)
            self.btnDecrypt.setEnabled(True)

        # Send
        elif eventSource == self.btnDecrypt:
            self.btnDecrypt.setEnabled(True)
            clientData = json.dumps({"action": "decrypt",
                                     "data": {
                                            "direction": self.direction,
                                            "msg": self.messageField.getText()
                                        }
                                     })

            self.client.sendto(clientData, ("127.0.0.1",2912))
            try:
                serverData, addr = self.client.recvfrom(2048)
                serverData = json.loads(serverData)

                if serverData["status"] == 0:
                    print serverData
                    self.messageField.setText(json.dumps(serverData["data"]))
                    self.statusActField.setForeground(Color.GREEN)
                    self.statusActField.setText("OK")
                else:
                    self.statusActField.setForeground(Color.RED)
                    self.statusActField.setText("Error: {}".format(json.dumps(serverData["data"])))

            except socket.timeout:
                pass

        elif eventSource == self.btnEncrypt:
            self.btnEncrypt.setEnabled(True)
            clientData = json.dumps({"action": "encrypt",
                                     "data": {
                                         "direction": self.direction,
                                         "msg": self.messageField.getText()
                                     }
                                     })

            self.client.sendto(clientData, ("127.0.0.1", 2912))
            try:
                serverData, addr = self.client.recvfrom(2048)
                serverData = json.loads(serverData)
                if serverData["status"] == 0:
                    if isinstance(serverData["data"], list):
                        self.messageField.setText(json.dumps(serverData["data"]))
                    else:
                        self.messageField.setText(serverData["data"])

                    self.statusActField.setForeground(Color.GREEN)
                    self.statusActField.setText("OK")
                else:
                    self.statusActField.setForeground(Color.RED)
                    self.statusActField.setText("Error: {}".format(json.dumps(serverData["data"])))

            except socket.timeout:
                pass

        self.client.close()


    def saveConfig(self, e=None):
        self.client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.client.settimeout(self.socket_time_out)

        config = {
            'ref': self.refField.getText(),
            'private': self.privateKeyField.getText(),
            'public': self.publicKeyField.getText(),
        }

        self.callbacks.saveExtensionSetting("config", pickle.dumps(config))

        try:
            clientData = json.dumps({"action":"init",
                                     "data":{
                                         "ref":json.loads(self.refField.getText()),
                                         "private":self.privateKeyField.getText(),
                                         "public":self.publicKeyField.getText()
                                     }
                                    })

            self.client.sendto(clientData, ("127.0.0.1", 2912))

            serverData, addr = self.client.recvfrom(2048)
            print (serverData)

            self.statusConnField.setText("CONNECTED")
            self.statusActField.setForeground(Color.GREEN)
            self.statusActField.setText("OK")

        except socket.timeout:
            self.statusActField.setForeground(Color.RED)
            self.statusActField.setText("Error: Can't connect to the local server make sure parser.py is running!")
            pass

        except Exception as e:
            self.statusActField.setForeground(Color.RED)
            self.statusActField.setText("Error: make Sure the ref is a correct json!")

        self.client.close()

    def clearConfig(self, e=None):
        self.refField.setText("")
        self.privateKeyField.setText("")
        self.publicKeyField.setText("")
        self.statusConnField.setText("NOT CONNECTED")
        self.statusActField.setText("OK")
        self.messageField.setText("")

    def restoreConfig(self, e=None):
        storedConfig = self.callbacks.loadExtensionSetting("config")
        if storedConfig != None:
            config = pickle.loads(storedConfig)
            self.refField.setText(config["ref"])
            self.privateKeyField.setText(config["private"])
            self.publicKeyField.setText(config["public"])

    def getTabCaption(self):
        return ("WhatsApp Decoder")

    def getUiComponent(self):
        return self.tab
예제 #19
0
class BurpExtender(IBurpExtender, IScannerCheck, IScanIssue, ITab):
    def registerExtenderCallbacks(self, callbacks):
        self.callbacks = callbacks
        self.helpers = callbacks.getHelpers()
        callbacks.setExtensionName("Missing Scanner Checks")
        self.out = callbacks.getStdout()

        # define all checkboxes
        self.cbPassiveChecks = self.defineCheckBox("Passive Scanner Checks")
        self.cbDOMXSS = self.defineCheckBox("DOM XSS", False)
        self.cbDOMXSSSources = self.defineCheckBox("Sources", False)
        self.cbDOMXSSSinks = self.defineCheckBox("Sinks")
        self.cbDOMXSSjQuerySinks = self.defineCheckBox("jQuery Sinks", False)
        self.grpDOMXSSSettings = JPanel()
        self.grpDOMXSSSettings.add(self.cbDOMXSSSources)
        self.grpDOMXSSSettings.add(self.cbDOMXSSSinks)
        self.grpDOMXSSSettings.add(self.cbDOMXSSjQuerySinks)
        self.cbSTS = self.defineCheckBox("Strict Transport Security")
        self.lblSTSMin = JLabel("Minimum acceptable max-age")
        self.inSTSMin = JTextField(
            str(STSMinimum), 9, actionPerformed=self.setSTSMinimum
        )  # TODO: actionPerformed only fires on enter key - focus lost would be better
        self.inSTSMin.setToolTipText(
            "Enter the minimum max-age value which is considered as acceptable. Press return to change setting!"
        )
        self.grpSTSSettings = JPanel()
        self.grpSTSSettings.add(self.lblSTSMin)
        self.grpSTSSettings.add(self.inSTSMin)
        self.cbXCTO = self.defineCheckBox("Content Sniffing")
        self.cbXXP = self.defineCheckBox(
            "Client-side XSS Filter Configuration")
        self.cbRedirToHTTPS = self.defineCheckBox(
            "Redirection from HTTP to HTTPS")
        self.btnSave = JButton("Set as default",
                               actionPerformed=self.saveConfig)
        self.btnRestore = JButton("Restore",
                                  actionPerformed=self.restoreConfig)
        self.grpConfig = JPanel()
        self.grpConfig.add(self.btnSave)
        self.grpConfig.add(self.btnRestore)
        self.restoreConfig()

        # definition of config tab
        self.tab = JPanel()
        layout = GroupLayout(self.tab)
        self.tab.setLayout(layout)
        layout.setAutoCreateGaps(True)
        layout.setAutoCreateContainerGaps(True)
        layout.setHorizontalGroup(layout.createSequentialGroup().addGroup(
            layout.createParallelGroup().addComponent(self.cbPassiveChecks)
        ).addGroup(layout.createParallelGroup().addComponent(
            self.cbDOMXSS).addComponent(self.cbSTS).addComponent(
                self.cbXCTO).addComponent(self.cbXXP).addComponent(
                    self.cbRedirToHTTPS)).addGroup(
                        layout.createParallelGroup().addComponent(
                            self.grpDOMXSSSettings, GroupLayout.PREFERRED_SIZE,
                            GroupLayout.PREFERRED_SIZE,
                            GroupLayout.PREFERRED_SIZE).addComponent(
                                self.grpSTSSettings,
                                GroupLayout.PREFERRED_SIZE,
                                GroupLayout.PREFERRED_SIZE,
                                GroupLayout.PREFERRED_SIZE).addComponent(
                                    self.grpConfig, GroupLayout.PREFERRED_SIZE,
                                    GroupLayout.PREFERRED_SIZE,
                                    GroupLayout.PREFERRED_SIZE)))
        layout.setVerticalGroup(layout.createSequentialGroup().addGroup(
            layout.createParallelGroup().addComponent(
                self.cbPassiveChecks).addComponent(self.cbDOMXSS).addComponent(
                    self.grpDOMXSSSettings, GroupLayout.PREFERRED_SIZE,
                    GroupLayout.PREFERRED_SIZE,
                    GroupLayout.PREFERRED_SIZE)).addGroup(
                        layout.createParallelGroup().addComponent(
                            self.cbSTS).addComponent(
                                self.grpSTSSettings,
                                GroupLayout.PREFERRED_SIZE,
                                GroupLayout.PREFERRED_SIZE,
                                GroupLayout.PREFERRED_SIZE)).addComponent(
                                    self.cbXCTO).addComponent(
                                        self.cbXXP).addComponent(
                                            self.cbRedirToHTTPS).addComponent(
                                                self.grpConfig,
                                                GroupLayout.PREFERRED_SIZE,
                                                GroupLayout.PREFERRED_SIZE,
                                                GroupLayout.PREFERRED_SIZE))

        self.domXSSSourcesRE = re.compile(
            "(location\s*[\[.])|([.\[]\s*[\"']?\s*(arguments|dialogArguments|innerHTML|write(ln)?|open(Dialog)?|showModalDialog|cookie|URL|documentURI|baseURI|referrer|name|opener|parent|top|content|self|frames)\W)|(localStorage|sessionStorage|Database)"
        )
        # NOTE: done some optimizations here, original RE caused too much noise
        # - added leading dot in the first part - original recognized "<a href=..." etc.
        # - removed "value" in first part
        self.domXSSSinksRE = re.compile(
            "(\.(src|href|data|location|code|action)\s*[\"'\]]*\s*\+?\s*=)|((replace|assign|navigate|getResponseHeader|open(Dialog)?|showModalDialog|eval|evaluate|execCommand|execScript|setTimeout|setInterval)\s*[\"'\]]*\s*\()"
        )
        self.domXSSjQuerySinksRE = re.compile(
            "after\(|\.append\(|\.before\(|\.html\(|\.prepend\(|\.replaceWith\(|\.wrap\(|\.wrapAll\(|\$\(|\.globalEval\(|\.add\(|jQUery\(|\$\(|\.parseHTML\("
        )
        self.headerSTSRE = re.compile(
            "^Strict-Transport-Security:.*?max-age=\"?(\d+)\"?",
            re.I)  # TODO: multiple max-age directives cause confusion!
        self.headerXCTORE = re.compile(
            "^X-Content-Type-Options:\s*nosniff\s*$", re.I)
        self.headerXXP = re.compile(
            "^X-XSS-Protection:\s*(\d)(?:\s*;\s*mode\s*=\s*\"?(block)\"?)?",
            re.I)
        self.headerLocationHTTPS = re.compile(
            "^(?:Content-)?Location:\s*(https://.*)$", re.I)

        callbacks.registerScannerCheck(self)
        callbacks.addSuiteTab(self)

    def defineCheckBox(self, caption, selected=True, enabled=True):
        checkBox = JCheckBox(caption)
        checkBox.setSelected(selected)
        checkBox.setEnabled(enabled)
        return checkBox

    def setSTSMinimum(self, e=None):
        val = self.inSTSMin.text
        if re.match("^\d+$", val):
            STSMinimum = int(val)
        else:
            self.inSTSMin.setText(
                str(STSMinimum))  # TODO: doesn't works as desired

    def saveConfig(self, e=None):
        config = {
            'passiveChecks': self.cbPassiveChecks.isSelected(),
            'DOMXSS': self.cbDOMXSS.isSelected(),
            'DOMXSSSources': self.cbDOMXSSSources.isSelected(),
            'DOMXSSSinks': self.cbDOMXSSSinks.isSelected(),
            'DOMXSSjQuerySinks': self.cbDOMXSSjQuerySinks.isSelected(),
            'STS': self.cbSTS.isSelected(),
            'STSMin': self.inSTSMin.text,
            'XCTO': self.cbXCTO.isSelected(),
            'XXP': self.cbXXP.isSelected(),
            'RedirToHTTPS': self.cbRedirToHTTPS.isSelected(),
        }
        self.callbacks.saveExtensionSetting("config", pickle.dumps(config))

    def restoreConfig(self, e=None):
        storedConfig = self.callbacks.loadExtensionSetting("config")
        if storedConfig != None:
            try:
                config = pickle.loads(storedConfig)
                self.cbPassiveChecks.setSelected(config['passiveChecks'])
                self.cbDOMXSS.setSelected(config['DOMXSS'])
                self.cbDOMXSSSources.setSelected(config['DOMXSSSources'])
                self.cbDOMXSSSinks.setSelected(config['DOMXSSSinks'])
                self.cbDOMXSSjQuerySinks.setSelected(
                    config['DOMXSSjQuerySinks'])
                self.cbSTS.setSelected(config['STS'])
                self.inSTSMin.text = config['STSMin']
                self.cbXCTO.setSelected(config['XCTO'])
                self.cbXXP.setSelected(config['XXP'])
                self.cbRedirToHTTPS.setSelected(config['RedirToHTTPS'])
                self.setSTSMinimum()
            except:
                print(
                    "Classical case of \"shouldn't happen\": something went wrong with config restore. Submit a bug or patch and keep your eyes open for Zombies. Something is really strange here.\nConfig contained: "
                    + storedConfig)

    ### ITab ###
    def getTabCaption(self):
        return ("Additional Scanner Checks")

    def getUiComponent(self):
        return self.tab

    def doActiveScan(self, baseRequestResponse, insertionPoint):
        pass

    ### IScannerCheck ###
    def doPassiveScan(self, baseRequestResponse):
        if not self.cbPassiveChecks.isSelected():
            return None
        scanIssues = list()
        requestProtocol = baseRequestResponse.getHttpService().getProtocol()
        analyzedResponse = self.helpers.analyzeResponse(
            baseRequestResponse.getResponse())
        responseHeaders = analyzedResponse.getHeaders()
        bodyOffset = analyzedResponse.getBodyOffset()
        responseBody = baseRequestResponse.getResponse(
        )[analyzedResponse.getBodyOffset():].tostring()

        # Identify DOMXSS sources and sinks
        domXSSSources = list()
        domXSSSinks = list()
        domXSSjQuerySinks = list()

        if self.cbDOMXSS.isSelected():
            if self.cbDOMXSSSources.isSelected():
                domXSSSources = self.domXSSSourcesRE.finditer(responseBody)
            if self.cbDOMXSSSinks.isSelected():
                domXSSSinks = self.domXSSSinksRE.finditer(responseBody)
            if self.cbDOMXSSjQuerySinks.isSelected():
                domXSSjQuerySinks = self.domXSSjQuerySinksRE.finditer(
                    responseBody)

            domXSSSourcesPos = extractMatchPositions(domXSSSources, bodyOffset)
            domXSSSinksPos = extractMatchPositions(domXSSSinks, bodyOffset)
            domXSSjQuerySinksPos = extractMatchPositions(
                domXSSjQuerySinks, bodyOffset)

            if len(domXSSSourcesPos) + len(domXSSSinksPos) + len(
                    domXSSjQuerySinksPos) > 0:  # One of the DOMXSS REs matched
                scanIssues.append(
                    DOMXSSScanIssue(baseRequestResponse, domXSSSourcesPos,
                                    domXSSSinksPos, domXSSjQuerySinksPos,
                                    self.helpers, self.callbacks))

        # Identify missing, wrong or multiple occurring HTTP headers
        headersSTS = list()
        headersXCTO = list()
        headersXXP = list()
        headersLocationHTTPS = list()

        offset = 0
        for header in responseHeaders:
            if self.cbSTS.isSelected():
                match = self.headerSTSRE.match(header)
                if match:
                    headersSTS.append((match, offset))

            if self.cbXCTO.isSelected():
                match = self.headerXCTORE.match(header)
                if match:
                    headersXCTO.append(match)

            if self.cbXXP.isSelected():
                match = self.headerXXP.match(header)
                if match:
                    headersXXP.append((match, offset))

            if self.cbRedirToHTTPS.isSelected() and requestProtocol == 'http':
                match = self.headerLocationHTTPS.match(header)
                if match:
                    headersLocationHTTPS.append((match, offset))

            offset += len(
                header
            ) + 2  # TODO: assumption that CRLF is always used. The world is ugly, make a real check.

        if requestProtocol != "https":
            pass  # HSTS only valid in HTTPS responses.
        elif self.cbSTS.isSelected():
            if len(headersSTS) == 0:  # No HSTS header
                scanIssues.append(
                    STSScanIssue(baseRequestResponse,
                                 STSScanIssue.caseNoHeader, None, self.helpers,
                                 self.callbacks))
            elif len(headersSTS) == 1 and int(
                    headersSTS[0][0].group(1)
            ) < STSMinimum:  # HSTS header present, but time frame too short
                scanIssues.append(
                    STSScanIssue(baseRequestResponse, STSScanIssue.caseTooLow,
                                 (int(headersSTS[0][0].group(1)),
                                  headersSTS[0][1] + headersSTS[0][0].start(1),
                                  headersSTS[0][1] + headersSTS[0][0].end(1)),
                                 self.helpers, self.callbacks))
            elif len(headersSTS) > 1:  # multiple HSTS headers
                scanIssues.append(
                    STSScanIssue(baseRequestResponse,
                                 STSScanIssue.caseMultipleHeaders, headersSTS,
                                 self.helpers, self.callbacks))

        # Redirection from HTTP to HTTPS
        if self.cbRedirToHTTPS.isSelected() and len(headersLocationHTTPS) > 0:
            scanIssues.append(
                RedirectFromHTTP2HTTPSScanIssue(baseRequestResponse,
                                                headersLocationHTTPS,
                                                self.helpers, self.callbacks))

        if self.cbXXP.isSelected():
            if len(headersXXP) == 0:  # No XSS protection header
                scanIssues.append(
                    XXPScanIssue(baseRequestResponse,
                                 XXPScanIssue.caseNoHeader, None, self.helpers,
                                 self.callbacks))
            elif len(headersXXP) == 1 and int(
                    headersXXP[0][0].group(1)) == 1 and headersXXP[0][0].group(
                        2) != "block":  # Activated but not in block mode
                scanIssues.append(
                    XXPScanIssue(baseRequestResponse,
                                 XXPScanIssue.caseNoBlockMode, headersXXP,
                                 self.helpers, self.callbacks))
            elif len(headersXXP) > 1:  # Multiple XXP headers
                scanIssues.append(
                    XXPScanIssue(baseRequestResponse,
                                 XXPScanIssue.caseMultipleHeaders, headersXXP,
                                 self.helpers, self.callbacks))
                # "X-XSS-Protection: 0" already catched by Burp

        # X-Content-Type-Options missing
        # NOTE: it is assumed that multiple "X-Content-Type-Options: nosniff" headers can't cause confusion at browser side because they all have the same meaning.
        if self.cbXCTO.isSelected() and len(headersXCTO) == 0:
            scanIssues.append(
                XCTOScanIssue(baseRequestResponse, self.helpers,
                              self.callbacks))

        return scanIssues

    def consolidateDuplicateIssues(self, existingIssue, newIssue):
        if existingIssue.getIssueName() == newIssue.getIssueName():
            if newIssue.getIssueName(
            ) == issueNameDOMXSS:  # DOMXSS issues are different if response content is different.
                responseExisting = existingIssue.getHttpMessages(
                )[0].getResponse()
                analyzedResponseExisting = self.helpers.analyzeResponse(
                    responseExisting)
                bodyOffsetExisting = analyzedResponseExisting.getBodyOffset()
                responseBodyExisting = responseExisting.getResponse(
                )[analyzedResponseExisting.getBodyOffset():].tostring()

                responseNew = newIssue.getHttpMessages()[0].getResponse()
                analyzedResponseNew = self.helpers.analyzeResponse(responseNew)
                bodyOffsetNew = analyzedResponseNew.getBodyOffset()
                responseBodyNew = responseNew.getResponse(
                )[analyzedResponseNew.getBodyOffset():].tostring()

                if responseBodyExisting == responseBodyNew:
                    return -1
                else:
                    return 0
            elif newIssue.getIssueName(
            ) == issueNameRedirectFromHTTP2HTTPS:  # Redirection issues are different if target URLs differ
                if existingIssue.getIssueDetail() == newIssue.getIssueDetail():
                    return -1
                else:
                    return 0
            else:  # In all other cases: keep existing issue
                return -1
        return 0
예제 #20
0
class WorkHelper(JFrame):

    def __init__(self):
        super(WorkHelper, self).__init__()
        self.clipboard = Toolkit.getDefaultToolkit().getSystemClipboard()

#############################################################
# Layout:
        layout = GroupLayout(self.getContentPane())
        self.getContentPane().setLayout(layout)
        layout.setAutoCreateGaps(True)
        layout.setAutoCreateContainerGaps(True)
#############################################################

#############################################################
# Frame Area:
        Larea1 = JLabel("InputArea:")

        Sarea1 = JScrollPane()
        self.area1 = JTextArea()
        self.area1.setToolTipText("Input Area")
        self.area1.setEditable(True)
        self.area1.setBorder(BorderFactory.createLineBorder(Color.gray))
        Sarea1.setPreferredSize(Dimension(300,100))
        Sarea1.getViewport().setView((self.area1))

        bClear = JButton("Clear", actionPerformed=self.bClear)
        bClear.setToolTipText("Clears the text form both Input and Output text Areas")

        bCopyToInput = JButton("Copy to Input", actionPerformed=self.bCopyToInput)
        bCopyToInput.setToolTipText("Copy the text from the Output Area to the Input Area for further Operations")
        
        self.cCtClipB = JCheckBox("Auto-Copy");
        self.cCtClipB.setToolTipText("When 'Checked' after the Categories are created they will added to the clipboard")
        self.cCtClipB.setSelected(1)
        
        Larea2 = JLabel("OutputArea:")
        
        Sarea2 = JScrollPane()
        self.area2 = JTextArea()
        self.area2.setToolTipText("Output Area")
        self.area2.setEditable(False)
        self.area2.setBorder(BorderFactory.createLineBorder(Color.gray))
        Sarea2.setPreferredSize(Dimension(300,100))
        Sarea2.getViewport().setView((self.area2))

#############################################################
# Tabbed Area:
        tabPane = JTabbedPane(JTabbedPane.TOP)
        self.getContentPane().add(tabPane)
        #####################################################
        # Text Edit pane
        panel_TEdit = JPanel()
        layout2 = GroupLayout(panel_TEdit)
        layout2.setAutoCreateGaps(True)
        layout2.setAutoCreateContainerGaps(True)
        panel_TEdit.setLayout(layout2)
        
        bRemoveNBSP_L = JButton("Clean LText", actionPerformed=self.bRemoveNBSP_L)
        bRemoveNBSP_L.setToolTipText("Removes Spaces, Tabs from the start of every text line from the input Area")
        bRemoveNBSP_R = JButton("Clean RText", actionPerformed=self.bRemoveNBSP_R)
        bRemoveNBSP_R.setToolTipText("Removes Spaces, Tabs from the end of every text line from the input Area")
    
        
        self.ReplaceThis = JTextField()
        self.ReplaceThis = JTextField(maximumSize=Dimension(120,25))
        self.ReplaceThis.setToolTipText("Text to be replaced")

        self.ReplaceThat = JTextField()
        self.ReplaceThat = JTextField(maximumSize=Dimension(120,25))
        self.ReplaceThat.setToolTipText("Text to be placed")

        bSandReplace = JButton("Replace Text", actionPerformed=self.bSandReplace)
        bSandReplace.setToolTipText("Replace the text from This with Text from That in the Text from the Input Area and displays it in the Output Area")

        bRemNumbers = JButton("Rem Numbers", actionPerformed=self.RemNumbers)
        bRemNumbers.setToolTipText("Removes numbers from the start of every line")
        #####################################################
        # Dimension pane
        panel_Dimensions = JPanel()
        layout3 = GroupLayout(panel_Dimensions)
        layout3.setAutoCreateGaps(True)
        layout3.setAutoCreateContainerGaps(True)
        panel_Dimensions.setLayout(layout3)
        
        
        self.cCurly = JCheckBox("Curly");
        self.cCurly.setToolTipText("When 'Checked' Curly Brackets will surround the Categories")
        self.cCurly.setSelected(1)

        self.cSemiC = JCheckBox("SemiColumn");
        self.cSemiC.setToolTipText("When 'Checked' after the Categories are created at the end will be a semicolomn")
        self.cSemiC.setSelected(1)

        self.iStart = JTextField(maximumSize=Dimension(40,25))
        self.iStart.setToolTipText("The Start Index for the Making of the Categories")

        self.RThis = JTextField()
        self.RThis = JTextField(maximumSize=Dimension(120,25))
        self.RThis.setToolTipText("The Starting Index used in creating the Categorical")

        self.RThat = JTextField()
        self.RThat = JTextField(maximumSize=Dimension(120,25))
        self.RThat.setToolTipText("The Finish Index used in creating the Categorical")
        
        optioncCategories = JLabel("Options:")
        bcCat = JButton("CreatCateg", actionPerformed=self.bcCat)
        bcCat.setToolTipText("Create a categorical form starting C_Index to finish C_Index; Use the text boxes to define the indexes")

        bM_Categories = JButton("Categories", actionPerformed=self.mCategories)
        bM_Categories.setToolTipText("Make Categories using the lines from the Input Area. Use it to define Categorical questions.")
        #####################################################
        # ConfirmIt pane
        panel_ConfirmIt = JPanel()
        layout4 = GroupLayout(panel_ConfirmIt)
        layout4.setAutoCreateGaps(True)
        layout4.setAutoCreateContainerGaps(True)
        panel_ConfirmIt.setLayout(layout4)
        
        self.PID = JTextField()
        self.PID = JTextField(maximumSize=Dimension(120,25))
        self.PID.setToolTipText("The PID number used for creating links with PID and ids from every line of the Input Area")
        
        bClinks = JButton("Create Links", actionPerformed=self.bClinks)
        bClinks.setToolTipText("Create links for a project using PID and ID, ID`s are read from every line of the Input Area")
        
        bClinksNA = JButton("Create Links NA ", actionPerformed=self.bClinksNA)
        bClinksNA.setToolTipText("Create links for a project using PID and ID`s from the standard sample test for US")
        
        bClinksCA = JButton("Create Links CA", actionPerformed=self.bClinksCA)
        bClinksCA.setToolTipText("Create links for a project using PID and ID`s from the standard sample test for CA")
        
        self.Width = JTextField()
        self.Width = JTextField(maximumSize=Dimension(120,25))
        self.Width.setToolTipText("The Width used in creating the DIV html tag, note the dimension used is in px")
        
        baddDIVt = JButton("Add DIV tag", actionPerformed=self.baddDIVt)
        baddDIVt.setToolTipText("Create a DIV tag for every line in the Input Area")
        #####################################################
        # Statistics pane
        panel_Statistics = JPanel()
        layout5 = GroupLayout(panel_Statistics)
        layout5.setAutoCreateGaps(True)
        layout5.setAutoCreateContainerGaps(True)
        panel_Statistics.setLayout(layout5)         
        
        #####################################################
        # TimeTraking pane
        panel_TimeTraking = JPanel()
        layout6 = GroupLayout(panel_TimeTraking)
        layout6.setAutoCreateGaps(True)
        layout6.setAutoCreateContainerGaps(True)
        panel_TimeTraking.setLayout(layout6)     
        
        #####################################################
        # Tabbed Area Tabs
        tabPane.addTab("Text Edit", panel_TEdit)
        tabPane.addTab("Dimensions", panel_Dimensions)
        tabPane.addTab("ConfirmIt", panel_ConfirmIt)
        tabPane.addTab("Statistics", panel_Statistics)
        tabPane.addTab("TimeTraking", panel_TimeTraking)
        
        
#############################################################




#############################################################
# Aplication Layouts: 2 groups one Horizontal and one Vertical
        
        #############################################################
        # Frame Layout: 2 groups one Horizontal and one Vertical
        layout.setHorizontalGroup(layout.createSequentialGroup()
            .addGroup(layout.createParallelGroup()
                .addComponent(Larea1)
                .addComponent(Sarea1)
                .addComponent(Sarea2)
                .addGroup(layout.createSequentialGroup()
                          .addComponent(bCopyToInput)
                          .addComponent(bClear)
                          .addComponent(self.cCtClipB))
                .addComponent(Larea2))
            .addGroup(layout.createParallelGroup()
                .addComponent(tabPane))
                        )

        layout.setVerticalGroup(layout.createSequentialGroup()
            .addGroup(layout.createParallelGroup()
                      .addGroup(layout.createSequentialGroup()
                          .addComponent(Larea1)
                          .addComponent(Sarea1)
                          .addGroup(layout.createParallelGroup()
                                    .addComponent(bCopyToInput)
                                    .addComponent(bClear)
                                    .addComponent(self.cCtClipB)    )
                          .addComponent(Larea2)
                          .addComponent(Sarea2))
                      .addGroup(layout.createSequentialGroup()
                          .addComponent(tabPane))
                          )
                        )

        #############################################################
        # TEdit Layout: 2 groups one Horizontal and one Vertical
        layout2.setHorizontalGroup(layout2.createSequentialGroup()
            .addGroup(layout2.createParallelGroup()
                .addGroup(layout2.createSequentialGroup()
                    .addComponent(bRemNumbers)
                    .addComponent(bRemoveNBSP_L)
                    .addComponent(bRemoveNBSP_R))
                    .addGroup(layout2.createSequentialGroup()
                    .addComponent(bSandReplace)
                    .addComponent(self.ReplaceThis)
                    .addComponent(self.ReplaceThat))  
                      
                      
                      
                                   ))
        
        layout2.setVerticalGroup(layout2.createSequentialGroup()
            .addGroup(layout2.createParallelGroup()
                .addComponent(bRemNumbers)
                .addComponent(bRemoveNBSP_L)
                .addComponent(bRemoveNBSP_R))
                                 
                .addGroup(layout2.createParallelGroup()
                    .addComponent(bSandReplace)
                    .addComponent(self.ReplaceThis)
                    .addComponent(self.ReplaceThat))  
                                 )
            
            
        #############################################################
        # Dimensions Layout: 2 groups one Horizontal and one Vertical
        layout3.setHorizontalGroup(layout3.createSequentialGroup()
        
         .addGroup(layout3.createParallelGroup()
            .addGroup(layout3.createSequentialGroup()
                .addComponent(bM_Categories)
                .addComponent(self.iStart))
            .addGroup(layout3.createSequentialGroup()
                .addComponent(optioncCategories)
                .addComponent(self.cCurly)
                .addComponent(self.cSemiC)
                )
           
            .addGroup(layout3.createSequentialGroup()
                .addComponent(bcCat)
                .addComponent(self.RThis)
                .addComponent(self.RThat))
            .addGroup(layout3.createSequentialGroup()
                
                )

                )
        )
        
        layout3.setVerticalGroup(layout3.createSequentialGroup()
            .addGroup(layout3.createSequentialGroup()
                    .addGroup(layout3.createParallelGroup()
                        .addComponent(bM_Categories)
                        .addComponent(self.iStart))
                    
                    .addGroup(layout3.createParallelGroup()
                        .addComponent(bcCat)
                        .addComponent(self.RThis)
                        .addComponent(self.RThat))
                    .addGroup(layout3.createParallelGroup()
                        
                    .addGroup(layout3.createParallelGroup()
                        .addComponent(optioncCategories)
                        .addComponent(self.cCurly)
                        .addComponent(self.cSemiC)
                        )
                   
                                )
                        )
            
            )
        #############################################################
        # ConfimIT Layout: 2 groups one Horizontal and one Vertical
        layout4.setHorizontalGroup(layout4.createSequentialGroup()
        
         .addGroup(layout4.createParallelGroup()
            .addGroup(layout4.createSequentialGroup()
                .addComponent(bClinks)
                .addComponent(self.PID)
                )
            .addGroup(layout4.createSequentialGroup()
                .addComponent(bClinksNA)
                .addComponent(bClinksCA)
                )
            .addGroup(layout4.createSequentialGroup()
                .addComponent(baddDIVt)
                .addComponent(self.Width)
                
                )
                
                ))
        
        
        layout4.setVerticalGroup(layout4.createSequentialGroup()
            .addGroup(layout4.createSequentialGroup()
                    .addGroup(layout4.createParallelGroup()
                        .addComponent(bClinks)
                        .addComponent(self.PID))
                    .addGroup(layout4.createParallelGroup()
                        .addComponent(bClinksNA)
                        .addComponent(bClinksCA)
                        )
                    
                    .addGroup(layout4.createParallelGroup()
                        .addComponent(baddDIVt)
                        .addComponent(self.Width)
                        )
                    
                        
                        ))
        
        
        #layout2.linkSize(SwingConstants.HORIZONTAL, [self.cCurly,bM_Categories])
        #layout.linkSize(SwingConstants.HORIZONTAL, [ok, bCopyToInput, close, bM_Categories])
        #layout3.linkSize(SwingConstants.HORIZONTAL, [self.RThis,self.RThat,bRemoveNBSP_L,bRemoveNBSP_R,bM_Categories,bSandReplace,bcCat])

        
#############################################################

#############################################################
# Aplication Settings
        self.pack()
        #self.setPreferredSize(Dimension(1000, 1000))
        self.setTitle("Workhelper")
        self.setSize(800, 500)
        self.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
        self.setLocationRelativeTo(None)
        self.setVisible(True)
#############################################################

#############################################################
# WorkHelper class methods:
    def onQuit(self, e):
        "@sig public void setExpression(java.lang.String e)"
        os.system.exit(0)


# def addToClipBoard(self, text):
# "@sig public void setExpression(java.lang.String text)"
# command = 'echo ' + text.strip() + '| clip'
# os.system(command)
# brute method for pasting into clipboard on windows




    def mCategories(self, e):
        "@sig public void setExpression(java.lang.String e)"
        """
        Takes every line of text form the Input Area and by using a
        string composition it creates the output in the SPSS dimension
        categories format.
        """
        try:
            StartIndex = int(self.iStart.getText())
        except ValueError:
            StartIndex=1




        text=self.area1.getText().rstrip()


        counter=StartIndex
        lastindex=0
        textO=""

        for i in range(0,len(text)):
                if text[i]=='\n':
                        textO=textO+("_"+str(counter)+' "'+text[lastindex:i]+'",\n')
                        lastindex=i+1
                        counter=counter+1

        if len(text[lastindex:len(text)])>0:
                textO=textO+("_"+str(counter)+' "'+text[lastindex:len(text)]+'"')


        if len(textO)>0:
            if self.cCurly.isSelected():
                textO = "{\n"+ textO + "\n}"
                if self.cSemiC.isSelected():
                    textO = textO + ";"
            self.copyToClipboard(textO)
            self.area2.setText(textO)

    def copyToClipboard(self, text):
            if self.cCtClipB.isSelected():
                stringSelection = StringSelection(text)
                self.clipboard.setContents(stringSelection, None)



    def bCopyToInput(self, e):
        "@sig public void setExpression(java.lang.String e)"
        """Copy the Text from the Output Area to the input Area for further operations"""

        self.area1.setText(self.area2.getText())

    def bRemoveNBSP_L(self, e):
        "@sig public void setExpression(java.lang.String e)"
        text=self.area1.getText().rstrip()
        textO=""
        lastindex=0

        for i in range(0,len(text)):
            if text[i] == '\n':
                textO = textO+text[lastindex:i].lstrip()+"\n"
                lastindex=i+1
                #print(text[0:i].lstrip()+'\n')
        if len(text[lastindex:len(text)])>0:
                textO=textO+text[lastindex:len(text)].lstrip()
        self.area2.setText(textO)

    def bRemoveNBSP_R(self, e):
        "@sig public void setExpression(java.lang.String e)"
        text=self.area1.getText().rstrip()
        textO=""
        lastindex=0

        for i in range(0,len(text)):
            if text[i] == '\n':
                textO = textO+text[lastindex:i].rstrip()+"\n"
                lastindex=i+1
                #print(text[0:i].lstrip()+'\n')
        if len(text[lastindex:len(text)])>0:
                textO=textO+text[lastindex:len(text)].rstrip()
        self.area2.setText(textO)

    def bClear(self, e):
        "@sig public void setExpression(java.lang.String e)"
        self.area1.setText("")
        self.area2.setText("")

    def bcCat(self, e):
        "@sig public void setExpression(java.lang.String e)"
        try:
            StartIndex = int(self.RThis.getText())
        except ValueError:
            StartIndex=1

        try:
            FinishIndex = int(self.RThat.getText())
        except ValueError:
            FinishIndex=1
        cCats=""
        for i in range(StartIndex,FinishIndex+1):
            if i<>FinishIndex:
                cCats=cCats+"_"+str(i)+","
            else:
                cCats=cCats+"_"+str(i)

        if StartIndex<FinishIndex:
            cCats="{"+cCats+"}"
            self.copyToClipboard(cCats)
            self.area2.setText(cCats)

    def bSandReplace(self, e):
        self.area2.setText(self.area1.getText().replace(self.ReplaceThis.getText(),self.ReplaceThat.getText()))
        self.copyToClipboard(self.area2.getText())

    #############################################################
    # Confirmit
    def bClinks(self, e):
    
    
        text=self.area1.getText().rstrip()

        lastindex=0
        textO=""

        for i in range(0,len(text)):
                if text[i]=='\n':
                    textO=textO+'http://surveys.ipsosinteractive.com/surveys2/?pid='+self.PID.getText()+'&id='+text[lastindex:i]+'\n'
                    lastindex=i+1

        if len(text[lastindex:len(text)])>0:
                textO=textO+'http://surveys.ipsosinteractive.com/surveys2/?pid='+self.PID.getText()+'&id='+text[lastindex:len(text)]

        self.copyToClipboard(textO)
        self.area2.setText(textO)
        
    def bClinksNA(self, e):
        
        
        output=""
        
        for i in range (1,201):
        
            if i<10:
                output=output+'http://surveys.ipsosinteractive.com/surveys2/?pid='+self.PID.getText()+'&id='+'US9900'+str(i)+'\n'
            else:
                if i<100:
                    output=output+'http://surveys.ipsosinteractive.com/surveys2/?pid='+self.PID.getText()+'&id='+'US990'+str(i)+'\n'
                else:
                    if i==200:
                        output=output+'http://surveys.ipsosinteractive.com/surveys2/?pid='+self.PID.getText()+'&id='+'US99'+str(i)
                    else: 
                        output=output+'http://surveys.ipsosinteractive.com/surveys2/?pid='+self.PID.getText()+'&id='+'US99'+str(i)+'\n'
        
        
        self.area2.setText(output)
        self.copyToClipboard(self.area2.getText())
        
    def bClinksCA(self, e):
        output=""
        
        for i in range (1,201):
        
            if i<10:
                output=output+'http://surveys.ipsosinteractive.com/surveys2/?pid='+self.PID.getText()+'&id='+'CA9900'+str(i)+'\n'
            else:
                if i<100:
                    output=output+'http://surveys.ipsosinteractive.com/surveys2/?pid='+self.PID.getText()+'&id='+'CA990'+str(i)+'\n'
                else:
                    if i==200:
                        output=output+'http://surveys.ipsosinteractive.com/surveys2/?pid='+self.PID.getText()+'&id='+'CA99'+str(i)
                    else: 
                        output=output+'http://surveys.ipsosinteractive.com/surveys2/?pid='+self.PID.getText()+'&id='+'CA99'+str(i)+'\n'
        
        
        self.area2.setText(output)
        self.copyToClipboard(self.area2.getText())
        
    def baddDIVt(self, e):
        
        try:
            Width = int(self.Width.getText())
        except ValueError:
            Width=1
            
        text=self.area1.getText().rstrip()

        lastindex=0
        textO=""

        for i in range(0,len(text)):
            if text[i]=='\n':
                textO=textO+'<div style="width:'+str(Width)+'px">'+text[lastindex:i]+'</div>'+'\n'
                lastindex=i+1

        if len(text[lastindex:len(text)])>0:
            textO=textO+'<div style="width:'+str(Width)+'px">'+text[lastindex:len(text)]+'</div>'
            

        self.copyToClipboard(textO)
        self.area2.setText(textO)
        
    def RemNumbers(self, e):
        text=self.area1.getText().rstrip()

        lastindex=0
        textO=""
        
        
        for i in range(0,len(text)):
            if text[i]=='\n':
                textO=textO+text[lastindex:i].lstrip('1234567890')+'\n'
                lastindex=i+1
        if len(text[lastindex:len(text)])>0:
            textO=textO+text[lastindex:len(text)].lstrip('1234567890')
            

        self.copyToClipboard(textO)
        self.area2.setText(textO)