Example #1
0
 def setup_edit_area(self, split_orientation=None):
     '''
     Check if the ATF text area is being displayed in a split editor.
     If so, resets to normal JScrollPane. If not, splits the screen.
     '''
     if isinstance(self.container, JSplitPane):
         # If Nammu is already displaying a split pane, reset to original
         # setup
         self.container = JScrollPane(self.edit_area)
         self.container.setRowHeaderView(self.line_numbers_area)
         self.container.setVisible(True)
         self.add(self.container, BorderLayout.CENTER)
     else:
         # If there is not a split pane, create both panels and setup view
         main_editor = JScrollPane(self.edit_area)
         main_editor.setRowHeaderView(self.line_numbers_area)
         secondary_editor = JScrollPane(self.secondary_area)
         secondary_editor.setRowHeaderView(self.secondary_line_numbers)
         self.container = JSplitPane(split_orientation,
                                     main_editor,
                                     secondary_editor)
         self.container.setDividerSize(5)
         self.container.setVisible(True)
         self.container.setDividerLocation(0.5)
         self.container.setResizeWeight(0.5)
         self.add(self.container, BorderLayout.CENTER)
Example #2
0
 def addCenterPane(self, atfAreaView, consoleView):
     splitPane = JSplitPane(JSplitPane.VERTICAL_SPLIT)
     splitPane.setTopComponent(atfAreaView)
     splitPane.setBottomComponent(consoleView)
     splitPane.setDividerSize(5)
     self.getContentPane().add(splitPane, BorderLayout.CENTER)
     # Make console's high remain smaller compared to edit area
     splitPane.setResizeWeight(0.9)
Example #3
0
    def initGui(self):
        def make_game_selector():
            self.gameChanger = False
            def dbChange(evt):
                if evt.source.text: 
                    self.gamedb = GameDB(evt.source.text)
                    self.gameChanger = True
            def idChange(evt):
                if evt.source.text: 
                    self.gameid = evt.source.text
                    self.gameChanger = True
            def turnChange(evt):
                if evt.source.text: 
                    self.turnid = evt.source.text
                    self.gameChanger = True

            selector = JPanel()
            selector.add(JLabel("DB:"))
            selector.add(textfield(self.gamedb.dbfile, dbChange))
            selector.add(JLabel("Game ID:"))
            selector.add(textfield(self.gameid, idChange))
            selector.add(JLabel("Turn ID:"))
            selector.add(textfield(self.turnid, turnChange))
            return JScrollPane(selector)

        def make_content_panel():
            self.contentPanel = JPanel(GridLayout(1, 0, 5, 5))
            self.render()
            return JScrollPane(self.contentPanel)

        def save(self, txt, filename):
            pass
            
        def make_code_editor():
            import inspect
            panel = JPanel(BorderLayout(2,2))
            self.codeArea = JTextArea()
            self.codeArea.text = self.scoringModule and inspect.getsource(self.scoringModule) or ""
            panel.add(JScrollPane(self.codeArea), BorderLayout.CENTER)
            return panel

        self.frame.contentPane.add(make_game_selector(), BorderLayout.NORTH)
#        self.frame.contentPane.add(make_content_panel(), BorderLayout.WEST)
#        self.frame.contentPane.add(make_code_editor(),   BorderLayout.CENTER)
        pane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT, make_content_panel(), make_code_editor())
        pane.setDividerLocation(self.frame.width/2)
        self.frame.contentPane.add(pane)
        reloadButton = JButton("Reload")
        def reload(evt):
            self.reload()
        reloadButton.addActionListener(reload)
        self.frame.contentPane.add(reloadButton, BorderLayout.SOUTH)
Example #4
0
    def __init__(self, callbacks, log):
        '''
        Creates GUI objects, registers right-click handlers, and adds the 
        extension's tab to the Burp UI.
        '''

        # Create split pane with top and bottom panes

        self._splitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT)
        self.bottom_pane = UiBottomPane(callbacks, log)
        self.top_pane = UiTopPane(callbacks, self.bottom_pane, log)
        self.bottom_pane.setLogTable(self.top_pane.logTable)
        self._splitpane.setLeftComponent(self.top_pane)
        self._splitpane.setRightComponent(self.bottom_pane)


        # Create right-click handler

        self.log = log
        rc_handler = RightClickHandler(callbacks, log)
        callbacks.registerContextMenuFactory(rc_handler)

        
        # Add the plugin's custom tab to Burp's UI

        callbacks.customizeUiComponent(self._splitpane)
        callbacks.addSuiteTab(self)
Example #5
0
    def initTabs(self):
        #
        ##  init autorize tabs
        #
        
        self.logTable = Table(self)

        self.logTable.setAutoCreateRowSorter(True)        

        tableWidth = self.logTable.getPreferredSize().width        
        self.logTable.getColumn("ID").setPreferredWidth(Math.round(tableWidth / 50 * 2))
        self.logTable.getColumn("URL").setPreferredWidth(Math.round(tableWidth / 50 * 24))
        self.logTable.getColumn("Orig. Length").setPreferredWidth(Math.round(tableWidth / 50 * 4))
        self.logTable.getColumn("Modif. Length").setPreferredWidth(Math.round(tableWidth / 50 * 4))
        self.logTable.getColumn("Unauth. Length").setPreferredWidth(Math.round(tableWidth / 50 * 4))
        self.logTable.getColumn("Authorization Enforcement Status").setPreferredWidth(Math.round(tableWidth / 50 * 4))
        self.logTable.getColumn("Authorization Unauth. Status").setPreferredWidth(Math.round(tableWidth / 50 * 4))

        self._splitpane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT)
        self._splitpane.setResizeWeight(1)
        self.scrollPane = JScrollPane(self.logTable)
        self._splitpane.setLeftComponent(self.scrollPane)
        self.scrollPane.getVerticalScrollBar().addAdjustmentListener(autoScrollListener(self))
        self.menuES0 = JCheckBoxMenuItem(self._enfocementStatuses[0],True)
        self.menuES1 = JCheckBoxMenuItem(self._enfocementStatuses[1],True)
        self.menuES2 = JCheckBoxMenuItem(self._enfocementStatuses[2],True)
        self.menuES0.addItemListener(menuTableFilter(self))
        self.menuES1.addItemListener(menuTableFilter(self))
        self.menuES2.addItemListener(menuTableFilter(self))

        copyURLitem = JMenuItem("Copy URL");
        copyURLitem.addActionListener(copySelectedURL(self))
        self.menu = JPopupMenu("Popup")
        self.menu.add(copyURLitem)
        self.menu.add(self.menuES0)
        self.menu.add(self.menuES1)
        self.menu.add(self.menuES2)

        self.tabs = JTabbedPane()
        self._requestViewer = self._callbacks.createMessageEditor(self, False)
        self._responseViewer = self._callbacks.createMessageEditor(self, False)

        self._originalrequestViewer = self._callbacks.createMessageEditor(self, False)
        self._originalresponseViewer = self._callbacks.createMessageEditor(self, False)

        self._unauthorizedrequestViewer = self._callbacks.createMessageEditor(self, False)
        self._unauthorizedresponseViewer = self._callbacks.createMessageEditor(self, False)        

        self.tabs.addTab("Modified Request", self._requestViewer.getComponent())
        self.tabs.addTab("Modified Response", self._responseViewer.getComponent())

        self.tabs.addTab("Original Request", self._originalrequestViewer.getComponent())
        self.tabs.addTab("Original Response", self._originalresponseViewer.getComponent())

        self.tabs.addTab("Unauthenticated Request", self._unauthorizedrequestViewer.getComponent())
        self.tabs.addTab("Unauthenticated Response", self._unauthorizedresponseViewer.getComponent())        

        self.tabs.addTab("Configuration", self.pnl)
        self.tabs.setSelectedIndex(6)
        self._splitpane.setRightComponent(self.tabs)
Example #6
0
    def initTabs(self):
        #
        ##  init autorize tabs
        #
        
        self._splitpane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT)
        self.scrollPane = JScrollPane(self.logTable)
        self._splitpane.setLeftComponent(self.scrollPane)
        colorsMenu = JMenu("Paint")
        redMenu = JMenuItem("Red")
        noneMenu = JMenuItem("None")
        greenMenu = JMenuItem("Green")
        redMenu.addActionListener(paintChange(self, "Red"))
        noneMenu.addActionListener(paintChange(self, None))
        greenMenu.addActionListener(paintChange(self, "Green"))
        colorsMenu.add(redMenu)
        colorsMenu.add(noneMenu)
        colorsMenu.add(greenMenu)
        
        
        self.menu = JPopupMenu("Popup")
        self.menu.add(colorsMenu)

        self.tabs = JTabbedPane()
        
        self.tabs.addTab("Request", self._requestViewer.getComponent())
        self.tabs.addTab("Response", self._responseViewer.getComponent())

        self.tabs.addTab("Vulnerability", self.pnl)

        self.tabs.addTab("Project Settings", self.projectSettings)
        
        self.tabs.setSelectedIndex(2)
        self._splitpane.setRightComponent(self.tabs)
Example #7
0
def createAndShowGUI():
    # Create the GUI and show it. As with all GUI code, this must run
    # on the event-dispatching thread.
    frame = JFrame("GUI Development ")
    frame.setSize(500, 600)
    frame.setLayout(BorderLayout())
    splitPane = JSplitPane(JSplitPane.VERTICAL_SPLIT)
    
    #Create and set up the content pane.
    psimures= ResourcePanel()
    psimures.setOpaque(True)
    pconfig = ConfigurationPanel()
    pconfig.setOpaque(True)      #content panes must be opaque

    # show the GUI
    splitPane.add(psimures)
    splitPane.add(pconfig)
    frame.add(splitPane)
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE)
    frame.setVisible(True)
Example #8
0
    def __init__(self, controller):
        '''
        Creates default empty text area in a panel for ATF edition.
        It has syntax highlighting based on the ATF parser (pyoracc).
        It also highlights line numbers where there are validations errors
        returned by the ORACC server.
        '''
        # Give reference to controller to delegate action response
        self.controller = controller

        # Make text area occupy all available space and resize with parent
        # window
        self.setLayout(BorderLayout())

        # Short hand for edit area and line numbers area
        self.edit_area = self.controller.edit_area
        self.line_numbers_area = self.controller.line_numbers_area

        # Create secondary text area for split view
        self.secondary_area = self.controller.secondary_area
        self.secondary_line_numbers = self.controller.secondary_line_numbers

        # Set undo/redo manager to edit area
        self.undo_manager = UndoManager()
        self.undo_manager.limit = 3000
        self.edit_listener = AtfUndoableEditListener(self.undo_manager)
        self.edit_area.getDocument().addUndoableEditListener(
                                                        self.edit_listener)

        # Sort out layout by synch-ing line numbers and text area and putting
        # only the text area in a scroll pane as indicated in the
        # TextLineNumber tutorial.
        self.edit_area.setPreferredSize(Dimension(1, 500))
        self.container = JScrollPane(self.edit_area)
        self.container.setRowHeaderView(self.line_numbers_area)
        self.add(self.container, BorderLayout.CENTER)

        self.vert_scroll = self.container.getVerticalScrollBar()
        self.vert_scroll.addAdjustmentListener(atfAreaAdjustmentListener(self))

        # Key listener that triggers syntax highlighting, etc. upon key release
        self.edit_area.addKeyListener(AtfAreaKeyListener(self))
        # Also needed in secondary area:
        self.secondary_area.addKeyListener(AtfAreaKeyListener(self))

        # Add a document listener to track changes to files
        docListener = atfAreaDocumentListener(self)
        self.edit_area.getDocument().addDocumentListener(docListener)

        # instance variable to store a record of the text contents prior to the
        # most recent change. Needed so that the different listeners can access
        # this to handle error line updating.
        self.oldtext = ''
Example #9
0
class BurpUi(ITab):
    '''
    The collection of objects that make up this extension's Burp UI. Created
    by BurpExtender.
    '''

    def __init__(self, callbacks, log):
        '''
        Creates GUI objects, registers right-click handlers, and adds the 
        extension's tab to the Burp UI.
        '''

        # Create split pane with top and bottom panes

        self._splitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT)
        self.bottom_pane = UiBottomPane(callbacks, log)
        self.top_pane = UiTopPane(callbacks, self.bottom_pane, log)
        self.bottom_pane.setLogTable(self.top_pane.logTable)
        self._splitpane.setLeftComponent(self.top_pane)
        self._splitpane.setRightComponent(self.bottom_pane)


        # Create right-click handler

        self.log = log
        rc_handler = RightClickHandler(callbacks, log)
        callbacks.registerContextMenuFactory(rc_handler)

        
        # Add the plugin's custom tab to Burp's UI

        callbacks.customizeUiComponent(self._splitpane)
        callbacks.addSuiteTab(self)

      
    def getTabCaption(self):
        return "Git"
       
    def getUiComponent(self):
        return self._splitpane
Example #10
0
    def __init__(self, mainPanel, auxPanel, auxTitle, orientation,
                 showTitle=True, minsize=Dimension(
                     AuxillarySplitPane.MINIMUM_WIDTH,
                     AuxillarySplitPane.MINIMUM_HEIGHT)):
        if orientation not in self.ORIENTATIONS:
            raise ValueError("Orientation should be one of "
                             "top, bottom, left, right")

        JSplitPane.__init__(self,
            AuxillarySplitPane.getJSplitPaneOrientation(orientation))
        self.mainPanel = mainPanel
        self.auxTitle = auxTitle

        self.orientation = orientation
        self.minimumSize = minsize
        self.showTitle = showTitle
        self.resizable = True

        self.auxPanelVisibleSize
        self.auxPanelWr

        self.addComponentListener(AuxResizeListener(self))
        self.init(auxPanel)
Example #11
0
    def	registerExtenderCallbacks(self, callbacks):
        global statement,con

        self._callbacks = callbacks
        self._helpers = callbacks.getHelpers()
        callbacks.setExtensionName("SQLite Logger")

        # select sqlite jdbc jar file
        c = classPathHacker()
        c.addFile("C:\\sqlite-jdbc-3.8.11.2.jar")

        # database filename.
        jdbc_url = "jdbc:sqlite:database" + str(datetime.date.today()) + ".db"
        driver = "org.sqlite.JDBC"
        Class.forName(driver).newInstance()
        con = DriverManager.getConnection(jdbc_url)

        # create table
        self.sql = "CREATE TABLE if not exists log(host text,path text,method text,request text,response text,time text);"
        statement = con.prepareStatement(self.sql)
        statement.executeUpdate()
        
        self._log = ArrayList()
        self._lock = Lock()

        self._splitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT)

        logTable = Table(self)
        scrollPane = JScrollPane(logTable)
        self._splitpane.setLeftComponent(scrollPane)

        tabs = JTabbedPane()
        self._requestViewer = callbacks.createMessageEditor(self, False)
        self._responseViewer = callbacks.createMessageEditor(self, False)
        tabs.addTab("Request", self._requestViewer.getComponent())
        tabs.addTab("Response", self._responseViewer.getComponent())
        self._splitpane.setRightComponent(tabs)

        callbacks.customizeUiComponent(self._splitpane)
        callbacks.customizeUiComponent(logTable)
        callbacks.customizeUiComponent(scrollPane)
        callbacks.customizeUiComponent(tabs)

        callbacks.addSuiteTab(self)

        callbacks.registerHttpListener(self)
        
        return
    def	registerExtenderCallbacks(self, callbacks):
    
        # 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("Reflected XSS Detector")
        
        # create the log and a lock on which to synchronize when adding log entries
        self._log = ArrayList()
        self._lock = Lock()
        
        # main split pane
        self._splitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT)
        
        # table of log entries
        logTable = Table(self)
        scrollPane = JScrollPane(logTable)
        self._splitpane.setLeftComponent(scrollPane)

        logTable.addMouseListener( CMouseListener(self) )

        # tabs with request/response viewers
        tabs = JTabbedPane()
        self._requestViewer = callbacks.createMessageEditor(self, False)
        self._responseViewer = callbacks.createMessageEditor(self, False)
        tabs.addTab("Response", self._responseViewer.getComponent())
        tabs.addTab("Request", self._requestViewer.getComponent())
        self._splitpane.setRightComponent(tabs)
        
        # customize our UI components
        callbacks.customizeUiComponent(self._splitpane)
        callbacks.customizeUiComponent(logTable)
        callbacks.customizeUiComponent(scrollPane)
        callbacks.customizeUiComponent(tabs)
        
        # add the custom tab to Burp's UI
        callbacks.addSuiteTab(self)
        
        # register ourselves as an HTTP listener
        callbacks.registerHttpListener(self)
        
        return
Example #13
0
    def initTabs(self):
        #
        ##  init autorize tabs
        #
        
        self.logTable = Table(self)
        self._splitpane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT)
        self._splitpane.setResizeWeight(1)
        self.scrollPane = JScrollPane(self.logTable)
        self._splitpane.setLeftComponent(self.scrollPane)
        self.scrollPane.getVerticalScrollBar().addAdjustmentListener(autoScrollListener(self))
        self.menuES0 = JCheckBoxMenuItem(self._enfocementStatuses[0],True)
        self.menuES1 = JCheckBoxMenuItem(self._enfocementStatuses[1],True)
        self.menuES2 = JCheckBoxMenuItem(self._enfocementStatuses[2],True)
        self.menuES0.addItemListener(menuTableFilter(self))
        self.menuES1.addItemListener(menuTableFilter(self))
        self.menuES2.addItemListener(menuTableFilter(self))

        copyURLitem = JMenuItem("Copy URL");
        copyURLitem.addActionListener(copySelectedURL(self))
        self.menu = JPopupMenu("Popup")
        self.menu.add(copyURLitem)
        self.menu.add(self.menuES0)
        self.menu.add(self.menuES1)
        self.menu.add(self.menuES2)

        self.tabs = JTabbedPane()
        self._requestViewer = self._callbacks.createMessageEditor(self, False)
        self._responseViewer = self._callbacks.createMessageEditor(self, False)

        self._originalrequestViewer = self._callbacks.createMessageEditor(self, False)
        self._originalresponseViewer = self._callbacks.createMessageEditor(self, False)

        self.tabs.addTab("Modified Request", self._requestViewer.getComponent())
        self.tabs.addTab("Modified Response", self._responseViewer.getComponent())

        self.tabs.addTab("Original Request", self._originalrequestViewer.getComponent())
        self.tabs.addTab("Original Response", self._originalresponseViewer.getComponent())

        self.tabs.addTab("Configuration", self.pnl)
        self.tabs.setSelectedIndex(4)
        self._splitpane.setRightComponent(self.tabs)
Example #14
0
    def getUiComponent(self):
        self.domainTable = JTable(ResourceTableModel())
        self.domainTable.setRowHeight(30)
        #Delete:
        #jcolumnModel = self.domainTable.getColumnModel()

        splitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT)
        topPane = JPanel()
        image_label = HelpLabel(self.callbacks)
        image_label.setHelpIcon("nothing")
        image_label.addMouseListener(ScreenMouseListener(self.callbacks))
        scope_button = JButton("Add Selected Domains To Scope",
                               actionPerformed=self.addToScope)
        dns_button = JButton("Resolve DNS", actionPerformed=self.resolveDns)
        #        search_text = JTextField("")
        saveButton = JButton("Save results", actionPerformed=self.saveResults)
        topPane.add(image_label)
        topPane.add(scope_button)
        topPane.add(dns_button)
        topPane.add(saveButton)
        scrollpane = JScrollPane(self.domainTable)
        splitpane.setTopComponent(topPane)
        splitpane.setBottomComponent(scrollpane)
        return splitpane
Example #15
0
class javadocInfo_10( java.lang.Runnable ) :

    #---------------------------------------------------------------------------
    # Name: __init__()
    # Role: Constructor - initialize application variables
    #---------------------------------------------------------------------------
    def __init__( self ) :
        self.prevText = None      # Previously specified user input (text)

    #---------------------------------------------------------------------------
    # Name: run()
    # Role: Instantiate the user class
    # Note: Invoked by the Swing Event Dispatch Thread
    #---------------------------------------------------------------------------
    def run( self ) :
        #-----------------------------------------------------------------------
        # Size the frame to use 1/2 of the screen
        #-----------------------------------------------------------------------
        screenSize = Toolkit.getDefaultToolkit().getScreenSize()
        frameSize  = Dimension( screenSize.width >> 1, screenSize.height >> 1 )
        frame = JFrame(
            'javadocInfo_10',
            size = frameSize,
            defaultCloseOperation = JFrame.EXIT_ON_CLOSE
        )
        #-----------------------------------------------------------------------
        # Reposition the frame to be in the center of the screen
        #-----------------------------------------------------------------------
        frame.setLocation(
            ( screenSize.width  - frameSize.width  ) >> 1,
            ( screenSize.height - frameSize.height ) >> 1
        )
        #-----------------------------------------------------------------------
        # Initialize the list to have exactly 1 element
        #-----------------------------------------------------------------------
        model = DefaultListModel()
        model.addElement( 'One moment please...' )
        self.List = JList(
            model,
            valueChanged  = self.pick,
            selectionMode = ListSelectionModel.SINGLE_SELECTION
        )
        #-----------------------------------------------------------------------
        # Put the List in a ScrollPane and place it in the middle of a pane
        #-----------------------------------------------------------------------
        pane = JPanel( layout = BorderLayout() )
        pane.add(
            JScrollPane(
                self.List,
                minimumSize = ( 300, 50 )
            ),
            BorderLayout.CENTER
        )
        #-----------------------------------------------------------------------
        # Add a TextField [for the URL of the selected entry] at the bottom
        #-----------------------------------------------------------------------
        self.text = JTextField(
            'Enter text...',
            caretUpdate = self.caretUpdate
        )
        pane.add( self.text, BorderLayout.SOUTH )
        #-----------------------------------------------------------------------
        # Add the pane and a scrollable TextArea to a SplitPane in the frame
        #-----------------------------------------------------------------------
        self.area = JEditorPane(
            'text/html',
            '<html><h3>Nothing selected</h3></html>',
            editable = 0
        )
        self.splitPane = JSplitPane(
            JSplitPane.HORIZONTAL_SPLIT,
            pane,
            self.area
        )
        self.splitPane.setDividerLocation( 234 )
        frame.add( self.splitPane )
        #-----------------------------------------------------------------------
        # Create a separate thread to locate & proces the remote URL
        #-----------------------------------------------------------------------
        self.Links   = {}    # Initialize the Links dictionary
        self.classes = None  # complete list of all classes found
        soupTask(
            self.List,       # The visible JList instance
            self.text,       # User input field
            JAVADOC_URL,     # Remote web page URL to be processed
            self.Links,      # Dictionary of links found
        ).execute()
        frame.setVisible( 1 )

    #---------------------------------------------------------------------------
    # Name: pick()
    # Role: ListSelectionListener event handler
    #---------------------------------------------------------------------------
    def pick( self, e ) :
        #-----------------------------------------------------------------------
        # Note: Ignore valueIsAdjusting events
        #-----------------------------------------------------------------------
        if not e.getValueIsAdjusting() :
            List  = self.List
            model = List.getModel()

            #---------------------------------------------------------------
            # Is a "valid" item selected?
            #---------------------------------------------------------------
            index = List.getSelectedIndex()
            if index > -1 :
                choice = model.elementAt( index )
                if self.Links.has_key( choice ) :
                    url = self.Links[ choice ]
                    headerTask( url, self.splitPane ).execute()
            else :
                message = 'Nothing selected'
                comp = self.splitPane.getRightComponent()
                Type = str( comp.getClass() ).split( '.' )[ -1 ]
                if Type == 'JEditorPane' :
                    comp.setText( '<html><h3>%s</h3></html>' % message )
                else :
                    area = JEditorPane(
                        'text/html',
                        '<html><h3>%s</h3></html>' % message,
                        editable = 0
                    )
                    self.splitPane.setRightComponent( area )

    #---------------------------------------------------------------------------
    # Name: caretUpdate()
    # Role: CaretListener event handler used to monitor JTextField for user input
    #---------------------------------------------------------------------------
    def caretUpdate( self, e ) :
        field = e.getSource()
        text  = field.getText()
        if self.prevText == None :
            self.prevText = text

        if self.classes == None :
            result = self.Links.keys()
            if len( result ) > 0 :
                result.sort()
                self.classes = result

        #-----------------------------------------------------------------------
        # Did the user just move the cursor, or did they change the text field?
        #-----------------------------------------------------------------------
        if text != self.prevText :
#           print 'dot: %2d  text: "%s"' % ( e.getDot(), text )
            model = DefaultListModel()
            items = [ item for item in self.classes if item.find( text ) > -1 ]
            if len( items ) > 0 :
                for item in items :
                    model.addElement( item )
            else :
                model.addElement( 'No matching classes found.' )
            self.List.setModel( model )
        self.prevText = text
Example #16
0
    def __init__(self,
                 kconfig_file="Kconfig",
                 config_file=".config",
                 systemLogger=None):
        """[summary]

        Parameters
        ----------
            kconfig_file : string (default: "Kconfig")
                The Kconfig configuration file
            config_file : string (default: ".config")
                The save file which will be used for loading and saving the settings
            systemLogger (default: None)
                A system logger object. If None then print statements are used for logging.
        """
        global log
        if systemLogger:
            log = systemLogger

        # Load Kconfig configuration files
        self.kconfig = Kconfig(kconfig_file)
        setKConfig(self.kconfig)

        if os.path.isfile(config_file):
            log.info(self.kconfig.load_config(config_file))
        elif os.path.isfile(".config"):
            log.info(self.kconfig.load_config(".config"))

        self.tree = KConfigTree(self.kconfig)
        self.tree.addTreeSelectionListener(self.treeSelectionChanged)
        jTreeSP = JScrollPane(self.tree)

        self.jta = JTextArea()
        self.jta.setEditable(False)
        jTextSP = JScrollPane(self.jta)

        toolPanel = JPanel()
        toolPanel.setLayout(BoxLayout(toolPanel, BoxLayout.X_AXIS))
        toolPanel.setBorder(BorderFactory.createEmptyBorder(2, 0, 2, 0))

        toolPanel.add(JLabel("Search: "))

        jSearchPanel = JPanel()
        jSearchPanel.setLayout(BoxLayout(jSearchPanel, BoxLayout.X_AXIS))
        self.jSearchField = JTextField()
        jSearchPanel.setBackground(self.jSearchField.getBackground())
        jSearchPanel.setBorder(self.jSearchField.getBorder())
        self.jSearchField.setBorder(None)
        self.jSearchField.getDocument().addDocumentListener(
            SearchListener(self.tree))
        jSearchPanel.add(self.jSearchField)

        clearSearchButton = JButton(u'\u00d7',
                                    actionPerformed=self.clearSearch)
        d = clearSearchButton.getPreferredSize()
        clearSearchButton.setPreferredSize(Dimension(d.height, d.height))
        clearSearchButton.setBackground(self.jSearchField.getBackground())
        clearSearchButton.setBorder(None)
        clearSearchButton.setOpaque(False)
        clearSearchButton.setContentAreaFilled(False)
        clearSearchButton.setFocusPainted(False)
        jSearchPanel.add(clearSearchButton)

        toolPanel.add(jSearchPanel)

        self.showAllCheckBox = JCheckBox("Show all",
                                         actionPerformed=self.OnShowAllCheck)
        toolPanel.add(self.showAllCheckBox)

        splitPane = JSplitPane(JSplitPane.VERTICAL_SPLIT, jTreeSP, jTextSP)
        splitPane.setOneTouchExpandable(True)
        splitPane.setDividerLocation(300)

        treePanel = JPanel(BorderLayout())
        treePanel.add(toolPanel, BorderLayout.NORTH)
        treePanel.add(splitPane, BorderLayout.CENTER)

        loadSavePanel = JPanel()
        loadSavePanel.setLayout(BoxLayout(loadSavePanel, BoxLayout.X_AXIS))
        loadSavePanel.add(
            JButton("Load", actionPerformed=self.loadConfigDialog))
        loadSavePanel.add(
            JButton("Save as", actionPerformed=self.writeConfigDialog))

        self.rootPanel = JPanel()
        self.rootPanel.setLayout(BorderLayout())
        self.rootPanel.add(loadSavePanel, BorderLayout.PAGE_START)
        self.rootPanel.add(treePanel, BorderLayout.CENTER)
Example #17
0
class View:
    def __init__(self, issues):
        self.json = issues.get_json()
        self.issues_object = issues
        self.issues = issues.get_issues()
        self.scanner_issues = issues.get_scanner_issues()
        self.scanner_panes = {}
        self.scanner_tables = {}
        self.is_scanner_panes = []

        self.set_vuln_tree()
        self.set_tree()
        self.set_scanner_panes()
        self.set_pane()
        self.set_tsl()

    def set_callbacks(self, callbacks):
        self.callbacks = callbacks

    def set_helpers(self, helpers):
        self.helpers = helpers

    def get_helpers(self):
        return self.helpers

    def get_issues(self):
        return self.issues

    def get_scanner_issues(self):
        return self.scanner_issues

    def set_scanner_count(self, is_checked, issue_name, issue_param):
        self.issues_object.set_scanner_count(self, is_checked, issue_name, issue_param)

    def set_is_scanner_pane(self, scanner_pane):
        self.is_scanner_panes.append(scanner_pane)

    def get_is_scanner_pane(self, scanner_pane):
        for pane in self.get_is_scanner_panes():
            if pane == scanner_pane:
                return True

        return False

    def get_is_scanner_panes(self):
        return self.is_scanner_panes

    def set_vuln_tree(self):
        self.vuln_tree = DefaultMutableTreeNode("Vulnerability Classes")

        vulns = self.json["issues"]

        # TODO: Sort the functionality by name and by vuln class
        for vuln_name in vulns:
            vuln = DefaultMutableTreeNode(vuln_name)
            self.vuln_tree.add(vuln)

            parameters = self.json["issues"][vuln_name]["params"]

            for parameter in parameters:
                param_node = DefaultMutableTreeNode(parameter)
                vuln.add(param_node)

    # Creates a JTree object from the checklist
    def set_tree(self):
        self.tree = JTree(self.vuln_tree)
        self.tree.getSelectionModel().setSelectionMode(
            TreeSelectionModel.SINGLE_TREE_SELECTION
        )

    def get_tree(self):
        return self.tree

    # Creates the tabs dynamically using data from the JSON file
    def set_scanner_panes(self):
        issues = self.issues

        for issue in issues:
            issue_name = issue["name"]
            issue_param = issue["param"]

            key = issue_name + "." + issue_param

            top_pane = self.create_request_list_pane(issue_name)
            bottom_pane = self.create_tabbed_pane()

            scanner_pane = JSplitPane(JSplitPane.VERTICAL_SPLIT, top_pane, bottom_pane)

            self.scanner_panes[key] = scanner_pane

    def get_scanner_panes(self):
        return self.scanner_panes

    def create_request_list_pane(self, issue_name):
        request_list_pane = JScrollPane()

        return request_list_pane

    # Creates a JTabbedPane for each vulnerability per functionality
    def create_tabbed_pane(self):
        tabbed_pane = JTabbedPane()
        tabbed_pane.add("Advisory", JScrollPane())
        tabbed_pane.add("Request", JScrollPane())
        tabbed_pane.add("Response", JScrollPane())

        self.tabbed_pane = tabbed_pane

        return tabbed_pane

    def set_tsl(self):
        tsl = TSL(self)
        self.tree.addTreeSelectionListener(tsl)

        return

    def set_pane(self):
        status = JTextArea()
        status.setLineWrap(True)
        status.setText("Nothing selected")
        self.status = status

        request_list_pane = JScrollPane()

        scanner_pane = JSplitPane(JSplitPane.VERTICAL_SPLIT,
                       request_list_pane,
                       self.tabbed_pane
        )

        self.pane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
                    JScrollPane(self.tree),
                    scanner_pane
        )

        self.pane.setDividerLocation(310)
        self.pane.getLeftComponent().setMinimumSize(Dimension(310, 300))

    def get_pane(self):
        return self.pane

    def set_scanner_table(self, scanner_pane, scanner_table):
        self.scanner_tables[scanner_pane] = scanner_table

    def get_scanner_table(self, scanner_pane):
        return self.scanner_tables[scanner_pane]

    def set_scanner_pane(self, scanner_pane):
        request_table_pane = scanner_pane.getTopComponent()
        scanner_table = self.get_scanner_table(scanner_pane)

        request_table_pane.getViewport().setView(scanner_table)
        request_table_pane.revalidate()
        request_table_pane.repaint()

    def create_scanner_pane(self, scanner_pane, issue_name, issue_param):
        scanner_issues = self.get_scanner_issues()
        request_table_pane = scanner_pane.getTopComponent()

        scanner_table_model = ScannerTableModel()
        scanner_table_model.addColumn("Checked")
        scanner_table_model.addColumn("Host")
        scanner_table_model.addColumn("Path")

        # Search all issues for the correct issue. Once found, add it into
        # the scanner table model to be showed in the UI.
        for scanner_issue in scanner_issues:
            is_same_name = scanner_issue.getIssueName() == issue_name
            is_same_param = scanner_issue.getParameter() == issue_param
            is_same_issue = is_same_name and is_same_param

            if is_same_issue:
                scanner_table_model.addRow([
                    False,
                    scanner_issue.getHttpService().getHost(),
                    scanner_issue.getUrl()
                ])

        scanner_table = JTable(scanner_table_model)
        scanner_table.getColumnModel().getColumn(0).setCellEditor(DefaultCellEditor(JCheckBox()))
        scanner_table.putClientProperty("terminateEditOnFocusLost", True)
        scanner_table_listener = ScannerTableListener(self, scanner_table, issue_name, issue_param)
        scanner_table_model.addTableModelListener(scanner_table_listener)
        scanner_table_list_listener = IssueListener(self, scanner_table, scanner_pane, issue_name, issue_param)
        scanner_table.getSelectionModel().addListSelectionListener(scanner_table_list_listener)

        self.set_scanner_table(scanner_pane, scanner_table)

        request_table_pane.getViewport().setView(scanner_table)
        request_table_pane.revalidate()
        request_table_pane.repaint()

    def set_tabbed_pane(self, scanner_pane, request_list, issue_url, issue_name, issue_param):
        tabbed_pane = scanner_pane.getBottomComponent()
        scanner_issues = self.get_scanner_issues()

        for scanner_issue in scanner_issues:
            is_same_url = scanner_issue.getUrl() == issue_url
            is_same_name = scanner_issue.getIssueName() == issue_name
            is_same_param = scanner_issue.getParameter() == issue_param
            is_same_issue = is_same_url and is_same_name and is_same_param

            if is_same_issue:
                current_issue = scanner_issue
                self.set_context_menu(request_list, scanner_issue)
                break

        advisory_tab_pane = self.set_advisory_tab_pane(current_issue)
        tabbed_pane.setComponentAt(0, advisory_tab_pane)

        request_tab_pane = self.set_request_tab_pane(current_issue)
        tabbed_pane.setComponentAt(1, request_tab_pane)

        response_tab_pane = self.set_response_tab_pane(current_issue)
        tabbed_pane.setComponentAt(2, response_tab_pane)

    def set_advisory_tab_pane(self, scanner_issue):
        advisory_pane = JEditorPane()
        advisory_pane.setEditable(False)
        advisory_pane.setEnabled(True)
        advisory_pane.setContentType("text/html")
        link_listener = LinkListener()
        advisory_pane.addHyperlinkListener(link_listener)
        advisory_pane.setText("<html>" +
            "<b>Location</b>: " + scanner_issue.getUrl() + "<br><br>" +
            scanner_issue.getIssueDetail() + "</html>"
        )

        # Set a context menu
        self.set_context_menu(advisory_pane, scanner_issue)

        return JScrollPane(advisory_pane)

    def set_request_tab_pane(self, scanner_issue):
        raw_request = scanner_issue.getRequestResponse().getRequest()
        request_body = StringUtil.fromBytes(raw_request)
        request_body = request_body.encode("utf-8")

        request_tab_textarea = JTextArea(request_body)
        request_tab_textarea.setLineWrap(True)

        # Set a context menu
        self.set_context_menu(request_tab_textarea, scanner_issue)

        return JScrollPane(request_tab_textarea)

    def set_response_tab_pane(self, scanner_issue):
        raw_response = scanner_issue.getRequestResponse().getResponse()
        response_body = StringUtil.fromBytes(raw_response)
        response_body = response_body.encode("utf-8")

        response_tab_textarea = JTextArea(response_body)
        response_tab_textarea.setLineWrap(True)

        # Set a context menu
        self.set_context_menu(response_tab_textarea, scanner_issue)

        return JScrollPane(response_tab_textarea)

    # Pass scanner_issue as argument
    def set_context_menu(self, component, scanner_issue):
        self.context_menu = JPopupMenu()

        repeater = JMenuItem("Send to Repeater")
        repeater.addActionListener(PopupListener(scanner_issue, self.callbacks))

        intruder = JMenuItem("Send to Intruder")
        intruder.addActionListener(PopupListener(scanner_issue, self.callbacks))

        hunt = JMenuItem("Send to HUNT")

        self.context_menu.add(repeater)
        self.context_menu.add(intruder)

        context_menu_listener = ContextMenuListener(component, self.context_menu)
        component.addMouseListener(context_menu_listener)

    def get_context_menu(self):
        return self.context_menu
Example #18
0
    def	registerExtenderCallbacks(self, callbacks):
        # 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("Test Auth | Cookie Repalce ")
        
        # create the log and a lock on which to synchronize when adding log entries
        self._log = ArrayList()
        self._lock = Lock()
        
        # main split pane
        self._splitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT)

        # user jpanel add compenents
        
        self._panel=JPanel()
        self._panel.setLayout(BorderLayout())

        subpanel=JPanel()
        button =JButton("OK")
        subpanel.add(button)
    

        self._panel.add(subpanel,BorderLayout.NORTH)

        # table of log entries
        logTable = Table(self)
        scrollPane = JScrollPane(logTable)
        self._splitpane.setLeftComponent(scrollPane)

        self._panel.add(self._splitpane,BorderLayout.CENTER)

        # tabs with request/response viewers
        tabs = JTabbedPane()
        self._requestViewer = callbacks.createMessageEditor(self, False)
        self._responseViewer = callbacks.createMessageEditor(self, False)
        tabs.addTab("Request", self._requestViewer.getComponent())
        tabs.addTab("Response", self._responseViewer.getComponent())
        self._splitpane.setRightComponent(tabs)
        
        # customize our UI components
        callbacks.customizeUiComponent(self._splitpane)
        # callbacks.customizeUiComponent(logTable)
        # callbacks.customizeUiComponent(scrollPane)
        # callbacks.customizeUiComponent(tabs)

        callbacks.customizeUiComponent(self._panel)
        callbacks.customizeUiComponent(subpanel)
        # callbacks.customizeUiComponent(button)
        
        # add the custom tab to Burp's UI
        callbacks.addSuiteTab(self)
        
        # register ourselves as an HTTP listener
        callbacks.registerHttpListener(self)
        
        return
Example #19
0
class BurpExtender(IBurpExtender, IHttpListener, IProxyListener,
                   IScannerListener, IExtensionStateListener, ITab,
                   IMessageEditorController, AbstractTableModel):
    def registerExtenderCallbacks(self, callbacks):
        # set our extension name
        self._callbacks = callbacks
        self.ATTRIBUTE_QUOTES = "(\".*\")|(\'.*\')"
        callbacks.setExtensionName("Rexsser")
        # obtain our output stream
        self._stdout = PrintWriter(callbacks.getStdout(), True)
        self._helpers = callbacks.getHelpers()
        # register ourselves as an HTTP listener

        self._log = ArrayList()
        self._lock = Lock()

        # main split pane
        self._splitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT)

        # table of log entries
        logTable = Table(self)
        scrollPane = JScrollPane(logTable)
        self._splitpane.setLeftComponent(scrollPane)

        # tabs with request/response viewers
        tabs = JTabbedPane()
        self._requestViewer = callbacks.createMessageEditor(self, False)
        self._responseViewer = callbacks.createMessageEditor(self, False)
        tabs.addTab("Request", self._requestViewer.getComponent())
        tabs.addTab("Response", self._responseViewer.getComponent())
        self._splitpane.setRightComponent(tabs)

        # customize our UI components
        callbacks.customizeUiComponent(self._splitpane)
        callbacks.customizeUiComponent(logTable)
        callbacks.customizeUiComponent(scrollPane)
        callbacks.customizeUiComponent(tabs)

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

        return

    def getTabCaption(self):
        return "Rexsser"

    def getUiComponent(self):
        return self._splitpane

    def getRowCount(self):
        try:
            return self._log.size()
        except:
            return 0

    def getColumnCount(self):
        return 4

    def getColumnName(self, columnIndex):
        if columnIndex == 0:
            return "Detail"
        if columnIndex == 1:
            return "Parameter"
        if columnIndex == 2:
            return "URL"
        if columnIndex == 3:
            return "WAF Status"
        return ""

    def getValueAt(self, rowIndex, columnIndex):
        logEntry = self._log.get(rowIndex)
        if columnIndex == 0:
            return logEntry._detail
        if columnIndex == 1:
            return logEntry._parameter
        if columnIndex == 2:
            return logEntry._url
        if columnIndex == 3:
            return logEntry._waf
        return ""

    def getHttpService(self):
        return self._currentlyDisplayedItem.getHttpService()

    def getRequest(self):
        return self._currentlyDisplayedItem.getRequest()

    def getResponse(self):
        return self._currentlyDisplayedItem.getResponse()

    def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo):
        if messageIsRequest:
            return

        self.toolFlag = toolFlag
        patt = "var (\w+).*=.*(.*)"
        payloads = [
            "fixedvaluehopefullyexists", "random1'ss", "random2\"ss",
            "dumm</script>ss", "<h1>duteer</h1>ss"
        ]
        for payload in payloads:
            if self._callbacks.getToolName(toolFlag) == "Proxy":
                self.processTestcases(patt, messageInfo, payload)

    def issues(self, messageInfo, detail, param, waf):
        self._lock.acquire()
        row = self._log.size()
        self._log.add(
            LogEntry(param,
                     self._callbacks.saveBuffersToTempFiles(messageInfo),
                     self._helpers.analyzeRequest(messageInfo).getUrl(),
                     detail, waf))
        self.fireTableRowsInserted(row, row)
        self._lock.release()

    def processTestcases(self, patt, messageInfo, payload):
        irequest = self._helpers.analyzeRequest(messageInfo)
        url = irequest.getUrl()
        response = messageInfo.getResponse()
        httpservice = messageInfo.getHttpService()
        inject = URLEncoder.encode(payload, "UTF-8")
        if self._callbacks.isInScope(url):
            #patt = "var (\w+).*=.*('|\")(.*)('|\")"
            words = []
            x = re.findall(patt, self._helpers.bytesToString(response))
            for y in x:
                words.append(y[0])
            sortedwords = list(set(words))
            if len(sortedwords) > 0:
                for word in sortedwords:
                    param = self._helpers.buildParameter(
                        word, inject, IParameter.PARAM_URL)
                    newrequest = self._helpers.addParameter(
                        messageInfo.getRequest(), param)
                    t = threading.Thread(target=self.makeRequest,
                                         args=[
                                             messageInfo.getHttpService(),
                                             newrequest, word, payload
                                         ])
                    t.daemon = True
                    t.start()

    def makeRequest(self, httpservice, requestBytes, word, payload):
        #useHttps = 1 if httpservice.getProtocol() == 'https' else 0
        #print(self._helpers.bytesToString(requestBytes))
        bRequestResponse = self._callbacks.makeHttpRequest(
            httpservice, requestBytes)
        tResp = bRequestResponse.getResponse()
        status = self._helpers.analyzeResponse(tResp).getStatusCode()
        url = self._helpers.analyzeRequest(bRequestResponse).getUrl()
        response = self._helpers.bytesToString(tResp)
        if status != 302:
            if status == 200:
                waf = "Allowed"
            else:
                waf = "Unknown"
            if payload in response:
                if payload == 'fixedvaluehopefullyexists':
                    str1 = word + " is a valid parameter"
                    str2 = self.definesContext(payload, response)
                    self.issues(bRequestResponse, str2 + " " + str1, word, waf)
                if payload == 'random1\'ss':
                    str1 = word + " single quote reflection allowed"
                    str2 = self.definesContext(payload, response)
                    self.issues(bRequestResponse, str2 + " " + str1, word, waf)
                if payload == 'random2"ss':
                    str1 = word + " Double quote allowed"
                    str2 = self.definesContext(payload, response)
                    self.issues(bRequestResponse, str2 + " " + str1, word, waf)
                if payload == 'dumm</script>ss':
                    str1 = word + " Script tags allowed"
                    str2 = self.definesContext(payload, response)
                    self.issues(bRequestResponse, str2 + " " + str1, word, waf)
                if payload == '<h1>duteer</h1>ss':
                    str1 = word + " HTML tags allowed"
                    str2 = self.definesContext(payload, response)
                    self.issues(bRequestResponse, str2 + " " + str1, word, waf)
            else:
                pass
        if status == 403:
            self.issues(bRequestResponse, "", word, "Blocked")

    def definesContext(self, reflection, html):
        indx = html.find(reflection)
        q = html[indx - 1]
        q2 = html[indx + len(reflection)]
        if q in reflection and q == '"':
            return "[Vulnerable][attribute][\"]"
        if q in reflection and q == "'":
            return "[Vulnerable][attribute][']"
        else:
            return "[Possible]"
Example #20
0
    def registerExtenderCallbacks(self, callbacks):
        # 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("Burp Scope Monitor Experimental")

        self.GLOBAL_HANDLER_ANALYZED = False
        self.GLOBAL_HANDLER = False
        self.STATUS = False
        self.AUTOSAVE_REQUESTS = 10
        self.AUTOSAVE_TIMEOUT = 600  # 10 minutes should be fine
        self.CONFIG_INSCOPE = True

        self.BAD_EXTENSIONS_DEFAULT = [
            '.gif', '.png', '.js', '.woff', '.woff2', '.jpeg', '.jpg', '.css',
            '.ico', '.m3u8', '.ts', '.svg'
        ]
        self.BAD_MIMES_DEFAULT = [
            'gif', 'script', 'jpeg', 'jpg', 'png', 'video', 'mp2t'
        ]

        self.BAD_EXTENSIONS = self.BAD_EXTENSIONS_DEFAULT
        self.BAD_MIMES = self.BAD_MIMES_DEFAULT

        # create the log and a lock on which to synchronize when adding log entries

        self._currentlyDisplayedItem = None

        self.SELECTED_MODEL_ROW = 0
        self.SELECTED_VIEW_ROW = 0

        self._log = ArrayList()
        self._fullLog = ArrayList()
        self._lock = Lock()
        self._lockFile = Lock()

        # main split pane
        self._parentPane = JTabbedPane()

        self._splitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT)

        ##### config pane
        self._config = JTabbedPane()

        config = JPanel()
        iexport = JPanel()

        #config.setLayout(BorderLayout())
        config.setLayout(None)
        iexport.setLayout(None)

        # config radio button
        X_BASE = 40
        Y_OFFSET = 5
        Y_OPTION = 200
        Y_OPTION_SPACING = 20
        Y_CHECKMARK_SPACING = 20

        self.showAllButton = JRadioButton(SHOW_ALL_BUTTON_LABEL, True)
        self.showNewButton = JRadioButton(SHOW_NEW_BUTTON_LABEL, False)
        self.showTestedButton = JRadioButton(SHOW_TEST_BUTTON_LABEL, False)

        self.showAllButton.setBounds(40, 60 + Y_OFFSET, 400, 30)
        self.showNewButton.setBounds(40, 80 + Y_OFFSET, 400, 30)
        self.showTestedButton.setBounds(40, 100 + Y_OFFSET, 400, 30)
        #self.showNewButton = JRadioButton(SHOW_NEW_BUTTON_LABEL, False)
        #self.showTestedButton = JRadioButton(SHOW_TEST_BUTTON_LABEL, False)

        self.showAllButton.addActionListener(self.handleRadioConfig)
        self.showNewButton.addActionListener(self.handleRadioConfig)
        self.showTestedButton.addActionListener(self.handleRadioConfig)

        self.clearButton = JButton("Clear")
        self.clearButton.addActionListener(self.handleClearButton)
        self.clearButton.setBounds(40, 20, 100, 30)

        self.startButton = JButton(MONITOR_ON_LABEL)
        self.startButton.addActionListener(self.handleStartButton)
        self.startButton.setBounds(150, 20, 200, 30)

        self.badExtensionsLabel = JLabel("Ignore extensions:")
        self.badExtensionsLabel.setBounds(X_BASE, 150, 200, 30)

        self.badExtensionsText = JTextArea("")
        self.loadBadExtensions()
        self.badExtensionsText.setBounds(X_BASE, 175, 310, 30)

        self.badExtensionsButton = JButton("Save")
        self.badExtensionsButton.addActionListener(
            self.handleBadExtensionsButton)
        self.badExtensionsButton.setBounds(355, 175, 70, 30)

        self.badExtensionsDefaultButton = JButton("Load Defaults")
        self.badExtensionsDefaultButton.addActionListener(
            self.handleBadExtensionsDefaultButton)
        self.badExtensionsDefaultButton.setBounds(430, 175, 120, 30)

        self.badMimesLabel = JLabel("Ignore mime types:")
        self.badMimesLabel.setBounds(X_BASE, 220, 200, 30)

        self.badMimesText = JTextArea("")
        self.loadBadMimes()
        self.badMimesText.setBounds(X_BASE, 245, 310, 30)

        self.badMimesButton = JButton("Save")
        self.badMimesButton.addActionListener(self.handleBadMimesButton)
        self.badMimesButton.setBounds(355, 245, 70, 30)

        self.badMimesDefaultButton = JButton("Load Defaults")
        self.badMimesDefaultButton.addActionListener(
            self.handleBadMimesDefaultButton)
        self.badMimesDefaultButton.setBounds(430, 245, 120, 30)

        self.otherLabel = JLabel("Other:")
        self.otherLabel.setBounds(40, 300, 120, 30)

        self.otherLabel2 = JLabel("Other:")
        self.otherLabel2.setBounds(X_BASE, Y_OPTION, 120, 30)

        self.autoSaveOption = JCheckBox("Auto save periodically")
        self.autoSaveOption.setSelected(True)
        self.autoSaveOption.addActionListener(self.handleAutoSaveOption)
        self.autoSaveOption.setBounds(X_BASE, Y_OPTION + Y_CHECKMARK_SPACING,
                                      420, 30)

        self.repeaterOptionButton = JCheckBox(
            "Repeater request automatically marks as analyzed")
        self.repeaterOptionButton.setSelected(True)
        self.repeaterOptionButton.addActionListener(
            self.handleRepeaterOptionButton)
        self.repeaterOptionButton.setBounds(50, 330, 420, 30)

        self.scopeOptionButton = JCheckBox("Follow Burp Target In Scope rules")
        self.scopeOptionButton.setSelected(True)
        self.scopeOptionButton.addActionListener(self.handleScopeOptionButton)
        self.scopeOptionButton.setBounds(50, 350, 420, 30)

        self.startOptionButton = JCheckBox("Autostart Scope Monitor")
        self.startOptionButton.setSelected(True)
        self.startOptionButton.addActionListener(self.handleStartOption)
        self.startOptionButton.setBounds(50, 350 + Y_OPTION_SPACING, 420, 30)

        self.markTestedRequestsProxy = JCheckBox(
            "Color request in Proxy tab if analyzed")
        self.markTestedRequestsProxy.setSelected(True)
        self.markTestedRequestsProxy.addActionListener(
            self.handleTestedRequestsProxy)
        self.markTestedRequestsProxy.setBounds(50, 350 + Y_OPTION_SPACING * 2,
                                               420, 30)

        self.markNotTestedRequestsProxy = JCheckBox(
            "Color request in Proxy tab if NOT analyzed")
        self.markNotTestedRequestsProxy.setSelected(True)
        self.markNotTestedRequestsProxy.addActionListener(
            self.handleNotTestedRequestsProxy)
        self.markNotTestedRequestsProxy.setBounds(50,
                                                  350 + Y_OPTION_SPACING * 3,
                                                  420, 30)

        self.saveButton = JButton("Save now")
        self.saveButton.addActionListener(self.handleSaveButton)
        self.saveButton.setBounds(X_BASE + 320, 95, 90, 30)

        self.loadButton = JButton("Load now")
        self.loadButton.addActionListener(self.handleLoadButton)
        self.loadButton.setBounds(X_BASE + 420, 95, 90, 30)

        self.selectPath = JButton("Select path")
        self.selectPath.addActionListener(self.selectExportFile)
        self.selectPath.setBounds(X_BASE + 530, 60, 120, 30)

        self.selectPathText = JTextArea("")
        self.selectPathText.setBounds(X_BASE, 60, 510, 30)

        self.selectPathLabel = JLabel("State file:")
        self.selectPathLabel.setBounds(X_BASE, 30, 200, 30)

        bGroup = ButtonGroup()

        bGroup.add(self.showAllButton)
        bGroup.add(self.showNewButton)
        bGroup.add(self.showTestedButton)

        config.add(self.clearButton)
        config.add(self.startButton)
        config.add(self.startOptionButton)
        config.add(self.showAllButton)
        config.add(self.showNewButton)
        config.add(self.showTestedButton)

        config.add(self.badExtensionsButton)
        config.add(self.badExtensionsText)
        config.add(self.badExtensionsLabel)

        config.add(self.badMimesButton)
        config.add(self.badMimesText)
        config.add(self.badMimesLabel)

        config.add(self.badExtensionsDefaultButton)
        config.add(self.badMimesDefaultButton)

        config.add(self.otherLabel)
        config.add(self.repeaterOptionButton)
        config.add(self.scopeOptionButton)
        config.add(self.markTestedRequestsProxy)
        config.add(self.markNotTestedRequestsProxy)

        iexport.add(self.saveButton)
        iexport.add(self.loadButton)
        iexport.add(self.selectPath)
        iexport.add(self.selectPathText)
        iexport.add(self.selectPathLabel)
        iexport.add(self.otherLabel2)
        iexport.add(self.autoSaveOption)

        self._config.addTab("General", config)
        self._config.addTab("Import/Export", iexport)

        ##### end config pane

        self._parentPane.addTab("Monitor", self._splitpane)
        self._parentPane.addTab("Config", self._config)

        # table of log entries
        self.logTable = Table(self)

        #self.logTable.setDefaultRenderer(self.logTable.getColumnClass(0), ColoredTableCellRenderer(self))

        self.logTable.setAutoCreateRowSorter(True)
        self.logTable.setRowSelectionAllowed(True)

        renderer = ColoredTableCellRenderer(self)
        #column = TableColumn(0, 190, renderer, None)

        print 'Initiating... '

        # this could be improved by fetching initial dimensions
        self.logTable.getColumn("URL").setPreferredWidth(720)  # noscope
        self.logTable.getColumn("URL").setResizable(True)

        self.logTable.getColumn("Checked").setCellRenderer(renderer)
        self.logTable.getColumn("Checked").setPreferredWidth(80)
        self.logTable.getColumn("Checked").setMaxWidth(80)

        self.logTable.getColumn("Method").setPreferredWidth(120)
        #self.logTable.getColumn("Method").setMaxWidth(120)
        self.logTable.getColumn("Method").setResizable(True)

        self.logTable.getColumn("Time").setPreferredWidth(120)  # noscope
        self.logTable.getColumn("Time").setResizable(True)

        scrollPane = JScrollPane(self.logTable)
        self._splitpane.setLeftComponent(scrollPane)

        # tabs with request/response viewers
        tabs = JTabbedPane()
        self._requestViewer = callbacks.createMessageEditor(self, False)
        self._responseViewer = callbacks.createMessageEditor(self, False)
        tabs.addTab("Request", self._requestViewer.getComponent())
        tabs.addTab("Response", self._responseViewer.getComponent())
        self._splitpane.setRightComponent(tabs)

        ## Row sorter shit

        #self._tableRowSorterAutoProxyAutoAction = CustomTableRowSorter(self.logTable.getModel())
        #self.logTable.setRowSorter(self._tableRowSorterAutoProxyAutoAction)

        markAnalyzedButton = JMenuItem("Mark Requests as Analyzed")
        markAnalyzedButton.addActionListener(markRequestsHandler(self, True))

        markNotAnalyzedButton = JMenuItem("Mark Requests as NOT Analyzed")
        markNotAnalyzedButton.addActionListener(
            markRequestsHandler(self, False))

        sendRequestMenu = JMenuItem("Send Request to Repeater")
        sendRequestMenu.addActionListener(sendRequestRepeater(self))

        deleteRequestMenu = JMenuItem("Delete request")
        deleteRequestMenu.addActionListener(deleteRequestHandler(self))

        self.menu = JPopupMenu("Popup")
        self.menu.add(markAnalyzedButton)
        self.menu.add(markNotAnalyzedButton)
        self.menu.add(sendRequestMenu)
        self.menu.add(deleteRequestMenu)

        # customize our UI components
        callbacks.customizeUiComponent(self._parentPane)
        callbacks.customizeUiComponent(self._splitpane)
        callbacks.customizeUiComponent(self._config)
        callbacks.customizeUiComponent(config)
        callbacks.customizeUiComponent(self.logTable)
        callbacks.customizeUiComponent(scrollPane)
        callbacks.customizeUiComponent(tabs)

        callbacks.registerContextMenuFactory(self)
        callbacks.registerExtensionStateListener(self)
        callbacks.registerScannerCheck(passiveScanner(self))

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

        # register ourselves as an HTTP listener
        callbacks.registerHttpListener(self)

        self.loadConfigs()

        print "Loaded!"

        print "Experimental import state.. "
        self.importState("")

        self.SC = sched.scheduler(time.time, time.sleep)
        self.SCC = self.SC.enter(10, 1, self.autoSave, (self.SC, ))
        self.SC.run()

        return
class BurpExtender(IBurpExtender, ITab, IHttpListener, IMessageEditorController, AbstractTableModel):
    
    def	registerExtenderCallbacks(self, callbacks):
    
        # 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("Reflected XSS Detector")
        
        # create the log and a lock on which to synchronize when adding log entries
        self._log = ArrayList()
        self._lock = Lock()
        
        # main split pane
        self._splitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT)
        
        # table of log entries
        logTable = Table(self)
        scrollPane = JScrollPane(logTable)
        self._splitpane.setLeftComponent(scrollPane)

        logTable.addMouseListener( CMouseListener(self) )

        # tabs with request/response viewers
        tabs = JTabbedPane()
        self._requestViewer = callbacks.createMessageEditor(self, False)
        self._responseViewer = callbacks.createMessageEditor(self, False)
        tabs.addTab("Response", self._responseViewer.getComponent())
        tabs.addTab("Request", self._requestViewer.getComponent())
        self._splitpane.setRightComponent(tabs)
        
        # customize our UI components
        callbacks.customizeUiComponent(self._splitpane)
        callbacks.customizeUiComponent(logTable)
        callbacks.customizeUiComponent(scrollPane)
        callbacks.customizeUiComponent(tabs)
        
        # add the custom tab to Burp's UI
        callbacks.addSuiteTab(self)
        
        # register ourselves as an HTTP listener
        callbacks.registerHttpListener(self)
        
        return
        
    #
    # implement ITab
    #
    
    def getTabCaption(self):
        return "R-XSS Detector"
    
    def getUiComponent(self):
        return self._splitpane
        
    #
    # implement IHttpListener
    #
    
    def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo):
    
        if not messageIsRequest:
            # create a new log entry with the message details
            mi = self._callbacks.saveBuffersToTempFiles(messageInfo)
            tmp = self._helpers.analyzeRequest(messageInfo).getParameters()
            response = bytearray(mi.getResponse())
            self._lock.acquire()
            for p in tmp:
                if response.find(str(p.getValue())) > 0:
                    row = self._log.size()
                    headers = self._helpers.analyzeResponse(mi.getResponse()).getHeaders()
                    cc = ""
                    for h in headers:
                        if h.find("Content-Type:") == 0:
                            cc = h[14:].lower()
                    accepted_ccs = ['text/html', 'application/json', 'application/x-javascript']
                    if cc in accepted_ccs:
                        self._log.add( LogEntry(toolFlag, mi, self._helpers.analyzeRequest(messageInfo).getUrl(), p.getType(), p.getName(), p.getValue() ) )
                        self.fireTableRowsInserted(row, row)
            self._lock.release()

        return

    #
    # extend AbstractTableModel
    #
    
    def getRowCount(self):
        try:
            return self._log.size()
        except:
            return 0

    def getColumnCount(self):
        return 4

    def getColumnName(self, columnIndex):
        if columnIndex == 0:
            return "Tool"
        if columnIndex == 1:
            return "URL"
        if columnIndex == 2:
            return "Status"
        if columnIndex == 3:
            return "Params"
        return ""
    def getRowAt(self, rowIndex):
        return self._log.get(rowIndex)

    def getValueAt(self, rowIndex, columnIndex):
        logEntry = self._log.get(rowIndex)
        if columnIndex == 0:
            return self._callbacks.getToolName(logEntry._tool)
        if columnIndex == 1:
            return logEntry._url.toString()
        if columnIndex == 2:
            return logEntry._requestResponse.getStatusCode()   
        if columnIndex == 3:
            types = ['GET','POST','COOKIE']
            return str(logEntry._key)+" ("+types[logEntry._key_type]+") = "+logEntry._value
        return ""

    #
    # implement IMessageEditorController
    # this allows our request/response viewers to obtain details about the messages being displayed
    #
    
    def getHttpService(self):
        return self._currentlyDisplayedItem.getHttpService()

    def getRequest(self):
        return self._currentlyDisplayedItem.getRequest()

    def getResponse(self):
        return self._currentlyDisplayedItem.getResponse()
Example #22
0
    def create(self):

        # Estilo general para todas las sub-tab.
        gBC = GridBagConstraints()
        gBC.fill = GridBagConstraints.BOTH
        gBC.ipadx = 5
        gBC.ipady = 5
        gBC.insets = Insets(0, 5, 5, 5)
        gBC.weightx = 0.5
        #gBC.weighty = 0.7

        #######################################
        ###   Creamos la primera sub-tab. (MASHUP)
        #######################################
        tab_1 = JPanel(GridBagLayout())
        tab_1_jlabelAyuda = JLabel(
            '<html><i>&#8226Tip: This Mashup receive one or more keywords in order to generate a list of possible passwords</i></html>'
        )
        tab_1_jlabelAyuda.setFont(Font("Serif", 0, 12))

        gBC.gridx = 0
        gBC.gridy = 0
        tab_1.add(
            JLabel('<html><font color=green><i>Income:</i></font></html>'),
            gBC)

        gBC.gridy = 1
        tab_1.add(JLabel('<html><b>&#8226 Name:</b></html>'), gBC)
        gBC.gridy = 2
        tab_1.add(self._tab1_nombre, gBC)

        gBC.gridy = 3
        tab_1.add(JLabel('<html><b>&#8226 Surname:</b></html>'), gBC)
        gBC.gridy = 4
        tab_1.add(self._tab1_apellido, gBC)

        gBC.gridy = 5
        tab_1.add(JLabel('<html><b>&#8226 Birthdate: (DDMMYYYY)</b></html>'),
                  gBC)
        gBC.gridy = 6
        tab_1.add(self._tab1_FNacimiento, gBC)

        gBC.gridy = 7
        tab_1.add(JLabel('<html><b>&#8226 Pet:</b></html>'), gBC)
        gBC.gridy = 8
        tab_1.add(self._tab1_mascota, gBC)

        gBC.gridy = 9
        tab_1.add(JLabel('<html><b>&#8226 Anyother:</b></html>'), gBC)
        gBC.gridy = 10
        tab_1.add(self._tab1_otro, gBC)

        gBC.gridy = 11
        tab_1.add(JLabel('<html><b>&#8226 Passwd Min Size:</b></html>'), gBC)
        gBC.gridy = 12
        tab_1.add(self._tab1_minsize, gBC)

        gBC.gridy = 13
        tab_1.add(JLabel('<html><b>&#8226 Passwd Max Size:</b></html>'), gBC)
        gBC.gridy = 14
        tab_1.add(self._tab1_maxsize, gBC)

        gBC.gridy = 15
        tab_1.add(
            JLabel(
                '<html><b>&#8226 Especial Chars: (comma separated)</b></html>'
            ), gBC)
        gBC.gridy = 16
        tab_1.add(self._tab1_specialchars, gBC)

        gBC.gridy = 17
        tab_1.add(self._tab1_transformations, gBC)

        gBC.gridy = 18
        tab_1.add(self._tab1_firstcapital, gBC)

        gBC.gridy = 19
        tab_1.add(JButton('Mashup!', actionPerformed=self.mashup), gBC)

        gBC.gridy = 20
        gBC.gridwidth = 3
        tab_1.add(JSeparator(), gBC)
        gBC.gridwidth = 1

        gBC.gridy = 21
        gBC.gridwidth = 3
        tab_1.add(tab_1_jlabelAyuda, gBC)
        gBC.gridwidth = 1

        gBC.gridx = 1
        gBC.gridy = 0
        gBC.gridheight = 20
        gBC.weightx = 0
        tab_1.add(JSeparator(SwingConstants.VERTICAL), gBC)
        gBC.gridheight = 1
        gBC.weightx = 0.5

        gBC.gridx = 2
        gBC.gridy = 0
        tab_1.add(
            JLabel('<html><font color=green><i>Outcome:</i></font></html>'),
            gBC)

        gBC.gridy = 1
        gBC.gridwidth = 2
        gBC.gridheight = 18
        tab_1.add(self._tab1_feedback_sp, gBC)
        gBC.gridwidth = 1
        gBC.gridheight = 1

        gBC.gridy = 19
        tab_1.add(
            JButton('Copy to clipboard!', actionPerformed=self.cpy_clipboard),
            gBC)

        #######################################
        ###   Creamos la segunda sub-tab. (REDIRECT)
        #######################################
        tab_2 = JPanel(GridBagLayout())
        tab_2_jlabelAyuda = JLabel(
            '<html><i>&#8226Tip: This Redirect receive a pair of hosts x,y in order to redirect from x to y.</i></html>'
        )
        tab_2_jlabelAyuda.setFont(Font("Serif", 0, 12))

        gBC.gridx = 0
        gBC.gridy = 0
        tab_2.add(
            JLabel('<html><b>&#8226 From: (i.e. www.facebook.com)</b></html>'),
            gBC)
        gBC.gridx = 1
        gBC.gridy = 0
        tab_2.add(self._tab2_JTFa, gBC)

        gBC.gridx = 2
        gBC.gridy = 0
        tab_2.add(
            JLabel('<html><b>&#8226 To: (i.e. www.myhomepage.es)</b></html>'),
            gBC)
        gBC.gridx = 3
        gBC.gridy = 0
        tab_2.add(self._tab2_JTFaa, gBC)

        gBC.gridx = 0
        gBC.gridy = 1
        gBC.gridwidth = 4
        tab_2.add(JSeparator(), gBC)
        gBC.gridwidth = 1

        gBC.gridx = 0
        gBC.gridy = 2
        tab_2.add(JLabel('<html><b>&#8226 From:</b></html>'), gBC)
        gBC.gridx = 1
        gBC.gridy = 2
        tab_2.add(self._tab2_JTFb, gBC)

        gBC.gridx = 2
        gBC.gridy = 2
        tab_2.add(JLabel('<html><b>&#8226 To:</b></html>'), gBC)
        gBC.gridx = 3
        gBC.gridy = 2
        tab_2.add(self._tab2_JTFbb, gBC)

        gBC.gridx = 0
        gBC.gridy = 3
        gBC.gridwidth = 4
        tab_2.add(self._tab2_boton, gBC)
        gBC.gridwidth = 1

        gBC.gridx = 0
        gBC.gridy = 4
        gBC.gridwidth = 4
        gBC.insets = Insets(100, 10, 5, 10)
        tab_2.add(JSeparator(), gBC)
        gBC.gridwidth = 1
        gBC.insets = Insets(5, 10, 5, 10)

        gBC.gridx = 0
        gBC.gridy = 5
        gBC.gridwidth = 4
        tab_2.add(tab_2_jlabelAyuda, gBC)
        gBC.gridwidth = 1

        #######################################
        ###   Creamos la tercera sub-tab. (LOADER)
        #######################################
        tab_3 = JPanel(GridBagLayout())
        tab_3_jlabelAyuda = JLabel(
            '<html><i>&#8226Tip: This Loader receive a list of Hosts or IPs that will be added to the Burp Scope.</i></html>'
        )
        tab_3_jlabelAyuda.setFont(Font("Serif", 0, 12))

        gBC.gridx = 0
        gBC.gridy = 0
        tab_3.add(
            JLabel(
                '<html><font color=green><i>List of targets: (i.e. http://www.mytargetweb.com)</i></font></html>'
            ), gBC)
        gBC.gridy = 1
        gBC.gridheight = 10
        gBC.weighty = 0.5
        tab_3.add(self._tab3_urls_sp, gBC)
        gBC.gridheight = 1
        gBC.weighty = 0
        gBC.gridy = 11
        tab_3.add(
            JButton('Load Into Target => Scope!', actionPerformed=self.loader),
            gBC)

        gBC.gridy = 12
        gBC.gridwidth = 5
        gBC.insets = Insets(100, 10, 5, 10)
        tab_3.add(JSeparator(), gBC)
        gBC.gridwidth = 1
        gBC.insets = Insets(5, 10, 5, 10)

        gBC.gridy = 13
        tab_3.add(tab_3_jlabelAyuda, gBC)

        #######################################
        ###   Creamos la cuarta sub-tab. (HEADERS)
        #######################################
        tab_4_jlabelAyuda = JLabel(
            "<html><i>&#8226Tip: This Headers records all unique headers that appear in every host, check out the security headers.</i></html>"
        )
        tab_4_jlabelAyuda.setFont(Font("Serif", 0, 12))

        tab_4_jLabelRecomendacion = JLabel(
            "<html>&#8226<b>Server</b>: Don't give away much information.<br> &#8226<b>Content-Security-Policy</b>: Protect your site from XSS attacks by whitelisting sources of approved content.<br> &#8226<b>Strict-Transport-Security</b>: Enforce the browser to use HTTPS.<br> &#8226<b>Public-Key-Pins</b>: Protect your site from MITM attacks.<br> &#8226<b>X-Content-Type-Options</b>: the valid value is -> nosniff .<br> &#8226<b>X-Frame-Options</b>: tells the browser whether you want to allow your site to be framed or not.<br> &#8226<b>X-XSS-Protection</b>: the best value is -> 1; mode=block .</html>"
        )
        tab_4_jLabelRecomendacion.setFont(Font("Dialog", 0, 13))

        tab_4 = JPanel(GridBagLayout())
        splitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT)
        tab_4_top = JPanel(GridBagLayout())
        tab_4_bottom = JPanel(GridBagLayout())

        gBC_table = GridBagConstraints()
        gBC_table.fill = GridBagConstraints.BOTH
        gBC_table.ipadx = 5
        gBC_table.ipady = 5
        gBC_table.insets = Insets(5, 10, 5, 10)
        gBC_table.weightx = 1
        gBC_table.weighty = 1

        tabla_datos = []
        tabla_headers = ('Severity', 'Header', 'Value', 'Host')
        self._tab4_tabla_model = DefaultTableModel(tabla_datos, tabla_headers)
        tabla_ej = JTable(self._tab4_tabla_model)
        tabla_example = JScrollPane(tabla_ej,
                                    JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
                                    JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED)

        gBC_table.gridx = 0
        gBC_table.gridy = 0
        gBC_table.gridheight = 5
        tab_4_top.add(tabla_example, gBC_table)
        gBC_table.gridheight = 1

        gBC_table.weightx = 0.5
        gBC_table.weighty = 0
        gBC_table.gridwidth = 2
        gBC_table.gridx = 0
        gBC_table.gridy = 0
        tab_4_bottom.add(JSeparator(), gBC_table)
        gBC_table.gridy = 1
        tab_4_bottom.add(tab_4_jlabelAyuda, gBC_table)
        gBC_table.gridy = 2
        tab_4_bottom.add(tab_4_jLabelRecomendacion, gBC_table)

        splitpane.setTopComponent(tab_4_top)
        splitpane.setBottomComponent(tab_4_bottom)
        gBC_table.weightx = 1
        gBC_table.weighty = 1
        gBC_table.gridx = 0
        gBC_table.gridy = 0
        tab_4.add(splitpane, gBC_table)

        #######################################
        ###   Creamos la quinta sub-tab. (ACTIVE SCAN)
        #######################################
        tab_5 = JPanel(GridBagLayout())
        tab_5_jlabelAyuda = JLabel(
            '<html><i>&#8226Tip: This Quick Scan receive a list of targets and launch an active scan.</i></html>'
        )
        tab_5_jlabelAyuda.setFont(Font("Serif", 0, 12))
        tab_5_jlabelWarning = JLabel(
            '<html><font color=red><i>&#8226Warning: Active scanning generates large numbers of requests which are malicious in form and which may result in compromise of the application. You should use this scanning mode with caution, only with the explicit permission of the application owner. For more information, read the documentation of active scan, Burp Suite.</font></i></html>'
        )
        tab_5_jlabelWarning.setFont(Font("Dialog", 0, 13))

        gBC.gridx = 0
        gBC.gridy = 0
        tab_5.add(
            JLabel(
                '<html><font color=green><i>List of targets: (i.e. http://192.168.1.1/index.html)</i></font></html>'
            ), gBC)
        gBC.gridy = 1
        gBC.gridheight = 8
        gBC.weighty = 0.5
        tab_5.add(self._tab5_target_sp, gBC)
        gBC.gridheight = 1
        gBC.weighty = 0
        gBC.gridy = 9
        tab_5.add(JButton('Launch Scan!', actionPerformed=self.do_active_scan),
                  gBC)

        gBC.gridy = 10
        gBC.gridwidth = 5
        gBC.insets = Insets(100, 10, 5, 10)
        tab_5.add(JSeparator(), gBC)
        gBC.gridwidth = 1
        gBC.insets = Insets(5, 10, 5, 10)

        gBC.gridy = 11
        tab_5.add(tab_5_jlabelAyuda, gBC)
        gBC.gridy = 12
        tab_5.add(tab_5_jlabelWarning, gBC)

        #######################################
        ###   Creamos la ultima sub-tab.
        #######################################
        tab_about = JPanel(GridBagLayout())

        gBC_about = GridBagConstraints()
        gBC_about.fill = GridBagConstraints.HORIZONTAL
        gBC_about.ipadx = 5
        gBC_about.ipady = 5
        gBC_about.insets = Insets(5, 10, 5, 10)
        gBC_about.weightx = 1
        gBC_about.weighty = 1

        Jlabel1 = JLabel('<html><b>Plug-in L-Tools</b></html>')
        Jlabel1.setFont(Font("Dialog", 1, 18))
        jlabel2 = JLabel(
            '<html>This Plug-in provides utilities for pentesters, researchers and developers, in order to support their work.</html>'
        )
        jlabel3 = JLabel('<html><b>CC-BY 4.0, 2017. Gino Angles</b></html>')
        jlabel3.setFont(Font("Dialog", 1, 14))
        jlabel4 = JLabel('<html><b>License</b></html>')
        jlabel4.setFont(Font("Dialog", 1, 14))
        jlabel5 = JLabel(
            '<html><img alt="Licensed under a Creative Commons BY" style="border-width:0" src="https://licensebuttons.net/l/by/4.0/88x31.png"></html>'
        )
        jlabel6 = JLabel(
            '<html>This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution 4.0 International License</a>.</html>'
        )
        jlabel7 = JLabel('<html><b>Dependencies</b></html>')
        jlabel7.setFont(Font("Dialog", 1, 14))
        jlabel8 = JLabel('Jython +2.7')
        jlabel9 = JLabel('http://www.jython.org')

        gBC_about.gridx = 0
        gBC_about.gridy = 0
        tab_about.add(Jlabel1, gBC_about)
        gBC_about.gridy = 1
        tab_about.add(jlabel2, gBC_about)
        gBC_about.gridy = 2
        tab_about.add(jlabel3, gBC_about)

        gBC_about.gridy = 3
        gBC_about.gridwidth = 5
        tab_about.add(JSeparator(), gBC_about)
        gBC_about.gridwidth = 1

        gBC_about.gridy = 4
        tab_about.add(jlabel4, gBC_about)
        gBC_about.gridy = 5
        tab_about.add(jlabel5, gBC_about)
        gBC_about.gridy = 6
        tab_about.add(jlabel6, gBC_about)

        gBC_about.gridy = 7
        gBC_about.gridwidth = 5
        tab_about.add(JSeparator(), gBC_about)
        gBC_about.gridwidth = 1

        gBC_about.gridy = 8
        tab_about.add(jlabel7, gBC_about)
        gBC_about.gridy = 9
        tab_about.add(jlabel8, gBC_about)
        gBC_about.gridy = 10
        tab_about.add(jlabel9, gBC_about)

        # Añadimos los sub-tab al contenedor y lo devolvemos.
        self.contenedor.addTab('Mashup', tab_1)
        self.contenedor.addTab('Redirect', tab_2)
        self.contenedor.addTab('Loader', tab_3)
        self.contenedor.addTab('Headers', tab_4)
        self.contenedor.addTab('Quick Scan', tab_5)
        self.contenedor.addTab('About', tab_about)

        return self.contenedor
    def launchGui(self, caller):
      self._stdout = PrintWriter(self._callbacks.getStdout(), True)
      self._stdout.println('Launching gui')
      callMessage = caller.getSelectedMessages()
      self.msg1 = callMessage[0]

      #setup frame
      self.frame = JFrame('Create Issue', windowClosing=self.closeUI)
      Border = BorderFactory.createLineBorder(Color.BLACK)

      #create split panel to add issue panel and template panel
      self.splitPane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT)
      self.frame.add(self.splitPane)

      #panel setup and add to splitPane
      self.issuePanel = JPanel(GridLayout(0,2))
      self.splitPane.setLeftComponent(self.issuePanel)

      #setup issue name text fields to add to panel
      self.issueNameField = JTextField('',15)
      self.issueNameLabel = JLabel("IssueName:", SwingConstants.CENTER)
      self.issuePanel.add(self.issueNameLabel)
      self.issuePanel.add(self.issueNameField)

      #add issue detail text area
      self.issueDetailField = JTextArea()
      self.issueDetailField.editable = True
      self.issueDetailField.wrapStyleWord = True
      self.issueDetailField.lineWrap = True
      self.issueDetailField.alignmentX = Component.LEFT_ALIGNMENT
      self.issueDetailField.size = (200, 20)
      self.issueDetailField.setBorder(Border)
      self.idfSp = JScrollPane()
      self.idfSp.getViewport().setView((self.issueDetailField))
      self.issuePanel.add(JLabel("Issue Detail:", SwingConstants.CENTER))
      self.issuePanel.add(self.idfSp)

      self.issueBackgroundField= JTextArea()
      self.issueBackgroundField.editable = True
      self.issueBackgroundField.wrapStyleWord = True
      self.issueBackgroundField.lineWrap = True
      self.issueBackgroundField.alignmentX = Component.LEFT_ALIGNMENT
      self.issueBackgroundField.size = (200, 20)
      self.issueBackgroundField.setBorder(Border)
      self.ibfSp = JScrollPane()
      self.ibfSp.getViewport().setView((self.issueBackgroundField))
      self.issuePanel.add(JLabel("Issue Background:", SwingConstants.CENTER))
      self.issuePanel.add(self.ibfSp)

      #add remediation detail text area
      self.remediationDetailField = JTextArea()
      self.remediationDetailField.editable = True
      self.remediationDetailField.wrapStyleWord = True
      self.remediationDetailField.lineWrap = True
      self.remediationDetailField.alignmentX = Component.LEFT_ALIGNMENT
      self.remediationDetailField.size = (200, 20)
      self.remediationDetailField.setBorder(Border)
      self.rdfSp = JScrollPane()
      self.rdfSp.getViewport().setView((self.remediationDetailField))
      self.issuePanel.add(JLabel("Remediation Detail:", SwingConstants.CENTER))
      self.issuePanel.add(self.rdfSp)

      self.remediationBackgroundField= JTextArea()
      self.remediationBackgroundField.editable = True
      self.remediationBackgroundField.wrapStyleWord = True
      self.remediationBackgroundField.lineWrap = True
      self.remediationBackgroundField.alignmentX = Component.LEFT_ALIGNMENT
      self.remediationBackgroundField.size = (200, 20)
      self.remediationBackgroundField.setBorder(Border)
      self.rbfSp = JScrollPane()
      self.rbfSp.getViewport().setView((self.remediationBackgroundField))
      self.issuePanel.add(JLabel("Remediation Background:", SwingConstants.CENTER))
      self.issuePanel.add(self.rbfSp)

      #add radio buttons for severity
      self.radioBtnSevHigh = JRadioButton('High', actionPerformed=None)
      self.radioBtnSevMedium = JRadioButton('Medium', actionPerformed=None)
      self.radioBtnSevLow = JRadioButton('Low', actionPerformed=None)
      severityButtonGroup = ButtonGroup()
      severityButtonGroup.add(self.radioBtnSevHigh)
      severityButtonGroup.add(self.radioBtnSevMedium)
      severityButtonGroup.add(self.radioBtnSevLow)
      self.radioBtnSevHigh.setSelected(True)
      self.issuePanel.add(JLabel("Severity:", SwingConstants.CENTER))
      self.issuePanel.add(self.radioBtnSevHigh)
      self.issuePanel.add(self.radioBtnSevMedium)
      self.issuePanel.add(self.radioBtnSevLow)
    
      self.reqPattern = JTextField('',15)
      self.issuePanel.add(JLabel("Mark Pattern in Request:", SwingConstants.CENTER))
      self.issuePanel.add(self.reqPattern)
      self.resPattern = JTextField('',15)
      self.issuePanel.add(JLabel("Mark Pattern in Response:", SwingConstants.CENTER))
      self.issuePanel.add(self.resPattern)

      #add a button
      self.issueButton = JButton('Add!', actionPerformed=lambda x, m=self.msg1: self.logScanIssue(m))
      self.issuePanel.add(self.issueButton)

      #template panel setup
      self.templatePanel = JPanel(GridLayout(1,2))
      self.splitPane.setRightComponent(self.templatePanel)
    
      #add a list of templates
      self.templatePanel.add(JLabel("Select from Templates", SwingConstants.CENTER))
      self.templateData = tuple(self.tmpl.keys())
      self.templateList = JList(self.templateData)
      self.templateScrollPane = JScrollPane()

      #self.templateScrollPane.setPreferredSize(Dimension(100,125))
      self.templateScrollPane.getViewport().setView((self.templateList))
      self.templatePanel.add(self.templateScrollPane)
      self.templateButton = JButton('Apply', actionPerformed=self.applyTemplate)
      self.templatePanel.add(self.templateButton)
     
      #pack up the frame and display it
      self.frame.pack()
      self.show()
class BurpExtender(IBurpExtender, ITab, IScannerCheck, IScannerInsertionPoint, IContextMenuFactory):

    # definitions
    EXTENSION_NAME="IssueCreator"
    tmpl = dict()
    tmpl['XSS'] = dict()
    tmpl['XSS']['name'] = 'Cross-Site Scripting (reflected)'
    tmpl['XSS']['idetail'] = 'It is possible to inject arbitrary JavaScript into the application\'s response'
    tmpl['XSS']['ibackground'] = '''Reflected cross-site scripting vulnerabilities arise when data is copied from a request and echoed into the application's immediate response in an unsafe way. An attacker can use the vulnerability to construct a request which, if issued by another application user, will cause JavaScript code supplied by the attacker to execute within the user's browser in the context of that user's session with the application.  The attacker-supplied code can perform a wide variety of actions, such as stealing the victim's session token or login credentials, performing arbitrary actions on the victim's behalf, and logging their keystrokes.  Users can be induced to issue the attacker's crafted request in various ways. For example, the attacker can send a victim a link containing a malicious URL in an email or instant message. They can submit the link to popular web sites that allow content authoring, for example in blog comments. And they can create an innocuous looking web site which causes anyone viewing it to make arbitrary cross-domain requests to the vulnerable application (using either the GET or the POST method).  The security impact of cross-site scripting vulnerabilities is dependent upon the nature of the vulnerable application, the kinds of data and functionality which it contains, and the other applications which belong to the same domain and organization. If the application is used only to display non-sensitive public content, with no authentication or access control functionality, then a cross-site scripting flaw may be considered low risk. However, if the same application resides on a domain which can access cookies for other more security-critical applications, then the vulnerability could be used to attack those other applications, and so may be considered high risk. Similarly, if the organization which owns the application is a likely target for phishing attacks, then the vulnerability could be leveraged to lend credibility to such attacks, by injecting Trojan functionality into the vulnerable application, and exploiting users' trust in the organization in order to capture credentials for other applications which it owns. In many kinds of application, such as those providing online banking functionality, cross-site scripting should always be considered high risk. '''
    tmpl['XSS']['rdetail'] = ''''Input should be validated as strictly as possible on arrival, given the kind of content which it is expected to contain. For example, personal names should consist of alphabetical and a small range of typographical characters, and be relatively short; a year of birth should consist of exactly four numerals; email addresses should match a well-defined regular expression. Input which fails the validation should be rejected, not sanitized.
    User input should be HTML-encoded at any point where it is copied into application responses. All HTML metacharacters, including < > " ' and =, should be replaced with the corresponding HTML entities (&lt; &gt; etc).
    In cases where the application's functionality allows users to author content using a restricted subset of HTML tags and attributes (for example, blog comments which allow limited formatting and linking), it is necessary to parse the supplied HTML to validate that it does not use any dangerous syntax; this is a non-trivial task.
    '''
    tmpl['XSS']['rbackground'] = 'do not trust user input!'

    tmpl['SQLi'] = dict()
    tmpl['SQLi']['name'] = 'SQL Injection'
    tmpl['SQLi']['idetail'] = 'Input parameter appears to be vulnerable to SQL injection attacks.'
    tmpl['SQLi']['ibackground'] = '''SQL injection vulnerabilities arise when user-controllable data is incorporated into database SQL queries in an unsafe manner. An attacker can supply crafted input to break out of the data context in which their input appears and interfere with the structure of the surrounding query.
    Various attacks can be delivered via SQL injection, including reading or modifying critical application data, interfering with application logic, escalating privileges within the database and executing operating system commands.
    '''
    tmpl['SQLi']['rdetail'] = '''The most effective way to prevent SQL injection attacks is to use parameterized queries (also known as prepared statements) for all database access. This method uses two steps to incorporate potentially tainted data into SQL queries: first, the application specifies the structure of the query, leaving placeholders for each item of user input; second, the application specifies the contents of each placeholder. Because the structure of the query has already defined in the first step, it is not possible for malformed data in the second step to interfere with the query structure. You should review the documentation for your database and application platform to determine the appropriate APIs which you can use to perform parameterized queries. It is strongly recommended that you parameterize every variable data item that is incorporated into database queries, even if it is not obviously tainted, to prevent oversights occurring and avoid vulnerabilities being introduced by changes elsewhere within the code base of the application.
    
    '''
    tmpl['SQLi']['rbackground'] = 'SQL Injection background'

    tmpl['Insecure-Cookie'] = dict()
    tmpl['Insecure-Cookie']['name'] = 'Cookie Was Set Without Secure Flag'
    tmpl['Insecure-Cookie']['idetail'] = 'Application has set a secure cookie without the secure attribute'
    tmpl['Insecure-Cookie']['ibackground'] = 'Client will send this cookie over the clear via http.  This could be eavesdropped on.'
    tmpl['Insecure-Cookie']['rdetail'] = 'The application should set all cookies that are session related or sensitive in nature with the secure attribute.'
    tmpl['Insecure-Cookie']['rbackground'] = '...'

    tmpl['Your-Item'] = dict()
    tmpl['Your-Item']['name'] = 'My issue name'
    tmpl['Your-Item']['idetail'] = 'My issue detail'
    tmpl['Your-Item']['ibackground'] = 'the issue background here'
    tmpl['Your-Item']['rdetail'] = '''the remediation detail.  i'll put this in triple quotes. because.
    '''
    tmpl['Your-Item']['rbackground'] = 'this is remediation background information for my issue'
    
    def registerExtenderCallbacks(self, callbacks):
        # keep a reference to our callbacks object
        self._callbacks = callbacks
        
        # obtain an extension helpers object
        self._helpers = callbacks.getHelpers()
       
        # define stdout writer
        self._stdout = PrintWriter(callbacks.getStdout(), True) 
        self._stdout.println(self.EXTENSION_NAME + ' by @luxcupitor')
        self._stdout.println('================================')
        self._stdout.println('')
        self._stdout.println('TIP: right click on items in proxy or repeater tab')
        self._stdout.println('and select "Add as Issue to Scanner".')
        self._stdout.println('')
        # set our extension name
        callbacks.setExtensionName(self.EXTENSION_NAME)
        
        # setup a context menu for the proxy tab. needs createMenuItems
        callbacks.registerContextMenuFactory(self)

        return

    def createMenuItems(self, caller):
      '''caller is the burpsuite context that invoked the menu'''
      menu = []
      #Proxy tab is context 6/repeater request is 0/repeater response is 3
      idx = caller.getInvocationContext()
      if idx == 6 or idx == 0 or idx == 3:
        menu.append(JMenuItem("Add as Issue to Scanner", None, actionPerformed=lambda x, c=caller: self.launchGui(c)))
      return menu if menu else None

    def getMatches(self, response, match):
      '''This finds our pattern match in the request/response and returns an int array'''
      start = 0
      count = 0
      matches = [array('i')]
      while start < len(response):
        start=self._helpers.indexOf(response, match, True, start, len(response))
        if start == -1:
          break
        try:
          matches[count]
        except:
          matches.append(array('i'))
        matches[count].append(start)
        matches[count].append(start+len(match))
        start += len(match)
        count += 1

      return matches

    def logScanIssue(self, baseRequestResponse):
      '''This is redundant (mostly) of the doPassiveScan function'''
      reqPATTERN=self.reqPattern.text
      resPATTERN=self.resPattern.text
      ISSUE_NAME=self.issueNameField.text
      ISSUE_DETAIL=self.issueDetailField.text
      ISSUE_BACKGROUND=self.issueBackgroundField.text
      REMEDIATION_BACKGROUND=self.remediationBackgroundField.text
      REMEDIATION_DETAIL=self.remediationDetailField.text
      if self.radioBtnSevHigh.isSelected():
        SEVERITY="High"
      elif self.radioBtnSevMedium.isSelected():
        SEVERITY="Medium"
      else:
        SEVERITY="Low"
      CONFIDENCE="Certain"
      self._stdout = PrintWriter(self._callbacks.getStdout(), True)
      self._stdout.println('logScanIssue has been called')
      self._stdout.println('[-] ISSUE_NAME: ' + ISSUE_NAME)
      self._stdout.println('[-] ISSUE_DETAIL: ' + ISSUE_DETAIL)
      self._stdout.println('[-] ISSUE_BACKGROUND: ' + ISSUE_BACKGROUND)
      self._stdout.println('[-] REMEDIATION_DETAIL: ' + REMEDIATION_DETAIL)
      self._stdout.println('[-] REMEDIATION_BACKGROUND: ' + REMEDIATION_BACKGROUND)
      self._stdout.println('[-] SEVERITY: ' + SEVERITY)
      self._stdout.println('[-] CONFIDENCE: ' + CONFIDENCE)
      match = False
      if reqPATTERN == "":
        reqmatch = None
      else:
        reqmatch = self.getMatches(baseRequestResponse.getRequest(), reqPATTERN)
        match = True
      if resPATTERN == "":
        resmatch = None
      else:
        resmatch = self.getMatches(baseRequestResponse.getResponse(), resPATTERN)
        match = True
      if match:
        httpmsgs = [self._callbacks.applyMarkers(baseRequestResponse,reqmatch,resmatch)]
        issue=ScanIssue(baseRequestResponse.getHttpService(), self._helpers.analyzeRequest(baseRequestResponse).getUrl(), httpmsgs, ISSUE_NAME, ISSUE_DETAIL, SEVERITY, CONFIDENCE, ISSUE_BACKGROUND, REMEDIATION_DETAIL, REMEDIATION_BACKGROUND)
        self._callbacks.addScanIssue(issue)
        self.closeUI(None)

      return

    def launchGui(self, caller):
      self._stdout = PrintWriter(self._callbacks.getStdout(), True)
      self._stdout.println('Launching gui')
      callMessage = caller.getSelectedMessages()
      self.msg1 = callMessage[0]

      #setup frame
      self.frame = JFrame('Create Issue', windowClosing=self.closeUI)
      Border = BorderFactory.createLineBorder(Color.BLACK)

      #create split panel to add issue panel and template panel
      self.splitPane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT)
      self.frame.add(self.splitPane)

      #panel setup and add to splitPane
      self.issuePanel = JPanel(GridLayout(0,2))
      self.splitPane.setLeftComponent(self.issuePanel)

      #setup issue name text fields to add to panel
      self.issueNameField = JTextField('',15)
      self.issueNameLabel = JLabel("IssueName:", SwingConstants.CENTER)
      self.issuePanel.add(self.issueNameLabel)
      self.issuePanel.add(self.issueNameField)

      #add issue detail text area
      self.issueDetailField = JTextArea()
      self.issueDetailField.editable = True
      self.issueDetailField.wrapStyleWord = True
      self.issueDetailField.lineWrap = True
      self.issueDetailField.alignmentX = Component.LEFT_ALIGNMENT
      self.issueDetailField.size = (200, 20)
      self.issueDetailField.setBorder(Border)
      self.idfSp = JScrollPane()
      self.idfSp.getViewport().setView((self.issueDetailField))
      self.issuePanel.add(JLabel("Issue Detail:", SwingConstants.CENTER))
      self.issuePanel.add(self.idfSp)

      self.issueBackgroundField= JTextArea()
      self.issueBackgroundField.editable = True
      self.issueBackgroundField.wrapStyleWord = True
      self.issueBackgroundField.lineWrap = True
      self.issueBackgroundField.alignmentX = Component.LEFT_ALIGNMENT
      self.issueBackgroundField.size = (200, 20)
      self.issueBackgroundField.setBorder(Border)
      self.ibfSp = JScrollPane()
      self.ibfSp.getViewport().setView((self.issueBackgroundField))
      self.issuePanel.add(JLabel("Issue Background:", SwingConstants.CENTER))
      self.issuePanel.add(self.ibfSp)

      #add remediation detail text area
      self.remediationDetailField = JTextArea()
      self.remediationDetailField.editable = True
      self.remediationDetailField.wrapStyleWord = True
      self.remediationDetailField.lineWrap = True
      self.remediationDetailField.alignmentX = Component.LEFT_ALIGNMENT
      self.remediationDetailField.size = (200, 20)
      self.remediationDetailField.setBorder(Border)
      self.rdfSp = JScrollPane()
      self.rdfSp.getViewport().setView((self.remediationDetailField))
      self.issuePanel.add(JLabel("Remediation Detail:", SwingConstants.CENTER))
      self.issuePanel.add(self.rdfSp)

      self.remediationBackgroundField= JTextArea()
      self.remediationBackgroundField.editable = True
      self.remediationBackgroundField.wrapStyleWord = True
      self.remediationBackgroundField.lineWrap = True
      self.remediationBackgroundField.alignmentX = Component.LEFT_ALIGNMENT
      self.remediationBackgroundField.size = (200, 20)
      self.remediationBackgroundField.setBorder(Border)
      self.rbfSp = JScrollPane()
      self.rbfSp.getViewport().setView((self.remediationBackgroundField))
      self.issuePanel.add(JLabel("Remediation Background:", SwingConstants.CENTER))
      self.issuePanel.add(self.rbfSp)

      #add radio buttons for severity
      self.radioBtnSevHigh = JRadioButton('High', actionPerformed=None)
      self.radioBtnSevMedium = JRadioButton('Medium', actionPerformed=None)
      self.radioBtnSevLow = JRadioButton('Low', actionPerformed=None)
      severityButtonGroup = ButtonGroup()
      severityButtonGroup.add(self.radioBtnSevHigh)
      severityButtonGroup.add(self.radioBtnSevMedium)
      severityButtonGroup.add(self.radioBtnSevLow)
      self.radioBtnSevHigh.setSelected(True)
      self.issuePanel.add(JLabel("Severity:", SwingConstants.CENTER))
      self.issuePanel.add(self.radioBtnSevHigh)
      self.issuePanel.add(self.radioBtnSevMedium)
      self.issuePanel.add(self.radioBtnSevLow)
    
      self.reqPattern = JTextField('',15)
      self.issuePanel.add(JLabel("Mark Pattern in Request:", SwingConstants.CENTER))
      self.issuePanel.add(self.reqPattern)
      self.resPattern = JTextField('',15)
      self.issuePanel.add(JLabel("Mark Pattern in Response:", SwingConstants.CENTER))
      self.issuePanel.add(self.resPattern)

      #add a button
      self.issueButton = JButton('Add!', actionPerformed=lambda x, m=self.msg1: self.logScanIssue(m))
      self.issuePanel.add(self.issueButton)

      #template panel setup
      self.templatePanel = JPanel(GridLayout(1,2))
      self.splitPane.setRightComponent(self.templatePanel)
    
      #add a list of templates
      self.templatePanel.add(JLabel("Select from Templates", SwingConstants.CENTER))
      self.templateData = tuple(self.tmpl.keys())
      self.templateList = JList(self.templateData)
      self.templateScrollPane = JScrollPane()

      #self.templateScrollPane.setPreferredSize(Dimension(100,125))
      self.templateScrollPane.getViewport().setView((self.templateList))
      self.templatePanel.add(self.templateScrollPane)
      self.templateButton = JButton('Apply', actionPerformed=self.applyTemplate)
      self.templatePanel.add(self.templateButton)
     
      #pack up the frame and display it
      self.frame.pack()
      self.show()
     
    def applyTemplate(self, event):
      selected = self.templateList.selectedIndex
      if selected >= 0:
        self.issueNameField.text = self.tmpl[self.templateData[selected]]['name']
        self.issueDetailField.text = self.tmpl[self.templateData[selected]]['idetail']
        self.issueBackgroundField.text = self.tmpl[self.templateData[selected]]['ibackground']
        self.remediationDetailField.text = self.tmpl[self.templateData[selected]]['rdetail']
        self.remediationBackgroundField.text = self.tmpl[self.templateData[selected]]['rbackground']

    def show(self):
      self.frame.visible = True


    def closeUI(self, event):
        self.frame.setVisible(False)
        self.frame.dispose()
Example #25
0
class AtfAreaView(JPanel):
    '''
    Initializes the ATF (edit/model) view and sets its layout.
    '''
    def __init__(self, controller):
        '''
        Creates default empty text area in a panel for ATF edition.
        It has syntax highlighting based on the ATF parser (pyoracc).
        It also highlights line numbers where there are validations errors
        returned by the ORACC server.
        '''
        # Give reference to controller to delegate action response
        self.controller = controller

        # Make text area occupy all available space and resize with parent
        # window
        self.setLayout(BorderLayout())

        # Short hand for edit area and line numbers area
        self.edit_area = self.controller.edit_area
        self.line_numbers_area = self.controller.line_numbers_area

        # Create secondary text area for split view
        self.secondary_area = self.controller.secondary_area
        self.secondary_line_numbers = self.controller.secondary_line_numbers

        # Set undo/redo manager to edit area
        self.undo_manager = UndoManager()
        self.undo_manager.limit = 3000
        self.edit_listener = AtfUndoableEditListener(self.undo_manager)
        self.edit_area.getDocument().addUndoableEditListener(
                                                        self.edit_listener)

        # Sort out layout by synch-ing line numbers and text area and putting
        # only the text area in a scroll pane as indicated in the
        # TextLineNumber tutorial.
        self.edit_area.setPreferredSize(Dimension(1, 500))
        self.container = JScrollPane(self.edit_area)
        self.container.setRowHeaderView(self.line_numbers_area)
        self.add(self.container, BorderLayout.CENTER)

        self.vert_scroll = self.container.getVerticalScrollBar()
        self.vert_scroll.addAdjustmentListener(atfAreaAdjustmentListener(self))

        # Key listener that triggers syntax highlighting, etc. upon key release
        self.edit_area.addKeyListener(AtfAreaKeyListener(self))
        # Also needed in secondary area:
        self.secondary_area.addKeyListener(AtfAreaKeyListener(self))

        # Add a document listener to track changes to files
        docListener = atfAreaDocumentListener(self)
        self.edit_area.getDocument().addDocumentListener(docListener)

        # instance variable to store a record of the text contents prior to the
        # most recent change. Needed so that the different listeners can access
        # this to handle error line updating.
        self.oldtext = ''

    def toggle_split(self, split_orientation=None):
        '''
        Clear ATF edit area and repaint chosen layout (splitscreen/scrollpane).
        '''
        # Remove all existent components in parent JPanel
        self.removeAll()
        # Check what editor view to toggle
        self.setup_edit_area(split_orientation)
        # Revalitate is needed in order to repaint the components
        self.revalidate()
        self.repaint()

    def setup_edit_area(self, split_orientation=None):
        '''
        Check if the ATF text area is being displayed in a split editor.
        If so, resets to normal JScrollPane. If not, splits the screen.
        '''
        if isinstance(self.container, JSplitPane):
            # If Nammu is already displaying a split pane, reset to original
            # setup
            self.container = JScrollPane(self.edit_area)
            self.container.setRowHeaderView(self.line_numbers_area)
            self.container.setVisible(True)
            self.add(self.container, BorderLayout.CENTER)
        else:
            # If there is not a split pane, create both panels and setup view
            main_editor = JScrollPane(self.edit_area)
            main_editor.setRowHeaderView(self.line_numbers_area)
            secondary_editor = JScrollPane(self.secondary_area)
            secondary_editor.setRowHeaderView(self.secondary_line_numbers)
            self.container = JSplitPane(split_orientation,
                                        main_editor,
                                        secondary_editor)
            self.container.setDividerSize(5)
            self.container.setVisible(True)
            self.container.setDividerLocation(0.5)
            self.container.setResizeWeight(0.5)
            self.add(self.container, BorderLayout.CENTER)

    def get_viewport_carets(self):
        '''
        Get the top left and bottom left caret position of the current viewport
        '''
        extent = self.container.getViewport().getExtentSize()
        top_left_position = self.container.getViewport().getViewPosition()
        top_left_char = self.edit_area.viewToModel(top_left_position)
        bottom_left_position = Point(top_left_position.x,
                                     top_left_position.y + extent.height)
        bottom_left_char = self.edit_area.viewToModel(bottom_left_position)

        # Something has gone wrong. Assume that top_left should be at the start
        # of the file
        if top_left_char >= bottom_left_char:
            top_left_char = 0

        # Get the text in the full edit area
        text = self.controller.edit_area.getText()

        # Pad the top of the viewport to capture up to the nearest header and
        # the bottom by 2 lines
        top_ch = self.controller.pad_top_viewport_caret(top_left_char, text)
        bottom_ch = self.controller.pad_bottom_viewport_caret(bottom_left_char,
                                                              text)

        return top_ch, bottom_ch

    def refresh(self):
        '''
        Restyle edit area using user selected appearance settings.
        '''

        config = self.controller.controller.config

        # Create a new font with the new size
        font = set_font(config['edit_area_style']['fontsize']['user'])

        # Update the sytnax highlighter font params, so our changes are not
        # superceded
        self.controller.syntax_highlighter.font = font
        self.controller.syntax_highlighter.setup_attribs()

        attrs = self.controller.edit_area.getInputAttributes()
        StyleConstants.setFontSize(attrs, font.getSize())

        # Get the Styledoc so we can update it
        doc = self.controller.edit_area.getStyledDocument()

        # Apply the new fontsize to the whole document
        doc.setCharacterAttributes(0, doc.getLength() + 1, attrs, False)
Example #26
0
class BurpExtender(IBurpExtender, ITab, IHttpListener, IMessageEditorController, AbstractTableModel, IBurpExtenderCallbacks):
    import java.net.URLClassLoader
    statement = None
    con = None

    def	registerExtenderCallbacks(self, callbacks):
        global statement,con

        self._callbacks = callbacks
        self._helpers = callbacks.getHelpers()
        callbacks.setExtensionName("SQLite Logger")

        # select sqlite jdbc jar file
        c = classPathHacker()
        c.addFile("C:\\sqlite-jdbc-3.8.11.2.jar")

        # database filename.
        jdbc_url = "jdbc:sqlite:database" + str(datetime.date.today()) + ".db"
        driver = "org.sqlite.JDBC"
        Class.forName(driver).newInstance()
        con = DriverManager.getConnection(jdbc_url)

        # create table
        self.sql = "CREATE TABLE if not exists log(host text,path text,method text,request text,response text,time text);"
        statement = con.prepareStatement(self.sql)
        statement.executeUpdate()
        
        self._log = ArrayList()
        self._lock = Lock()

        self._splitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT)

        logTable = Table(self)
        scrollPane = JScrollPane(logTable)
        self._splitpane.setLeftComponent(scrollPane)

        tabs = JTabbedPane()
        self._requestViewer = callbacks.createMessageEditor(self, False)
        self._responseViewer = callbacks.createMessageEditor(self, False)
        tabs.addTab("Request", self._requestViewer.getComponent())
        tabs.addTab("Response", self._responseViewer.getComponent())
        self._splitpane.setRightComponent(tabs)

        callbacks.customizeUiComponent(self._splitpane)
        callbacks.customizeUiComponent(logTable)
        callbacks.customizeUiComponent(scrollPane)
        callbacks.customizeUiComponent(tabs)

        callbacks.addSuiteTab(self)

        callbacks.registerHttpListener(self)
        
        return


    def exitSuite(self,False):
        con.close()
        return

    def getTabCaption(self):
        return "SQLite Logger"


    def getUiComponent(self):
        return self._splitpane


    def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo):
        global statement

        # insert into database request,response
        if not messageIsRequest:
            self._lock.acquire()
            row = self._log.size()

            self.reqinfo = self._helpers.analyzeRequest(messageInfo)
            self.parsed = urlparse.urlparse(self.reqinfo.getUrl().toString())

            print "request"
            print self._helpers.bytesToString(messageInfo.getRequest())
            print ""
            print "req header"
            print self._helpers.bytesToString(messageInfo.getResponse()).encode('utf8', 'replace')
            print ""

            self._log.add(LogEntry(toolFlag, self._callbacks.saveBuffersToTempFiles(messageInfo),self.reqinfo.getMethod(), self.parsed.netloc, self.parsed.path))


            self.sql = "INSERT INTO log(host,path,method,request,response,time) VALUES (?,?,?,?,?,?);"
            statement = con.prepareStatement(self.sql)

            statement.setString(1,self.parsed.path)
            statement.setString(2,self.parsed.netloc)
            statement.setString(3,self.reqinfo.getMethod())
            statement.setString(4,self._helpers.bytesToString(messageInfo.getRequest()))
            statement.setString(5,self._helpers.bytesToString(messageInfo.getResponse()))
            statement.setString(6,str(datetime.datetime.today()))
            statement.executeUpdate()

            self.fireTableRowsInserted(row, row)
            self._lock.release()
        return


    def getRowCount(self):
        try:
            return self._log.size()
        except:
            return 0

    def getColumnCount(self):
        return 4

    def getColumnName(self, columnIndex):
        if columnIndex == 0:
            return "Tool"
        if columnIndex == 1:
            return "Method"
        if columnIndex == 2:
            return "Host"
        if columnIndex == 3:
            return "Path"

        return ""


    def getValueAt(self, rowIndex, columnIndex):
        logEntry = self._log.get(rowIndex)
        if columnIndex == 0:
            return self._callbacks.getToolName(logEntry._tool)
        if columnIndex == 1:
            return logEntry._method
        if columnIndex == 2:
            return logEntry._host
        if columnIndex == 3:
            return logEntry._path
        return ""


    def getHttpService(self):
        return self._currentlyDisplayedItem.getHttpService()


    def getRequest(self):
        return self._currentlyDisplayedItem.getRequest()


    def getResponse(self):
        return self._currentlyDisplayedItem.getResponse()
class BurpExtender(IBurpExtender, ITab, IMessageEditorController, IContextMenuFactory):
    
    #
    # implement IBurpExtender
    #
    
    def	registerExtenderCallbacks(self, callbacks):
    
        # keep a reference to our Burp callbacks object
        self._callbacks = callbacks
        # obtain an Burp extension helpers object
        self._helpers = callbacks.getHelpers()
        # set our extension name
        callbacks.setExtensionName("AuthMatrix - v0.5.2")

        # DB that holds everything users, roles, and messages
        self._db = MatrixDB()

        # For saving/loading config
        self._fc = JFileChooser()        

        # Used by ActionListeners
        selfExtender = self
        self._selectedColumn = -1
        self._selectedRow = -1


        # Table of User entries
        self._userTable = UserTable(self, model = UserTableModel(self._db))
        roleScrollPane = JScrollPane(self._userTable)
        self._userTable.redrawTable()

        # Table of Request (AKA Message) entries
        self._messageTable = MessageTable(self, model = MessageTableModel(self._db))
        messageScrollPane = JScrollPane(self._messageTable)
        self._messageTable.redrawTable()


        # Semi-Generic Popup stuff
        def addPopup(component, popup):
            class genericMouseListener(MouseAdapter):
                def mousePressed(self, e):
                    if e.isPopupTrigger():
                        self.showMenu(e)
                def mouseReleased(self, e):
                    if e.isPopupTrigger():
                        self.showMenu(e)
                def showMenu(self, e):
                    if type(component) is JTableHeader:
                        table = component.getTable()
                        column = component.columnAtPoint(e.getPoint())
                        if type(table) is MessageTable and column >= selfExtender._db.STATIC_MESSAGE_TABLE_COLUMN_COUNT or type(table) is UserTable and column >= selfExtender._db.STATIC_USER_TABLE_COLUMN_COUNT:
                            selfExtender._selectedColumn = column
                        else:
                            return
                    else:
                        selfExtender._selectedRow = component.rowAtPoint(e.getPoint())
                    popup.show(e.getComponent(), e.getX(), e.getY())
            component.addMouseListener(genericMouseListener())

        class actionRunMessage(ActionListener):
            def actionPerformed(self,e):
                if selfExtender._selectedRow >= 0:
                    if selfExtender._selectedRow not in selfExtender._messageTable.getSelectedRows():
                        indexes = [selfExtender._db.getMessageByRow(selfExtender._selectedRow)._index]
                    else:
                        indexes = [selfExtender._db.getMessageByRow(rowNum)._index for rowNum in selfExtender._messageTable.getSelectedRows()]
                    t = Thread(target=selfExtender.runMessagesThread, args = [indexes])
                    t.start()
                    selfExtender._selectedColumn = -1
                    # Redrawing the table happens in colorcode within the thread

        class actionRemoveMessage(ActionListener):
            def actionPerformed(self,e):
                if selfExtender._selectedRow >= 0:
                    if selfExtender._selectedRow not in selfExtender._messageTable.getSelectedRows():
                        indexes = [selfExtender._db.getMessageByRow(selfExtender._selectedRow)._index]
                    else:
                        indexes = [selfExtender._db.getMessageByRow(rowNum)._index for rowNum in selfExtender._messageTable.getSelectedRows()]
                    for i in indexes:
                        selfExtender._db.deleteMessage(i)
                    selfExtender._selectedColumn = -1
                    selfExtender._messageTable.redrawTable()

        class actionRemoveUser(ActionListener):
            def actionPerformed(self,e):
                if selfExtender._selectedRow >= 0:
                    if selfExtender._selectedRow not in selfExtender._userTable.getSelectedRows():
                        indexes = [selfExtender._db.getUserByRow(selfExtender._selectedRow)._index]
                    else:
                        indexes = [selfExtender._db.getUserByRow(rowNum)._index for rowNum in selfExtender._userTable.getSelectedRows()]
                    for i in indexes:
                        selfExtender._db.deleteUser(i)
                    selfExtender._selectedColumn = -1
                    selfExtender._userTable.redrawTable()

        # TODO combine these next two classes
        class actionRemoveRoleHeaderFromMessageTable(ActionListener):
            def actionPerformed(self,e):
                if selfExtender._selectedColumn >= 0:
                    selfExtender._db.deleteRole(selfExtender._db.getRoleByMessageTableColumn(selfExtender._selectedColumn)._index)
                    selfExtender._selectedColumn = -1
                    selfExtender._userTable.redrawTable()
                    selfExtender._messageTable.redrawTable()

        class actionRemoveRoleHeaderFromUserTable(ActionListener):
            def actionPerformed(self,e):
                if selfExtender._selectedColumn >= 0:
                    selfExtender._db.deleteRole(selfExtender._db.getRoleByUserTableColumn(selfExtender._selectedColumn)._index)
                    selfExtender._selectedColumn = -1
                    selfExtender._userTable.redrawTable()
                    selfExtender._messageTable.redrawTable()


        # Message Table popups
        messagePopup = JPopupMenu()
        addPopup(self._messageTable,messagePopup)
        messageRun = JMenuItem("Run Request(s)")
        messageRun.addActionListener(actionRunMessage())
        messagePopup.add(messageRun)
        messageRemove = JMenuItem("Remove Request(s)")
        messageRemove.addActionListener(actionRemoveMessage())
        messagePopup.add(messageRemove)

        messageHeaderPopup = JPopupMenu()
        addPopup(self._messageTable.getTableHeader(),messageHeaderPopup)
        roleRemoveFromMessageTable = JMenuItem("Remove Role")
        roleRemoveFromMessageTable.addActionListener(actionRemoveRoleHeaderFromMessageTable())
        messageHeaderPopup.add(roleRemoveFromMessageTable)

        # User Table popup
        userPopup = JPopupMenu()
        addPopup(self._userTable,userPopup)
        userRemove = JMenuItem("Remove Users(s)")
        userRemove.addActionListener(actionRemoveUser())
        userPopup.add(userRemove)

        userHeaderPopup = JPopupMenu()
        addPopup(self._userTable.getTableHeader(),userHeaderPopup)
        roleRemoveFromUserTable = JMenuItem("Remove Role")
        roleRemoveFromUserTable.addActionListener(actionRemoveRoleHeaderFromUserTable())
        userHeaderPopup.add(roleRemoveFromUserTable)

        # Top pane
        topPane = JSplitPane(JSplitPane.VERTICAL_SPLIT,roleScrollPane,messageScrollPane)

        # request tabs added to this tab on click in message table
        self._tabs = JTabbedPane()

        # Button pannel
        buttons = JPanel()
        runButton = JButton("Run", actionPerformed=self.runClick)
        newUserButton = JButton("New User", actionPerformed=self.getInputUserClick)
        newRoleButton = JButton("New Role", actionPerformed=self.getInputRoleClick)
        #debugButton = JButton("Debug", actionPerformed=self.printDB)
        saveButton = JButton("Save", actionPerformed=self.saveClick)
        loadButton = JButton("Load", actionPerformed=self.loadClick)
        clearButton = JButton("Clear", actionPerformed=self.clearClick)
        buttons.add(runButton)
        buttons.add(newUserButton)
        buttons.add(newRoleButton)
        #buttons.add(debugButton)
        buttons.add(saveButton)
        buttons.add(loadButton)
        buttons.add(clearButton)

        bottomPane = JSplitPane(JSplitPane.VERTICAL_SPLIT, self._tabs, buttons)

        # Main Pane
        self._splitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT, topPane, bottomPane)
        


        # customize our UI components
        callbacks.customizeUiComponent(self._splitpane)
        callbacks.customizeUiComponent(topPane)
        callbacks.customizeUiComponent(bottomPane)
        callbacks.customizeUiComponent(messageScrollPane)
        callbacks.customizeUiComponent(roleScrollPane)
        callbacks.customizeUiComponent(self._messageTable)
        callbacks.customizeUiComponent(self._userTable)
        callbacks.customizeUiComponent(self._tabs)
        callbacks.customizeUiComponent(buttons)

        self._splitpane.setResizeWeight(0.5)
        topPane.setResizeWeight(0.3)
        bottomPane.setResizeWeight(0.95)


        # Handles checkbox color coding
        # Must be bellow the customizeUiComponent calls
        self._messageTable.setDefaultRenderer(Boolean, SuccessBooleanRenderer(self._db))


        # add the custom tab to Burp's UI
        callbacks.addSuiteTab(self)        
        # register SendTo option
        callbacks.registerContextMenuFactory(self)

        return
        
    ##
    ## implement ITab
    ##
    
    def getTabCaption(self):
        return "AuthMatrix"
    
    def getUiComponent(self):
        return self._splitpane
       

    ##
    ## Creates the sendto tab in other areas of Burp
    ##

    def createMenuItems(self, invocation):

        def addRequestsToTab(e):
            for messageInfo in messages:
                # saveBuffers is required since modifying the original from its source changes the saved objects, its not a copy
                messageIndex = self._db.createNewMessage(self._callbacks.saveBuffersToTempFiles(messageInfo), 
                    self._helpers.analyzeRequest(messageInfo).getUrl())
                #self._messageTable.getModel().addRow(row)
            self._messageTable.redrawTable()

        ret = []
        messages = invocation.getSelectedMessages()

        # Check if the messages in the target tree have a response
        valid = True
        if invocation.getInvocationContext() == invocation.CONTEXT_TARGET_SITE_MAP_TREE:
            for selected in messages:
                if not selected.getResponse():
                    valid = False

        if valid:
            menuItem = JMenuItem("Send request(s) to AuthMatrix");
            menuItem.addActionListener(addRequestsToTab)
            ret.append(menuItem)
        return ret
    
    ##
    ## implement IMessageEditorController
    ## this allows our request/response viewers to obtain details about the messages being displayed
    ##

    def getHttpService(self):
        return self._currentlyDisplayedItem.getHttpService()

    def getRequest(self):
        return self._currentlyDisplayedItem.getRequest()

    def getResponse(self):
        return self._currentlyDisplayedItem.getResponse()

    ##
    ## Actions on Bottom Row Button Clicks
    ##

    def printDB(self, e):
        out = ""
        for a in self._db.arrayOfUsers:
            out += str(a._index)+" "+a._name+" : "+str(a._roles)+"\n"
        for b in self._db.arrayOfMessages:
            out += str(b._index)+" "+str(b._roles)+"\n"
        JOptionPane.showMessageDialog(self._splitpane,out)

    def getInputUserClick(self, e):
        newUser = JOptionPane.showInputDialog(self._splitpane,"Enter New User:"******"Enter New Role:")
        if not newRole is None:
            self._db.getOrCreateRole(newRole)
            self._userTable.redrawTable()
            self._messageTable.redrawTable()

    def saveClick(self, e):
        returnVal = self._fc.showSaveDialog(self._splitpane)
        if returnVal == JFileChooser.APPROVE_OPTION:
            f = self._fc.getSelectedFile()
            if f.exists():
                result = JOptionPane.showConfirmDialog(self._splitpane, "The file exists, overwrite?", "Existing File", JOptionPane.YES_NO_OPTION)
                if result != JOptionPane.YES_OPTION:
                    return
            fileName = f.getPath()
            outs = ObjectOutputStream(FileOutputStream(fileName))
            outs.writeObject(self._db.getSaveableObject())
            outs.close()

    def loadClick(self,e):
        returnVal = self._fc.showOpenDialog(self._splitpane)
        if returnVal == JFileChooser.APPROVE_OPTION:
            warning = """
            CAUTION: 

            Loading a saved configuration deserializes data. 
            This action may pose a security threat to the application.
            Only proceed when the source and contents of this file is trusted. 

            Load Selected File?
            """
            result = JOptionPane.showOptionDialog(self._splitpane, warning, "Caution", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, None, ["OK", "Cancel"],"OK")
            if result != JOptionPane.YES_OPTION:
                return
            f = self._fc.getSelectedFile()
            fileName = f.getPath()
            
            ins = ObjectInputStream(FileInputStream(fileName))
            dbData=ins.readObject()
            ins.close()

            self._db.load(dbData,self)
            self._userTable.redrawTable()
            self._messageTable.redrawTable()

    def clearClick(self,e):
        result = JOptionPane.showConfirmDialog(self._splitpane, "Clear AuthMatrix Configuration?", "Clear Config", JOptionPane.YES_NO_OPTION)
        if result == JOptionPane.YES_OPTION:
            self._db.clear()
            self._tabs.removeAll()
            self._userTable.redrawTable()
            self._messageTable.redrawTable()

    def runClick(self,e):
        t = Thread(target=self.runMessagesThread)
        self._tabs.removeAll()
        t.start()

    def changeDomainPopup(self, oldDomain, index):
        hostField = JTextField(25)
        checkbox = JCheckBox()
        domainPanel = JPanel(GridLayout(0,1))
        domainPanel.add(JLabel("Request %s: Domain %s inaccessible. Enter new domain." % (str(index),oldDomain)))

        firstline = JPanel()
        firstline.add(JLabel("Host:"))
        firstline.add(hostField)
        domainPanel.add(firstline)
        secondline = JPanel()
        secondline.add(JLabel("Replace domain for all requests?"))
        secondline.add(checkbox)
        domainPanel.add(secondline)
        result = JOptionPane.showConfirmDialog(
            self._splitpane,domainPanel, "Domain Inaccessible", JOptionPane.OK_CANCEL_OPTION)
        cancelled = (result == JOptionPane.CANCEL_OPTION)
        if cancelled:
            return (False, None, False)
        return (True, hostField.getText(), checkbox.isSelected())

    ##
    ## Methods for running messages and analyzing results
    ##

    def runMessagesThread(self, messageIndexes=None):
        self._db.lock.acquire()
        try:
            indexes = messageIndexes
            if not indexes:
                indexes = self._db.getActiveMessageIndexes()
            self.clearColorResults(indexes)
            for index in indexes:
                self.runMessage(index)
                #self.colorCodeResults()
        except:
            traceback.print_exc(file=self._callbacks.getStderr())
        finally:
            self._db.lock.release()
            self.colorCodeResults()

    # Replaces headers/cookies with user's token
    def getNewHeader(self, requestInfo, userEntry):
        headers = requestInfo.getHeaders()
        if userEntry.isCookie():
            cookieHeader = "Cookie:"
            newheader = cookieHeader
            previousCookies = []
            # note: getHeaders has to be called again here cuz of java references
            for header in requestInfo.getHeaders():
                # Find and remove existing cookie header
                if str(header).startswith(cookieHeader):
                    previousCookies = str(header)[len(cookieHeader):].replace(" ","").split(";")
                    headers.remove(header)

            newCookies = userEntry._token.replace(" ","").split(";")
            newCookieVariableNames = []
            for newCookie in newCookies:
                # If its a valid cookie
                equalsToken = newCookie.find("=")
                if equalsToken >= 0:
                    newCookieVariableNames.append(newCookie[0:equalsToken+1])

            # Add all the old unchanged cookies
            for previousCookie in previousCookies:
                # If its a valid cookie
                equalsToken = previousCookie.find("=")
                if equalsToken >= 0:
                    if previousCookie[0:equalsToken+1] not in newCookieVariableNames:
                        newCookies.append(previousCookie)

            # Remove whitespace
            newCookies = [x for x in newCookies if x]
            newheader = cookieHeader+" "+";".join(newCookies)

        else:
            # TODO: Support multiple headers with a newline somehow
            newheader = userEntry._token
            # Remove previous HTTP Header
            colon = newheader.find(":")
            if colon >= 0:
                # getHeaders has to be called again here cuz of java references
                for header in requestInfo.getHeaders():
                    # If the header already exists, remove it
                    if str(header).startswith(newheader[0:colon+1]):
                        headers.remove(header)
        headers.add(newheader)
        return headers

    def runMessage(self, messageIndex):
        messageEntry = self._db.arrayOfMessages[messageIndex]
        # Clear Previous Results:
        messageEntry._roleResults = {}
        messageEntry._userRuns = {}

        messageInfo = messageEntry._requestResponse
        requestInfo = self._helpers.analyzeRequest(messageInfo)
        reqBody = messageInfo.getRequest()[requestInfo.getBodyOffset():]
        for userIndex in self._db.getActiveUserIndexes():
            userEntry = self._db.arrayOfUsers[userIndex]
            headers = self.getNewHeader(requestInfo, userEntry)

            # Add static CSRF token if available
            # TODO: Kinda hacky, but for now it will add the token as long as there is some content in the post body
            # Even if its a GET request.  This screws up when original requests have no body though... oh well...
            newBody = reqBody
            if userEntry._staticcsrf and len(reqBody):
                delimeter = userEntry._staticcsrf.find("=")
                if delimeter >= 0:
                    csrfname = userEntry._staticcsrf[0:delimeter]
                    csrfvalue = userEntry._staticcsrf[delimeter+1:]
                    params = requestInfo.getParameters()
                    for param in params:
                        if str(param.getName())==csrfname:
                            # Handle CSRF Tokens in Body
                            if param.getType() == 1:
                                newBody = reqBody[0:param.getValueStart()-requestInfo.getBodyOffset()] + StringUtil.toBytes(csrfvalue) + reqBody[param.getValueEnd()-requestInfo.getBodyOffset():]
                            # Handle CSRF Tokens in Cookies (for Cookie==Body mitigation technique):
                            if param.getType() == 2:
                                # TODO: required moving above portion to a function
                                # TODO: also need to think about when cookie name != postarg name
                                print "Cookie CSRF Tokens are not currently supported"
                    if newBody == reqBody:
                        newBody = reqBody+StringUtil.toBytes("&"+userEntry._staticcsrf)

            # Construct and send a message with the new headers
            message = self._helpers.buildHttpMessage(headers, newBody)
            requestResponse = self._callbacks.makeHttpRequest(messageInfo.getHttpService(),message)
            messageEntry.addRunByUserIndex(userIndex, self._callbacks.saveBuffersToTempFiles(requestResponse))

        # Grab all active roleIndexes that should succeed
        activeSuccessRoles = [index for index in messageEntry._roles.keys() if messageEntry._roles[index] and not self._db.arrayOfRoles[index].isDeleted()]
        # Check Role Results of message
        for roleIndex in self._db.getActiveRoleIndexes():
            success = self.checkResult(messageEntry, roleIndex, activeSuccessRoles)
            messageEntry.setRoleResultByRoleIndex(roleIndex, success)
                    
    def colorCodeResults(self):
        self._messageTable.redrawTable()

    def clearColorResults(self, messageIndexArray = None):
        if not messageIndexArray:
            messageIndexes = self._db.getActiveMessageIndexes()
        else:
            messageIndexes = messageIndexArray
        for messageIndex in messageIndexes:
            messageEntry = self._db.arrayOfMessages[messageIndex]
            messageEntry._roleResults = {}
            messageEntry._userRuns = {}
        self._messageTable.redrawTable()

    def checkResult(self, messageEntry, roleIndex, activeSuccessRoles):
        for userIndex in self._db.getActiveUserIndexes():
            userEntry = self._db.arrayOfUsers[userIndex]

            ignoreUser = False
            # if user is not in this role, ignore it
            if not userEntry._roles[roleIndex]:
                ignoreUser = True
            # If user is in any other role that should succeed, then ignore it
            for index in userEntry._roles.keys():
                if not index == roleIndex and userEntry._roles[index] and index in activeSuccessRoles:
                    ignoreUser = True

            if not ignoreUser:
                shouldSucceed = roleIndex in activeSuccessRoles
                requestResponse = messageEntry._userRuns[userEntry._index]
                resp = StringUtil.fromBytes(requestResponse.getResponse())
                found = re.search(messageEntry._successRegex, resp, re.DOTALL)
                succeeds = found if shouldSucceed else not found
                if not succeeds:
                    return False
        return True
Example #28
0
 def dividerLocation(self, location):
     JSplitPane.setDividerLocation(self, location)
     newAuxPanelSize = self.flipLocation(location)
     if newAuxPanelSize >= self.minAuxSize):
         self.auxPanelVisibleSize = newAuxPanelSize
    def registerExtenderCallbacks(self, callbacks):
    
        # keep a reference to our callbacks object (Burp Extensibility Feature)
        self._callbacks = callbacks   
        self._helpers = callbacks.getHelpers()

        # set our extension name
        callbacks.setExtensionName("Generate Finding")
        callbacks.registerContextMenuFactory(self)

        # -- Request Response Viewers -- #

        # create the lower half for the Request Response tabs...
        # Request and response from selection
        self._tabbedPane = JTabbedPane()
        tabs = self._tabbedPane
        self._requestViewer = callbacks.createMessageEditor(self, True)
        self._responseViewer = callbacks.createMessageEditor(self, True)
        self._requestHighlight = callbacks.createTextEditor()
        self._responseHighlight = callbacks.createTextEditor()
        tabs.addTab("Supporting Request", self._requestViewer.getComponent())
        tabs.addTab("Supporting Response", self._responseViewer.getComponent())
        tabs.addTab("Request Marker Selection", self._requestHighlight.getComponent())
        tabs.addTab("Response Marker Selection", self._responseHighlight.getComponent())
        #self._mainFrame.setRightComponent(tabs) # set to the lower split pane
        print "*" * 60
        print "[+] Request/Response tabs created"
    

        # -- Define Issue Details GUI & Layout-- #

        # Labels and Input boxes...
        # Issue Name
        self.issueNameLabel = JLabel(" Issue Name:")
        self.issueNameValue = JTextArea(text = str(issueNamePlaceholder), 
                         editable = True,
                         wrapStyleWord = True,
                         lineWrap = True,
                         alignmentX = Component.LEFT_ALIGNMENT,
                         size = (1, 20)
                         )

        # Issue Detail
        self.issueDetailLabel = JLabel(" Issue Detail:")

        #self.issueDetailValue = JTextField(str(issueDetailPlaceholder), 15)
        self.issueDetailValue = JTextArea(text = str(issueDetailPlaceholder), 
                         editable = True,
                         wrapStyleWord = True,
                         lineWrap = True,
                         alignmentX = Component.LEFT_ALIGNMENT,
                         size = (100, 20)
                         )

        # IssueBackground
        self.issueBackgroundLabel = JLabel(" Issue Background:")
        self.issueBackgroundValue = JTextArea(text = str(issueBackgroundPlaceholder), 
                         editable = True,
                         wrapStyleWord = True,
                         lineWrap = True,
                         alignmentX = Component.LEFT_ALIGNMENT,
                         size = (100, 20)
                         )

        # Remediation Detail
        self.issueRemediationLabel = JLabel(" Remediation Detail:")
        self.issueRemediationValue = JTextArea(text = str(remediationDetailPlaceholder), 
                         editable = True,
                         wrapStyleWord = True,
                         lineWrap = True,
                         alignmentX = Component.LEFT_ALIGNMENT,
                         size = (100, 20)
                         )
 
         # Remediation Background
        self.issueRemBackgroundLabel = JLabel(" Remediation Background:")
        self.issueRemBackgroundValue = JTextArea(text = str(remediationBackgroundPlaceholder), 
                         editable = True,
                         wrapStyleWord = True,
                         lineWrap = True,
                         alignmentX = Component.LEFT_ALIGNMENT,
                         size = (100, 20)
                         )  

        # Issue URL
        self.issueURLLabel = JLabel(" URL (path = http://domain/path):")
        self.issueURLValue = JTextArea(text = str(issueURLPlaceholder), 
                         editable = True,
                         wrapStyleWord = True,
                         lineWrap = True,
                         alignmentX = Component.LEFT_ALIGNMENT,
                         size = (1, 20)
                         )                       

        # Issue Port
        self.issuePortLabel = JLabel(" Port:")
        self.issuePortValue = JTextArea(text = str(issuePortPlaceholder), 
                         editable = True,
                         wrapStyleWord = True,
                         lineWrap = True,
                         alignmentX = Component.LEFT_ALIGNMENT,
                         size = (1, 20)
                         )

        # Confidence
        self.confidenceValuesList = ("Certain","Firm","Tentative")
        self.issueConfienceLabel = JLabel(" Confidence [Certain, Firm or Tentative]")
        self.issueConfidenceValue = JComboBox(self.confidenceValuesList)

        # Severity
        self.severityValuesList = ("High","Medium","Low","Information")
        self.issueSeverityLabel = JLabel(" Severity [High, Medium Low or Informational]")
        self.issueSeverityValue = JComboBox(self.severityValuesList)

        # Add Finding button

        self.addFindingButton = JButton("Generate Finding", actionPerformed=self.createScanIssue, alignmentX=Component.CENTER_ALIGNMENT) 


        # -- Group items for display -- #         

        # Group items 
        self.grpIssueSummary = JPanel(GridLayout(0,1))
        self.grpIssueSummary.add(self.issueNameLabel)
        self.grpIssueSummary.add(self.issueNameValue)
        self.grpIssueSummary.add(self.issueDetailLabel)
        self.grpIssueSummary.add(self.issueDetailValue)
        self.grpIssueSummary.add(self.issueBackgroundLabel)
        self.grpIssueSummary.add(self.issueBackgroundValue)
        self.grpIssueSummary.add(self.issueRemediationLabel)
        self.grpIssueSummary.add(self.issueRemediationValue)
        self.grpIssueSummary.add(self.issueRemBackgroundLabel)
        self.grpIssueSummary.add(self.issueRemBackgroundValue)
        self.grpIssueSummary.add(self.issueURLLabel)
        self.grpIssueSummary.add(self.issueURLValue)
        self.grpIssueSummary.add(self.issuePortLabel)
        self.grpIssueSummary.add(self.issuePortValue)
        self.grpIssueSummary.add(self.issueURLLabel)
        self.grpIssueSummary.add(self.issueURLValue)
        self.grpIssueSummary.add(self.issuePortLabel)
        self.grpIssueSummary.add(self.issuePortValue)

        self.grpRatingBoxes = JPanel()
        self.grpRatingBoxes.add(self.issueSeverityLabel)
        self.grpRatingBoxes.add(self.issueSeverityValue)
        self.grpRatingBoxes.add(self.issueConfienceLabel)
        self.grpRatingBoxes.add(self.issueConfidenceValue)
        self.grpRatingBoxes.add(self.addFindingButton)


        # add grps to details frame
        self._detailsPanel = JPanel(GridLayout(0,1))
        self._detailsPanel.add(self.grpIssueSummary)
        self._detailsPanel.add(self.grpRatingBoxes)


        self._findingDetailsPane = JScrollPane(self._detailsPanel)
        # create the main frame to hold details
        self._detailsViewer = self._findingDetailsPane # creates a form for details
        #tabs.addTab("Finding Details", self._detailsViewer)

        self._mainFrame = JSplitPane(JSplitPane.VERTICAL_SPLIT, self._detailsViewer, tabs)
        self._mainFrame.setOneTouchExpandable(True);
        self._mainFrame.setDividerLocation(0.5)
        self._mainFrame.setResizeWeight(0.50)

        print "[+] Finding details panel created"
        print "[+] Rendering..."

        # customize our UI components
        callbacks.customizeUiComponent(self._mainFrame)
        callbacks.customizeUiComponent(self._tabbedPane)
        callbacks.customizeUiComponent(self._detailsPanel)
        callbacks.customizeUiComponent(tabs)
        
        # add the custom tab to Burp's UI
        callbacks.addSuiteTab(self)
        print "[+] Done"
        print "[!] Added suite tab initialize complete!"

        return
Example #30
0
class BurpExtender(IBurpExtender, ITab, IContextMenuFactory):
    def registerExtenderCallbacks(self, callbacks):

        # set our extension name
        callbacks.setExtensionName("CT Search")
        callbacks.registerContextMenuFactory(self)
        # obtain output stream
        self._stdout = PrintWriter(callbacks.getStdout(), True)
        stdout = PrintWriter(callbacks.getStdout(), True)

        # write a message to our output stream
        self._callbacks = callbacks

        # write a message to the Burp alerts tab
        callbacks.issueAlert("Hello alerts")

        #create and populate a jtable:
        initial_row = ['a', 'DOMAINS', True]
        self.fileTable = JTable(ResourceTableModel())
        # set up the Tab:

        self.infoPanel = JPanel()
        footerPanel = JPanel()

        footerPanel.add(JLabel("by mcgyver5 "))
        #        self._chooseFileButton = JButton("OPEN Local FILE", actionPerformed=self.fileButtonClick)
        self.infoPanel.add(JLabel("INFORMATION PANE"))

        #        self.infoPanel.add(self._chooseFileButton)
        scrollpane = JScrollPane(self.fileTable)
        ## this is a split inside the top component
        topPane = JSplitPane(JSplitPane.VERTICAL_SPLIT)
        topPane.setTopComponent(self.infoPanel)
        topPane.setBottomComponent(scrollpane)
        #self._chooseFileButton.setEnabled(True)
        self._splitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT)
        self._splitpane.setTopComponent(topPane)
        self._splitpane.setBottomComponent(footerPanel)
        #callbacks.addSuiteTab(self)

    def get_domains_from_json_list(self, json_list):
        my_domain_list = []
        for cert in json_list:
            try:
                domainList = str(cert.get('name_value')).strip()
                for domain in domainList.split("\n"):
                    if not domain in my_domain_list:
                        my_domain_list.append(domain)
            except Exception as e:
                print(e)
        my_domain_list.sort()
        return list(set(my_domain_list))

    def get_domains_from_api(self, domain):
        my_domain_list = []
        try:
            api_url = "https://crt.sh/?q=%.{}&output=json".format(domain)
            request = urllib2.urlopen(api_url)
            data = request.read()
            json_list = json.loads(data)
            my_domain_list = self.get_domains_from_json_list(json_list)
        except Exception as e:
            print("error")
            print(e)
        return my_domain_list

    def lookup_ct(self, whatever):
        domain = ""
        http_traffic = self.context.getSelectedMessages()
        for traffic in http_traffic:
            http_service = traffic.getHttpService()
            host = http_service.getHost()
            domain = host.replace('www.', '')
            self._stdout.println(domain)
        domain_list = self.get_domains_from_api(domain)
        ct_tab = CTSearchTab(self._callbacks)
        self._callbacks.addSuiteTab(ct_tab)
        ct_tab.setDomainList(domain_list)

    def fake_lookup_ct(self, whatever):
        domain_list = self.get_domains_from_file()
        ct_tab = CTSearchTab(self._callbacks)
        self._callbacks.addSuiteTab(ct_tab)
        ct_tab.setDomainList(domain_list)

    def createMenuItems(self, context_menu):
        self.context = context_menu
        menu_list = ArrayList()
        menu_list.add(
            JMenuItem("Lookup Domain in CT Logs",
                      actionPerformed=self.lookup_ct))
        menu_list.add(
            JMenuItem("CT LOgs Test get Domains from test file",
                      actionPerformed=self.fake_lookup_ct))
        return menu_list

    def get_domains_from_file(self):
        my_domain_list = []
        fileChooser = JFileChooser()
        result = fileChooser.showOpenDialog(self._splitpane)
        if result == JFileChooser.APPROVE_OPTION:
            f = fileChooser.getSelectedFile()
            fileName = f.getPath()
            self._stdout.println(fileName)
            file_data = open(fileName).read()
            json_list = json.loads(file_data)
            for cert in json_list:
                try:
                    domainList = str(cert.get('name_value')).strip()
                    for domain in domainList.split("\n"):
                        if not domain in my_domain_list:
                            domain = domain.replace("*.", "")
                            my_domain_list.append(domain)
                except Exception as e:
                    self._stdout.println(e)
            my_domain_list.sort()

        return list(set(my_domain_list))


#    def populateTableModel(self,f):
#        domain_list = []
#        num = 0
#        try:
#            path = os.getcwd()
#            self._stdout.println("path is : " + path)
#            fhandle = open(f)
#            file_data = fhandle.read()
#            domain_list = self.get_domains_from_file(file_data)
#            tableModel = self.fileTable.getModel()
#        except Exception as e:
#            self._stdout.println("exception!  ")
#            self._stdout.println(e)
#        for dom in domain_list:
#            num = num + 1
#            row = [str(num),dom,False]
#            tableModel.addRow(row)
#

    def getTabCaption(self):
        return "Import URLs"

    def getUiComponent(self):
        return self._splitpane
Example #31
0
class BurpExtender(IBurpExtender, ITab, IHttpListener,
                   IMessageEditorController, AbstractTableModel,
                   IContextMenuFactory):
    def registerExtenderCallbacks(self, callbacks):
        # 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("Autorize")

        # create the log and a lock on which to synchronize when adding log entries
        self._log = ArrayList()
        self._lock = Lock()
        self.intercept = 0

        self.initInterceptionFilters()

        self.initEnforcementDetector()

        self.initExport()

        self.initConfigurationTab()

        self.initTabs()

        self.initCallbacks()

        print "Thank you for installing Autorize v0.9 extension"
        print "by Barak Tawily"
        return

    def initExport(self):
        #
        ## init enforcement detector tab
        #

        exportLType = JLabel("File Type:")
        exportLType.setBounds(10, 10, 100, 30)

        exportLES = JLabel("Enforcement Statuses:")
        exportLES.setBounds(10, 50, 160, 30)

        exportFileTypes = ["HTML"]
        self.exportType = JComboBox(exportFileTypes)
        self.exportType.setBounds(100, 10, 200, 30)

        exportES = [
            "All Statuses", "Authorization bypass!",
            "Authorization enforced??? (please configure enforcement detector)",
            "Authorization enforced!"
        ]
        self.exportES = JComboBox(exportES)
        self.exportES.setBounds(100, 50, 200, 30)

        exportLES = JLabel("Statuses:")
        exportLES.setBounds(10, 50, 100, 30)

        self.exportButton = JButton("Export",
                                    actionPerformed=self.exportToHTML)
        self.exportButton.setBounds(390, 25, 100, 30)

        self.exportPnl = JPanel()
        self.exportPnl.setLayout(None)
        self.exportPnl.setBounds(0, 0, 1000, 1000)
        self.exportPnl.add(exportLType)
        self.exportPnl.add(self.exportType)
        self.exportPnl.add(exportLES)
        self.exportPnl.add(self.exportES)
        self.exportPnl.add(self.exportButton)

    def initEnforcementDetector(self):
        #
        ## init enforcement detector tab
        #

        self.EDFP = ArrayList()
        self.EDCT = ArrayList()

        EDLType = JLabel("Type:")
        EDLType.setBounds(10, 10, 140, 30)

        EDLContent = JLabel("Content:")
        EDLContent.setBounds(10, 50, 140, 30)

        EDLabelList = JLabel("Filter List:")
        EDLabelList.setBounds(10, 165, 140, 30)

        EDStrings = [
            "Finger Print: (enforced message body contains)",
            "Content-Length: (constant Content-Length number of enforced response)"
        ]
        self.EDType = JComboBox(EDStrings)
        self.EDType.setBounds(80, 10, 430, 30)

        self.EDText = JTextArea("", 5, 30)
        self.EDText.setBounds(80, 50, 300, 110)

        self.EDModel = DefaultListModel()
        self.EDList = JList(self.EDModel)
        self.EDList.setBounds(80, 175, 300, 110)
        self.EDList.setBorder(LineBorder(Color.BLACK))

        self.EDAdd = JButton("Add filter", actionPerformed=self.addEDFilter)
        self.EDAdd.setBounds(390, 85, 120, 30)
        self.EDDel = JButton("Remove filter", actionPerformed=self.delEDFilter)
        self.EDDel.setBounds(390, 210, 120, 30)

        self.EDPnl = JPanel()
        self.EDPnl.setLayout(None)
        self.EDPnl.setBounds(0, 0, 1000, 1000)
        self.EDPnl.add(EDLType)
        self.EDPnl.add(self.EDType)
        self.EDPnl.add(EDLContent)
        self.EDPnl.add(self.EDText)
        self.EDPnl.add(self.EDAdd)
        self.EDPnl.add(self.EDDel)
        self.EDPnl.add(EDLabelList)
        self.EDPnl.add(self.EDList)

    def initInterceptionFilters(self):
        #
        ##  init interception filters tab
        #

        IFStrings = [
            "URL Contains: ", "Scope items only: (Content is not required)"
        ]
        self.IFType = JComboBox(IFStrings)
        self.IFType.setBounds(80, 10, 430, 30)

        self.IFModel = DefaultListModel()
        self.IFList = JList(self.IFModel)
        self.IFList.setBounds(80, 175, 300, 110)
        self.IFList.setBorder(LineBorder(Color.BLACK))

        self.IFText = JTextArea("", 5, 30)
        self.IFText.setBounds(80, 50, 300, 110)

        IFLType = JLabel("Type:")
        IFLType.setBounds(10, 10, 140, 30)

        IFLContent = JLabel("Content:")
        IFLContent.setBounds(10, 50, 140, 30)

        IFLabelList = JLabel("Filter List:")
        IFLabelList.setBounds(10, 165, 140, 30)

        self.IFAdd = JButton("Add filter", actionPerformed=self.addIFFilter)
        self.IFAdd.setBounds(390, 85, 120, 30)
        self.IFDel = JButton("Remove filter", actionPerformed=self.delIFFilter)
        self.IFDel.setBounds(390, 210, 120, 30)

        self.filtersPnl = JPanel()
        self.filtersPnl.setLayout(None)
        self.filtersPnl.setBounds(0, 0, 1000, 1000)
        self.filtersPnl.add(IFLType)
        self.filtersPnl.add(self.IFType)
        self.filtersPnl.add(IFLContent)
        self.filtersPnl.add(self.IFText)
        self.filtersPnl.add(self.IFAdd)
        self.filtersPnl.add(self.IFDel)
        self.filtersPnl.add(IFLabelList)
        self.filtersPnl.add(self.IFList)

    def initConfigurationTab(self):
        #
        ##  init configuration tab
        #
        self.prevent304 = JCheckBox("Prevent 304 Not Modified status code")
        self.prevent304.setBounds(290, 25, 300, 30)

        self.ignore304 = JCheckBox("Ignore 304/204 status code responses")
        self.ignore304.setBounds(290, 5, 300, 30)
        self.ignore304.setSelected(True)

        self.autoScroll = JCheckBox("Auto Scroll")
        self.autoScroll.setBounds(290, 45, 140, 30)

        startLabel = JLabel("Authorization checks:")
        startLabel.setBounds(10, 10, 140, 30)
        self.startButton = JButton("Autorize is off",
                                   actionPerformed=self.startOrStop)
        self.startButton.setBounds(160, 10, 120, 30)
        self.startButton.setBackground(Color(255, 100, 91, 255))

        self.clearButton = JButton("Clear List",
                                   actionPerformed=self.clearList)
        self.clearButton.setBounds(10, 40, 100, 30)

        self.replaceString = JTextArea("Cookie: Insert=injected; header=here;",
                                       5, 30)
        self.replaceString.setWrapStyleWord(True)
        self.replaceString.setLineWrap(True)
        self.replaceString.setBounds(10, 80, 470, 180)

        self.filtersTabs = JTabbedPane()
        self.filtersTabs.addTab("Enforcement Detector", self.EDPnl)
        self.filtersTabs.addTab("Interception Filters", self.filtersPnl)
        self.filtersTabs.addTab("Export", self.exportPnl)

        self.filtersTabs.setBounds(0, 280, 2000, 700)

        self.pnl = JPanel()
        self.pnl.setBounds(0, 0, 1000, 1000)
        self.pnl.setLayout(None)
        self.pnl.add(self.startButton)
        self.pnl.add(self.clearButton)
        self.pnl.add(self.replaceString)
        self.pnl.add(startLabel)
        self.pnl.add(self.autoScroll)
        self.pnl.add(self.ignore304)
        self.pnl.add(self.prevent304)
        self.pnl.add(self.filtersTabs)

    def initTabs(self):
        #
        ##  init autorize tabs
        #

        self.logTable = Table(self)
        self._splitpane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT)
        self._splitpane.setResizeWeight(1)
        self.scrollPane = JScrollPane(self.logTable)
        self._splitpane.setLeftComponent(self.scrollPane)
        self.scrollPane.getVerticalScrollBar().addAdjustmentListener(
            autoScrollListener(self))
        copyURLitem = JMenuItem("Copy URL")
        copyURLitem.addActionListener(copySelectedURL(self))
        self.menu = JPopupMenu("Popup")
        self.menu.add(copyURLitem)

        self.tabs = JTabbedPane()
        self._requestViewer = self._callbacks.createMessageEditor(self, False)
        self._responseViewer = self._callbacks.createMessageEditor(self, False)

        self._originalrequestViewer = self._callbacks.createMessageEditor(
            self, False)
        self._originalresponseViewer = self._callbacks.createMessageEditor(
            self, False)

        self.tabs.addTab("Modified Request",
                         self._requestViewer.getComponent())
        self.tabs.addTab("Modified Response",
                         self._responseViewer.getComponent())

        self.tabs.addTab("Original Request",
                         self._originalrequestViewer.getComponent())
        self.tabs.addTab("Original Response",
                         self._originalresponseViewer.getComponent())

        self.tabs.addTab("Configuration", self.pnl)
        self.tabs.setSelectedIndex(4)
        self._splitpane.setRightComponent(self.tabs)

    def initCallbacks(self):
        #
        ##  init callbacks
        #

        # customize our UI components
        self._callbacks.customizeUiComponent(self._splitpane)
        self._callbacks.customizeUiComponent(self.logTable)
        self._callbacks.customizeUiComponent(self.scrollPane)
        self._callbacks.customizeUiComponent(self.tabs)
        self._callbacks.customizeUiComponent(self.filtersTabs)
        self._callbacks.registerContextMenuFactory(self)
        # add the custom tab to Burp's UI
        self._callbacks.addSuiteTab(self)

    #
    ## Events functions
    #
    def startOrStop(self, event):
        if self.startButton.getText() == "Autorize is off":
            self.startButton.setText("Autorize is on")
            self.startButton.setBackground(Color.GREEN)
            self.intercept = 1
            self._callbacks.registerHttpListener(self)
        else:
            self.startButton.setText("Autorize is off")
            self.startButton.setBackground(Color(255, 100, 91, 255))
            self.intercept = 0
            self._callbacks.removeHttpListener(self)

    def addEDFilter(self, event):
        typeName = self.EDType.getSelectedItem().split(":")[0]
        self.EDModel.addElement(typeName + ": " + self.EDText.getText())

    def delEDFilter(self, event):
        index = self.EDList.getSelectedIndex()
        if not index == -1:
            self.EDModel.remove(index)

    def addIFFilter(self, event):
        typeName = self.IFType.getSelectedItem().split(":")[0]
        self.IFModel.addElement(typeName + ": " + self.IFText.getText())

    def delIFFilter(self, event):
        index = self.IFList.getSelectedIndex()
        if not index == -1:
            self.IFModel.remove(index)

    def clearList(self, event):
        self._lock.acquire()
        self._log = ArrayList()
        row = self._log.size()
        self.fireTableRowsInserted(row, row)
        self._lock.release()

    def exportToHTML(self, event):
        parentFrame = JFrame()
        fileChooser = JFileChooser()
        fileChooser.setSelectedFile(File("AutorizeReprort.html"))
        fileChooser.setDialogTitle("Save Autorize Report")
        userSelection = fileChooser.showSaveDialog(parentFrame)
        if userSelection == JFileChooser.APPROVE_OPTION:
            fileToSave = fileChooser.getSelectedFile()

        enforcementStatusFilter = self.exportES.getSelectedItem()
        htmlContent = """<html><title>Autorize Report by Barak Tawily</title>
        <style>
        .datagrid table { border-collapse: collapse; text-align: left; width: 100%; }
         .datagrid {font: normal 12px/150% Arial, Helvetica, sans-serif; background: #fff; overflow: hidden; border: 1px solid #006699; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; }
         .datagrid table td, .datagrid table th { padding: 3px 10px; }
         .datagrid table thead th {background:-webkit-gradient( linear, left top, left bottom, color-stop(0.05, #006699), color-stop(1, #00557F) );background:-moz-linear-gradient( center top, #006699 5%, #00557F 100% );filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#006699', endColorstr='#00557F');background-color:#006699; color:#FFFFFF; font-size: 15px; font-weight: bold; border-left: 1px solid #0070A8; } .datagrid table thead th:first-child { border: none; }.datagrid table tbody td { color: #00496B; border-left: 1px solid #E1EEF4;font-size: 12px;font-weight: normal; }.datagrid table tbody .alt td { background: #E1EEF4; color: #00496B; }.datagrid table tbody td:first-child { border-left: none; }.datagrid table tbody tr:last-child td { border-bottom: none; }.datagrid table tfoot td div { border-top: 1px solid #006699;background: #E1EEF4;} .datagrid table tfoot td { padding: 0; font-size: 12px } .datagrid table tfoot td div{ padding: 2px; }.datagrid table tfoot td ul { margin: 0; padding:0; list-style: none; text-align: right; }.datagrid table tfoot  li { display: inline; }.datagrid table tfoot li a { text-decoration: none; display: inline-block;  padding: 2px 8px; margin: 1px;color: #FFFFFF;border: 1px solid #006699;-webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; background:-webkit-gradient( linear, left top, left bottom, color-stop(0.05, #006699), color-stop(1, #00557F) );background:-moz-linear-gradient( center top, #006699 5%, #00557F 100% );filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#006699', endColorstr='#00557F');background-color:#006699; }.datagrid table tfoot ul.active, .datagrid table tfoot ul a:hover { text-decoration: none;border-color: #006699; color: #FFFFFF; background: none; background-color:#00557F;}div.dhtmlx_window_active, div.dhx_modal_cover_dv { position: fixed !important; }
        table {
        width: 100%;
        table-layout: fixed;
        }
        td {
            border: 1px solid #35f;
            overflow: hidden;
            text-overflow: ellipsis;
        }
        td.a {
            width: 13%;
            white-space: nowrap;
        }
        td.b {
            width: 9%;
            word-wrap: break-word;
        }
        </style>
        <body>
        <h1>Autorize Report<h1>
        <div class="datagrid"><table>
        <thead><tr><th>URL</th><th>Authorization Enforcement Status</th></tr></thead>
        <tbody>"""

        for i in range(0, self._log.size()):
            color = ""
            if self._log.get(
                    i
            )._enfocementStatus == "Authorization enforced??? (please configure enforcement detector)":
                color = "yellow"
            if self._log.get(i)._enfocementStatus == "Authorization bypass!":
                color = "red"
            if self._log.get(i)._enfocementStatus == "Authorization enforced!":
                color = "LawnGreen"

            if enforcementStatusFilter == "All Statuses":
                htmlContent += "<tr bgcolor=\"%s\"><td><a href=\"%s\">%s</a></td><td>%s</td></tr>" % (
                    color, self._log.get(i)._url, self._log.get(i)._url,
                    self._log.get(i)._enfocementStatus)
            else:
                if enforcementStatusFilter == self._log.get(
                        i)._enfocementStatus:
                    htmlContent += "<tr bgcolor=\"%s\"><td><a href=\"%s\">%s</a></td><td>%s</td></tr>" % (
                        color, self._log.get(i)._url, self._log.get(i)._url,
                        self._log.get(i)._enfocementStatus)

        htmlContent += "</tbody></table></div></body></html>"
        f = open(fileToSave.getAbsolutePath(), 'w')
        f.writelines(htmlContent)
        f.close()

    #
    # implement IContextMenuFactory
    #
    def createMenuItems(self, invocation):
        responses = invocation.getSelectedMessages()
        if responses > 0:
            ret = LinkedList()
            requestMenuItem = JMenuItem("Send request to Autorize")
            cookieMenuItem = JMenuItem("Send cookie to Autorize")
            requestMenuItem.addActionListener(
                handleMenuItems(self, responses[0], "request"))
            cookieMenuItem.addActionListener(
                handleMenuItems(self, responses[0], "cookie"))
            ret.add(requestMenuItem)
            ret.add(cookieMenuItem)
            return (ret)
        return null

    #
    # implement ITab
    #
    def getTabCaption(self):
        return "Autorize"

    def getUiComponent(self):
        return self._splitpane

        #

    # extend AbstractTableModel
    #

    def getRowCount(self):
        try:
            return self._log.size()
        except:
            return 0

    def getColumnCount(self):
        return 2

    def getColumnName(self, columnIndex):
        if columnIndex == 0:
            return "URL"
        if columnIndex == 1:
            return "Authorization Enforcement Status"
        return ""

    def getValueAt(self, rowIndex, columnIndex):
        logEntry = self._log.get(rowIndex)
        if columnIndex == 0:
            return logEntry._url.toString()
        if columnIndex == 1:
            return logEntry._enfocementStatus
        return ""

    #
    # implement IMessageEditorController
    # this allows our request/response viewers to obtain details about the messages being displayed
    #

    def getHttpService(self):
        return self._currentlyDisplayedItem.getHttpService()

    def getRequest(self):
        return self._currentlyDisplayedItem.getRequest()

    def getResponse(self):
        return self._currentlyDisplayedItem.getResponse()

    #
    # implement IHttpListener
    #
    def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo):
        if self.intercept == 1:
            if self.prevent304.isSelected():
                if messageIsRequest:
                    requestHeaders = list(
                        self._helpers.analyzeRequest(messageInfo).getHeaders())
                    newHeaders = list()
                    found = 0
                    for header in requestHeaders:
                        if not "If-None-Match:" in header and not "If-Modified-Since:" in header:
                            newHeaders.append(header)
                            found = 1
                    if found == 1:
                        requestInfo = self._helpers.analyzeRequest(messageInfo)
                        bodyBytes = messageInfo.getRequest()[requestInfo.
                                                             getBodyOffset():]
                        bodyStr = self._helpers.bytesToString(bodyBytes)
                        messageInfo.setRequest(
                            self._helpers.buildHttpMessage(
                                newHeaders, bodyStr))

            if not messageIsRequest:
                if not self.replaceString.getText(
                ) in self._helpers.analyzeRequest(messageInfo).getHeaders():
                    if self.ignore304.isSelected():
                        firstHeader = self._helpers.analyzeResponse(
                            messageInfo.getResponse()).getHeaders()[0]
                        if "304" in firstHeader or "204" in firstHeader:
                            return
                    if self.IFList.getModel().getSize() == 0:
                        self.checkAuthorization(
                            messageInfo,
                            self._helpers.analyzeResponse(
                                messageInfo.getResponse()).getHeaders())
                    else:
                        urlString = str(
                            self._helpers.analyzeRequest(messageInfo).getUrl())
                        for i in range(0, self.IFList.getModel().getSize()):
                            if self.IFList.getModel().getElementAt(i).split(
                                    ":")[0] == "Scope items only":
                                currentURL = URL(urlString)
                                if self._callbacks.isInScope(currentURL):
                                    self.checkAuthorization(
                                        messageInfo,
                                        self._helpers.analyzeResponse(
                                            messageInfo.getResponse()).
                                        getHeaders())
                            if self.IFList.getModel().getElementAt(i).split(
                                    ":")[0] == "URL Contains":
                                if self.IFList.getModel().getElementAt(
                                        i)[14:] in urlString:
                                    self.checkAuthorization(
                                        messageInfo,
                                        self._helpers.analyzeResponse(
                                            messageInfo.getResponse()).
                                        getHeaders())
        return

    def makeRequest(self, messageInfo, message):
        requestURL = self._helpers.analyzeRequest(messageInfo).getUrl()
        return self._callbacks.makeHttpRequest(
            self._helpers.buildHttpService(
                str(requestURL.getHost()), int(requestURL.getPort()),
                requestURL.getProtocol() == "https"), message)

    def makeMessage(self, messageInfo, removeOrNot):
        requestInfo = self._helpers.analyzeRequest(messageInfo)
        headers = requestInfo.getHeaders()
        if removeOrNot:
            headers = list(headers)
            removeHeaders = ArrayList()
            removeHeaders.add(self.replaceString.getText()
                              [0:self.replaceString.getText().index(":")])

            for header in headers[:]:
                for removeHeader in removeHeaders:
                    if removeHeader in header:
                        headers.remove(header)

            headers.append(self.replaceString.getText())

        msgBody = messageInfo.getRequest()[requestInfo.getBodyOffset():]
        return self._helpers.buildHttpMessage(headers, msgBody)

    def checkAuthorization(self, messageInfo, originalHeaders):
        message = self.makeMessage(messageInfo, True)
        requestResponse = self.makeRequest(messageInfo, message)
        analyzedResponse = self._helpers.analyzeResponse(
            requestResponse.getResponse())

        oldStatusCode = originalHeaders[0]
        newStatusCode = analyzedResponse.getHeaders()[0]
        oldContentLen = self.getContentLength(originalHeaders)
        newContentLen = self.getContentLength(analyzedResponse.getHeaders())

        impression = ""

        EDFilters = self.EDModel.toArray()
        if oldStatusCode == newStatusCode:
            if oldContentLen == newContentLen:
                impression = "Authorization bypass!"
            else:
                impression = "Authorization enforced??? (please configure enforcement detector)"
                for filter in EDFilters:
                    if str(filter).startswith("Content-Length: "):
                        if newContentLen == filter:
                            impression = "Authorization enforced!"
                    if str(filter).startswith("Finger Print: "):
                        if filter[14:] in self._helpers.bytesToString(
                                requestResponse.getResponse()
                            [analyzedResponse.getBodyOffset():]):
                            impression = "Authorization enforced!"
        else:
            impression = "Authorization enforced!"

        self._lock.acquire()
        row = self._log.size()
        self._log.add(
            LogEntry(self._callbacks.saveBuffersToTempFiles(requestResponse),
                     self._helpers.analyzeRequest(requestResponse).getUrl(),
                     messageInfo,
                     impression))  # same requests not include again.
        self.fireTableRowsInserted(row, row)
        self._lock.release()

    def getContentLength(self, analyzedResponseHeaders):
        for header in analyzedResponseHeaders:
            if "Content-Length:" in header:
                return header
        return "null"

    def getCookieFromMessage(self, messageInfo):
        headers = list(
            self._helpers.analyzeRequest(
                messageInfo.getRequest()).getHeaders())
        for header in headers:
            if "Cookie:" in header:
                return header
        return None
Example #32
0
    def __init__(self,
                 logtable_factory=None,
                 external_filter_action_listener=None,
                 external_start_button_action_listener=None,
                 external_stop_button_action_listener=None,
                 external_clear_button_action_listener=None,
                 tools_keys=None):
        self.this = JPanel()

        if tools_keys is None:
            tools_keys = []

        self.external_start_button_action_listener = external_start_button_action_listener
        self.external_stop_button_action_listener = external_stop_button_action_listener
        self.external_clear_button_action_listener = external_clear_button_action_listener


        self.this.setLayout(BoxLayout(self.this, BoxLayout.Y_AXIS))

        # main split pane
        splitPane = JSplitPane(JSplitPane.VERTICAL_SPLIT)

        # table of log entries
        logTableModel = LogTableModel()
        self.logTableModel = logTableModel
        if logtable_factory is not None:
            logTable = logtable_factory(logTableModel)
        else:
            # XXX: create a generic logtable that works even without burp to made it work standalone
            raise ValueError("logtable_factory cannot be none")
        scrollPane = JScrollPane(logTable)
        splitPane.setLeftComponent(scrollPane)

        # tabs with request/response viewers
        tabs = JTabbedPane()
        tabs.setBorder(BorderFactory.createLineBorder(Color.black))
        tabs.addTab("Request", logTable.getRequestViewer().getComponent())
        tabs.addTab("Response", logTable.getResponseViewer().getComponent())
        splitPane.setRightComponent(tabs)

        # top control panel
        controlPanel = JPanel(FlowLayout(FlowLayout.LEFT))

        toolLabel = JLabel("Select tool: ")
        controlPanel.add(toolLabel)


        tools = JavaArrayList(tools_keys)
        toolList = JComboBox(tools)
        toolList.addActionListener(external_filter_action_listener)
        controlPanel.add(toolList)

        startButton = JButton("Start")
        self.startButton = startButton
        controlPanel.add(startButton)
        stopButton = JButton("Stop")
        self.stopButton = stopButton
        controlPanel.add(stopButton)
        clearButton = JButton("Clear")
        self.clearButton = clearButton
        startButton.setEnabled(False)
        controlPanel.add(clearButton)
        scopeLabel = JLabel("In-scope items only?")
        controlPanel.add(scopeLabel)
        scopeCheckBox = JCheckBox()
        self.scopeCheckBox = scopeCheckBox
        controlPanel.add(scopeCheckBox)
        filterLabel = JLabel("Filter Query:")
        controlPanel.add(filterLabel)
        queryFilterText = JTextField(40)
        self.queryFilterText = queryFilterText
        controlPanel.add(queryFilterText)

        startButton.addActionListener(self.start_button_action_listener)

        stopButton.addActionListener(self.stop_button_action_listener)

        clearButton.addActionListener(self.clear_button_action_listener)

        controlPanel.setAlignmentX(0)
        self.this.add(controlPanel)
        self.this.add(splitPane)
Example #33
0
    def registerExtenderCallbacks(self, callbacks):

        # 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("Response Clusterer")

        # create the log and a lock on which to synchronize when adding log entries
        self._log = ArrayList()
        self._lock = Lock()

        # main split pane
        self._main_jtabedpane = JTabbedPane()

        # The split pane with the log and request/respponse details
        self._splitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT)

        # table of log entries
        logTable = Table(self)
        scrollPane = JScrollPane(logTable)
        self._splitpane.setLeftComponent(scrollPane)

        # List of log entries
        self._log_entries = []

        # tabs with request/response viewers
        tabs = JTabbedPane()
        self._requestViewer = callbacks.createMessageEditor(self, False)
        self._responseViewer = callbacks.createMessageEditor(self, False)
        tabs.addTab("Request", self._requestViewer.getComponent())
        tabs.addTab("Response", self._responseViewer.getComponent())
        self._splitpane.setRightComponent(tabs)

        #Setup the options
        self._optionsJPanel = JPanel()
        gridBagLayout = GridBagLayout()
        gbc = GridBagConstraints()
        self._optionsJPanel.setLayout(gridBagLayout)

        self.max_clusters = 500
        self.JLabel_max_clusters = JLabel("Maximum amount of clusters: ")
        gbc.gridy = 0
        gbc.gridx = 0
        self._optionsJPanel.add(self.JLabel_max_clusters, gbc)
        self.JTextField_max_clusters = JTextField(str(self.max_clusters), 5)
        self.JTextField_max_clusters.getDocument().addDocumentListener(self)
        gbc.gridx = 1
        self._optionsJPanel.add(self.JTextField_max_clusters, gbc)
        callbacks.customizeUiComponent(self.JLabel_max_clusters)
        callbacks.customizeUiComponent(self.JTextField_max_clusters)

        self.similarity = 0.95
        self.JLabel_similarity = JLabel("Similarity (between 0 and 1)")
        gbc.gridy = 1
        gbc.gridx = 0
        self._optionsJPanel.add(self.JLabel_similarity, gbc)
        self.JTextField_similarity = JTextField(str(self.similarity), 5)
        self.JTextField_similarity.getDocument().addDocumentListener(self)
        gbc.gridx = 1
        self._optionsJPanel.add(self.JTextField_similarity, gbc)
        callbacks.customizeUiComponent(self.JLabel_similarity)
        callbacks.customizeUiComponent(self.JTextField_similarity)

        self.use_quick_similar = False
        self.JLabel_use_quick_similar = JLabel(
            "Use set intersection of space splitted tokens for similarity (default: optimized difflib.SequenceMatcher.quick_ratio)"
        )
        gbc.gridy = 2
        gbc.gridx = 0
        self._optionsJPanel.add(self.JLabel_use_quick_similar, gbc)
        self.JCheckBox_use_quick_similar = JCheckBox("")
        self.JCheckBox_use_quick_similar.addActionListener(self)
        gbc.gridx = 1
        self._optionsJPanel.add(self.JCheckBox_use_quick_similar, gbc)
        callbacks.customizeUiComponent(self.JCheckBox_use_quick_similar)

        self.response_max_size = 10 * 1024  #10kb
        self.JLabel_response_max_size = JLabel("Response max size (bytes)")
        gbc.gridy = 3
        gbc.gridx = 0
        self._optionsJPanel.add(self.JLabel_response_max_size, gbc)
        self.JTextField_response_max_size = JTextField(
            str(self.response_max_size), 5)
        self.JTextField_response_max_size.getDocument().addDocumentListener(
            self)
        gbc.gridx = 1
        self._optionsJPanel.add(self.JTextField_response_max_size, gbc)
        callbacks.customizeUiComponent(self.JLabel_response_max_size)
        callbacks.customizeUiComponent(self.JTextField_response_max_size)

        self.uninteresting_mime_types = ('JPEG', 'CSS', 'GIF', 'script', 'GIF',
                                         'PNG', 'image')
        self.uninteresting_status_codes = ()
        self.uninteresting_url_file_extensions = ('js', 'css', 'zip', 'war',
                                                  'jar', 'doc', 'docx', 'xls',
                                                  'xlsx', 'pdf', 'exe', 'dll',
                                                  'png', 'jpeg', 'jpg', 'bmp',
                                                  'tif', 'tiff', 'gif', 'webp',
                                                  'm3u', 'mp4', 'm4a', 'ogg',
                                                  'aac', 'flac', 'mp3', 'wav',
                                                  'avi', 'mov', 'mpeg', 'wmv',
                                                  'swf', 'woff', 'woff2')

        about = "<html>"
        about += "Author: floyd, @floyd_ch, http://www.floyd.ch<br>"
        about += "modzero AG, http://www.modzero.ch<br>"
        about += "<br>"
        about += "<h3>Getting an overview of the tested website</h3>"
        about += "<p style=\"width:500px\">"
        about += "This plugin clusters all response bodies by similarity and shows a summary, one request/response per cluster. "
        about += 'Adjust similarity in the options if you get too few or too many entries in the "One member of each cluster" '
        about += "tab. The plugin will allow a tester to get an overview of the tested website's responses from all tools (scanner, proxy, etc.). "
        about += "As similarity comparison "
        about += "can use a lot of ressources, only small, in-scope responses that have interesting response codes, "
        about += "file extensions and mime types are processed. "
        about += "</p>"
        about += "</html>"
        self.JLabel_about = JLabel(about)
        self.JLabel_about.setLayout(GridBagLayout())
        self._aboutJPanel = JScrollPane(self.JLabel_about)

        # customize our UI components
        callbacks.customizeUiComponent(self._splitpane)
        callbacks.customizeUiComponent(logTable)
        callbacks.customizeUiComponent(scrollPane)
        callbacks.customizeUiComponent(tabs)

        # add the splitpane and options to the main jtabedpane
        self._main_jtabedpane.addTab("One member of each cluster", None,
                                     self._splitpane, None)
        self._main_jtabedpane.addTab("Options", None, self._optionsJPanel,
                                     None)
        self._main_jtabedpane.addTab("About & README", None, self._aboutJPanel,
                                     None)

        # clusters will grow up to self.max_clusters response bodies...
        self._clusters = set()
        self.Similarity = Similarity()

        # Now load the already stored
        with self._lock:
            log_entries_from_storage = self.load_project_setting("log_entries")
            if log_entries_from_storage:
                for toolFlag, req, resp, url in log_entries_from_storage:
                    try:
                        self.add_new_log_entry(toolFlag, req, resp, url)
                    except Exception as e:
                        print "Exception when deserializing a stored log entry", toolFlag, url
                        print e

        # Important: Do this at the very end (otherwise we could run into troubles locking up entire threads)
        # add the custom tab to Burp's UI
        callbacks.addSuiteTab(self)

        # register ourselves as an HTTP listener
        callbacks.registerHttpListener(self)
Example #34
0
class BurpExtender(IBurpExtender, ITab, IHttpListener,
                   IMessageEditorController, AbstractTableModel,
                   IContextMenuFactory, IExtensionStateListener):

    #
    # implement IBurpExtender
    #

    def registerExtenderCallbacks(self, callbacks):
        # 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("Burp Scope Monitor Experimental")

        self.GLOBAL_HANDLER_ANALYZED = False
        self.GLOBAL_HANDLER = False
        self.STATUS = False
        self.AUTOSAVE_REQUESTS = 10
        self.AUTOSAVE_TIMEOUT = 600  # 10 minutes should be fine
        self.CONFIG_INSCOPE = True

        self.BAD_EXTENSIONS_DEFAULT = [
            '.gif', '.png', '.js', '.woff', '.woff2', '.jpeg', '.jpg', '.css',
            '.ico', '.m3u8', '.ts', '.svg'
        ]
        self.BAD_MIMES_DEFAULT = [
            'gif', 'script', 'jpeg', 'jpg', 'png', 'video', 'mp2t'
        ]

        self.BAD_EXTENSIONS = self.BAD_EXTENSIONS_DEFAULT
        self.BAD_MIMES = self.BAD_MIMES_DEFAULT

        # create the log and a lock on which to synchronize when adding log entries

        self._currentlyDisplayedItem = None

        self.SELECTED_MODEL_ROW = 0
        self.SELECTED_VIEW_ROW = 0

        self._log = ArrayList()
        self._fullLog = ArrayList()
        self._lock = Lock()
        self._lockFile = Lock()

        # main split pane
        self._parentPane = JTabbedPane()

        self._splitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT)

        ##### config pane
        self._config = JTabbedPane()

        config = JPanel()
        iexport = JPanel()

        #config.setLayout(BorderLayout())
        config.setLayout(None)
        iexport.setLayout(None)

        # config radio button
        X_BASE = 40
        Y_OFFSET = 5
        Y_OPTION = 200
        Y_OPTION_SPACING = 20
        Y_CHECKMARK_SPACING = 20

        self.showAllButton = JRadioButton(SHOW_ALL_BUTTON_LABEL, True)
        self.showNewButton = JRadioButton(SHOW_NEW_BUTTON_LABEL, False)
        self.showTestedButton = JRadioButton(SHOW_TEST_BUTTON_LABEL, False)

        self.showAllButton.setBounds(40, 60 + Y_OFFSET, 400, 30)
        self.showNewButton.setBounds(40, 80 + Y_OFFSET, 400, 30)
        self.showTestedButton.setBounds(40, 100 + Y_OFFSET, 400, 30)
        #self.showNewButton = JRadioButton(SHOW_NEW_BUTTON_LABEL, False)
        #self.showTestedButton = JRadioButton(SHOW_TEST_BUTTON_LABEL, False)

        self.showAllButton.addActionListener(self.handleRadioConfig)
        self.showNewButton.addActionListener(self.handleRadioConfig)
        self.showTestedButton.addActionListener(self.handleRadioConfig)

        self.clearButton = JButton("Clear")
        self.clearButton.addActionListener(self.handleClearButton)
        self.clearButton.setBounds(40, 20, 100, 30)

        self.startButton = JButton(MONITOR_ON_LABEL)
        self.startButton.addActionListener(self.handleStartButton)
        self.startButton.setBounds(150, 20, 200, 30)

        self.badExtensionsLabel = JLabel("Ignore extensions:")
        self.badExtensionsLabel.setBounds(X_BASE, 150, 200, 30)

        self.badExtensionsText = JTextArea("")
        self.loadBadExtensions()
        self.badExtensionsText.setBounds(X_BASE, 175, 310, 30)

        self.badExtensionsButton = JButton("Save")
        self.badExtensionsButton.addActionListener(
            self.handleBadExtensionsButton)
        self.badExtensionsButton.setBounds(355, 175, 70, 30)

        self.badExtensionsDefaultButton = JButton("Load Defaults")
        self.badExtensionsDefaultButton.addActionListener(
            self.handleBadExtensionsDefaultButton)
        self.badExtensionsDefaultButton.setBounds(430, 175, 120, 30)

        self.badMimesLabel = JLabel("Ignore mime types:")
        self.badMimesLabel.setBounds(X_BASE, 220, 200, 30)

        self.badMimesText = JTextArea("")
        self.loadBadMimes()
        self.badMimesText.setBounds(X_BASE, 245, 310, 30)

        self.badMimesButton = JButton("Save")
        self.badMimesButton.addActionListener(self.handleBadMimesButton)
        self.badMimesButton.setBounds(355, 245, 70, 30)

        self.badMimesDefaultButton = JButton("Load Defaults")
        self.badMimesDefaultButton.addActionListener(
            self.handleBadMimesDefaultButton)
        self.badMimesDefaultButton.setBounds(430, 245, 120, 30)

        self.otherLabel = JLabel("Other:")
        self.otherLabel.setBounds(40, 300, 120, 30)

        self.otherLabel2 = JLabel("Other:")
        self.otherLabel2.setBounds(X_BASE, Y_OPTION, 120, 30)

        self.autoSaveOption = JCheckBox("Auto save periodically")
        self.autoSaveOption.setSelected(True)
        self.autoSaveOption.addActionListener(self.handleAutoSaveOption)
        self.autoSaveOption.setBounds(X_BASE, Y_OPTION + Y_CHECKMARK_SPACING,
                                      420, 30)

        self.repeaterOptionButton = JCheckBox(
            "Repeater request automatically marks as analyzed")
        self.repeaterOptionButton.setSelected(True)
        self.repeaterOptionButton.addActionListener(
            self.handleRepeaterOptionButton)
        self.repeaterOptionButton.setBounds(50, 330, 420, 30)

        self.scopeOptionButton = JCheckBox("Follow Burp Target In Scope rules")
        self.scopeOptionButton.setSelected(True)
        self.scopeOptionButton.addActionListener(self.handleScopeOptionButton)
        self.scopeOptionButton.setBounds(50, 350, 420, 30)

        self.startOptionButton = JCheckBox("Autostart Scope Monitor")
        self.startOptionButton.setSelected(True)
        self.startOptionButton.addActionListener(self.handleStartOption)
        self.startOptionButton.setBounds(50, 350 + Y_OPTION_SPACING, 420, 30)

        self.markTestedRequestsProxy = JCheckBox(
            "Color request in Proxy tab if analyzed")
        self.markTestedRequestsProxy.setSelected(True)
        self.markTestedRequestsProxy.addActionListener(
            self.handleTestedRequestsProxy)
        self.markTestedRequestsProxy.setBounds(50, 350 + Y_OPTION_SPACING * 2,
                                               420, 30)

        self.markNotTestedRequestsProxy = JCheckBox(
            "Color request in Proxy tab if NOT analyzed")
        self.markNotTestedRequestsProxy.setSelected(True)
        self.markNotTestedRequestsProxy.addActionListener(
            self.handleNotTestedRequestsProxy)
        self.markNotTestedRequestsProxy.setBounds(50,
                                                  350 + Y_OPTION_SPACING * 3,
                                                  420, 30)

        self.saveButton = JButton("Save now")
        self.saveButton.addActionListener(self.handleSaveButton)
        self.saveButton.setBounds(X_BASE + 320, 95, 90, 30)

        self.loadButton = JButton("Load now")
        self.loadButton.addActionListener(self.handleLoadButton)
        self.loadButton.setBounds(X_BASE + 420, 95, 90, 30)

        self.selectPath = JButton("Select path")
        self.selectPath.addActionListener(self.selectExportFile)
        self.selectPath.setBounds(X_BASE + 530, 60, 120, 30)

        self.selectPathText = JTextArea("")
        self.selectPathText.setBounds(X_BASE, 60, 510, 30)

        self.selectPathLabel = JLabel("State file:")
        self.selectPathLabel.setBounds(X_BASE, 30, 200, 30)

        bGroup = ButtonGroup()

        bGroup.add(self.showAllButton)
        bGroup.add(self.showNewButton)
        bGroup.add(self.showTestedButton)

        config.add(self.clearButton)
        config.add(self.startButton)
        config.add(self.startOptionButton)
        config.add(self.showAllButton)
        config.add(self.showNewButton)
        config.add(self.showTestedButton)

        config.add(self.badExtensionsButton)
        config.add(self.badExtensionsText)
        config.add(self.badExtensionsLabel)

        config.add(self.badMimesButton)
        config.add(self.badMimesText)
        config.add(self.badMimesLabel)

        config.add(self.badExtensionsDefaultButton)
        config.add(self.badMimesDefaultButton)

        config.add(self.otherLabel)
        config.add(self.repeaterOptionButton)
        config.add(self.scopeOptionButton)
        config.add(self.markTestedRequestsProxy)
        config.add(self.markNotTestedRequestsProxy)

        iexport.add(self.saveButton)
        iexport.add(self.loadButton)
        iexport.add(self.selectPath)
        iexport.add(self.selectPathText)
        iexport.add(self.selectPathLabel)
        iexport.add(self.otherLabel2)
        iexport.add(self.autoSaveOption)

        self._config.addTab("General", config)
        self._config.addTab("Import/Export", iexport)

        ##### end config pane

        self._parentPane.addTab("Monitor", self._splitpane)
        self._parentPane.addTab("Config", self._config)

        # table of log entries
        self.logTable = Table(self)

        #self.logTable.setDefaultRenderer(self.logTable.getColumnClass(0), ColoredTableCellRenderer(self))

        self.logTable.setAutoCreateRowSorter(True)
        self.logTable.setRowSelectionAllowed(True)

        renderer = ColoredTableCellRenderer(self)
        #column = TableColumn(0, 190, renderer, None)

        print 'Initiating... '

        # this could be improved by fetching initial dimensions
        self.logTable.getColumn("URL").setPreferredWidth(720)  # noscope
        self.logTable.getColumn("URL").setResizable(True)

        self.logTable.getColumn("Checked").setCellRenderer(renderer)
        self.logTable.getColumn("Checked").setPreferredWidth(80)
        self.logTable.getColumn("Checked").setMaxWidth(80)

        self.logTable.getColumn("Method").setPreferredWidth(120)
        #self.logTable.getColumn("Method").setMaxWidth(120)
        self.logTable.getColumn("Method").setResizable(True)

        self.logTable.getColumn("Time").setPreferredWidth(120)  # noscope
        self.logTable.getColumn("Time").setResizable(True)

        scrollPane = JScrollPane(self.logTable)
        self._splitpane.setLeftComponent(scrollPane)

        # tabs with request/response viewers
        tabs = JTabbedPane()
        self._requestViewer = callbacks.createMessageEditor(self, False)
        self._responseViewer = callbacks.createMessageEditor(self, False)
        tabs.addTab("Request", self._requestViewer.getComponent())
        tabs.addTab("Response", self._responseViewer.getComponent())
        self._splitpane.setRightComponent(tabs)

        ## Row sorter shit

        #self._tableRowSorterAutoProxyAutoAction = CustomTableRowSorter(self.logTable.getModel())
        #self.logTable.setRowSorter(self._tableRowSorterAutoProxyAutoAction)

        markAnalyzedButton = JMenuItem("Mark Requests as Analyzed")
        markAnalyzedButton.addActionListener(markRequestsHandler(self, True))

        markNotAnalyzedButton = JMenuItem("Mark Requests as NOT Analyzed")
        markNotAnalyzedButton.addActionListener(
            markRequestsHandler(self, False))

        sendRequestMenu = JMenuItem("Send Request to Repeater")
        sendRequestMenu.addActionListener(sendRequestRepeater(self))

        deleteRequestMenu = JMenuItem("Delete request")
        deleteRequestMenu.addActionListener(deleteRequestHandler(self))

        self.menu = JPopupMenu("Popup")
        self.menu.add(markAnalyzedButton)
        self.menu.add(markNotAnalyzedButton)
        self.menu.add(sendRequestMenu)
        self.menu.add(deleteRequestMenu)

        # customize our UI components
        callbacks.customizeUiComponent(self._parentPane)
        callbacks.customizeUiComponent(self._splitpane)
        callbacks.customizeUiComponent(self._config)
        callbacks.customizeUiComponent(config)
        callbacks.customizeUiComponent(self.logTable)
        callbacks.customizeUiComponent(scrollPane)
        callbacks.customizeUiComponent(tabs)

        callbacks.registerContextMenuFactory(self)
        callbacks.registerExtensionStateListener(self)
        callbacks.registerScannerCheck(passiveScanner(self))

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

        # register ourselves as an HTTP listener
        callbacks.registerHttpListener(self)

        self.loadConfigs()

        print "Loaded!"

        print "Experimental import state.. "
        self.importState("")

        self.SC = sched.scheduler(time.time, time.sleep)
        self.SCC = self.SC.enter(10, 1, self.autoSave, (self.SC, ))
        self.SC.run()

        return

    ##### CUSTOM CODE #####
    def loadConfigs(self):

        if self._callbacks.loadExtensionSetting("CONFIG_AUTOSTART") == "False":
            self.startOptionButton.setSelected(False)
            self.startOrStop(None, False)
        else:
            self.startOptionButton.setSelected(True)
            self.startOrStop(None, True)

        if self._callbacks.loadExtensionSetting("exportFile") != "":
            self.selectPathText.setText(
                self._callbacks.loadExtensionSetting("exportFile"))

        if self._callbacks.loadExtensionSetting("CONFIG_REPEATER") == "True":
            self.repeaterOptionButton.setSelected(True)
        else:
            self.repeaterOptionButton.setSelected(False)

        if self._callbacks.loadExtensionSetting("CONFIG_INSCOPE") == "True":
            self.scopeOptionButton.setSelected(True)
        else:
            self.scopeOptionButton.setSelected(False)

        if self._callbacks.loadExtensionSetting("CONFIG_AUTOSAVE") == "True":
            self.autoSaveOption.setSelected(True)
        else:
            self.autoSaveOption.setSelected(False)

        if self._callbacks.loadExtensionSetting(
                "CONFIG_HIGHLIGHT_TESTED") == "True":
            self.markTestedRequestsProxy.setSelected(True)
        else:
            self.markTestedRequestsProxy.setSelected(False)

        if self._callbacks.loadExtensionSetting(
                "CONFIG_HIGHLIGHT_NOT_TESTED") == "True":
            self.markNotTestedRequestsProxy.setSelected(True)
        else:
            self.markNotTestedRequestsProxy.setSelected(False)

        return

    def selectExportFile(self, event):
        parentFrame = JFrame()
        fileChooser = JFileChooser()
        fileChooser.setDialogTitle("Specify file to save state")
        fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY)

        userSelection = fileChooser.showOpenDialog(parentFrame)

        if (userSelection == JFileChooser.APPROVE_OPTION):
            fileLoad = fileChooser.getSelectedFile()
            filename = fileLoad.getAbsolutePath()

            self.selectPathText.setText(filename)
            print 'Filename selected:' + filename
            self._callbacks.saveExtensionSetting("exportFile", filename)

        return

    def extensionUnloaded(self):
        print 'extension unloading.. '

        print 'canceling scheduler.. '
        map(self.SC.cancel, self.SC.queue)
        return

    def loadBadExtensions(self):
        bad = self._callbacks.loadExtensionSetting("badExtensions")
        if bad:
            self.badExtensionsText.setText(bad)
            # transform text to array
            bad = bad.replace(" ", "")
            self.BAD_EXTENSIONS = bad.split(",")
        else:
            print 'no bad extension saved, reverting'
            self.badExtensionsText.setText(", ".join(self.BAD_EXTENSIONS))

    def loadBadMimes(self):
        bad = self._callbacks.loadExtensionSetting("badMimes")
        if bad:
            self.badMimesText.setText(bad)

            bad = bad.replace(" ", "")
            self.BAD_MIMES = bad.split(",")
        else:
            print 'no bad mimes saved, reverting'
            self.badMimesText.setText(", ".join(self.BAD_MIMES))

    ## GLOBAL CONTEXT CODE ##

    def createMenuItems(self, invocation):
        responses = invocation.getSelectedMessages()
        if responses > 0:
            ret = LinkedList()
            analyzedMenuItem = JMenuItem("Mark as analyzed")
            notAnalyzedMenuItem = JMenuItem("Mark as NOT analyzed")

            for response in responses:
                analyzedMenuItem.addActionListener(
                    handleMenuItems(self, response, "analyzed"))
                notAnalyzedMenuItem.addActionListener(
                    handleMenuItems(self, response, "not"))
            ret.add(analyzedMenuItem)
            ret.add(notAnalyzedMenuItem)
            return ret

    def getEndpoint(self, requestResponse):
        url_ = str(self._helpers.analyzeRequest(requestResponse).getUrl())
        o = urlparse(url_)

        url = o.scheme + "://" + o.netloc + o.path
        #print "Url3: " + url
        return url

    def getMethod(self, requestResponse):
        return self._helpers.analyzeRequest(requestResponse).getMethod()

    ##### CUSTOM CODE #####
    def handleTestedRequestsProxy(self, event):
        self._callbacks.saveExtensionSetting(
            "CONFIG_HIGHLIGHT_TESTED",
            str(self.markTestedRequestsProxy.isSelected()))
        return

    def handleNotTestedRequestsProxy(self, event):
        self._callbacks.saveExtensionSetting(
            "CONFIG_HIGHLIGHT_NOT_TESTED",
            str(self.markNotTestedRequestsProxy.isSelected()))
        return

    def handleStartOption(self, event):
        self._callbacks.saveExtensionSetting(
            "CONFIG_AUTOSTART", str(self.startOptionButton.isSelected()))
        #print 'saving autostart: ' + str(self.startOptionButton.isSelected())
        return

    def startOrStop(self, event, autoStart):
        if (self.startButton.getText() == MONITOR_OFF_LABEL) or autoStart:
            self.startButton.setText(MONITOR_ON_LABEL)
            self.startButton.setBackground(GREEN_COLOR)
            self.STATUS = True
        else:
            self.startButton.setText(MONITOR_OFF_LABEL)
            self.startButton.setBackground(RED_COLOR)
            self.STATUS = False

    def handleStartButton(self, event):
        self.startOrStop(event, False)

    def handleAutoSaveOption(self, event):
        self._callbacks.saveExtensionSetting(
            "CONFIG_AUTOSAVE", str(self.autoSaveOption.isSelected()))
        return

    def handleSaveButton(self, event):
        self.exportState("")

    def handleLoadButton(self, event):
        self.importState("")

    def handleRepeaterOptionButton(self, event):
        self._callbacks.saveExtensionSetting(
            "CONFIG_REPEATER", str(self.repeaterOptionButton.isSelected()))
        return

    def handleScopeOptionButton(self, event):
        self.CONFIG_INSCOPE = self.scopeOptionButton.isSelected()
        self._callbacks.saveExtensionSetting("CONFIG_INSCOPE",
                                             str(self.CONFIG_INSCOPE))
        return

    def handleBadExtensionsButton(self, event):
        #print "before BAD array: "
        print self.BAD_EXTENSIONS

        extensions = self.badExtensionsText.getText()
        self._callbacks.saveExtensionSetting("badExtensions", extensions)
        print 'New extensions blocked: ' + extensions
        bad = extensions.replace(" ", "")
        self.BAD_EXTENSIONS = bad.split(",")
        #print "BAD array: "
        #print self.BAD_EXTENSIONS

    def handleBadExtensionsDefaultButton(self, event):
        self.BAD_EXTENSIONS = self.BAD_EXTENSIONS_DEFAULT
        self.badExtensionsText.setText(", ".join(self.BAD_EXTENSIONS))
        self._callbacks.saveExtensionSetting("badExtensions",
                                             ", ".join(self.BAD_EXTENSIONS))
        return

    def handleBadMimesDefaultButton(self, event):
        self.BAD_MIMES = self.BAD_MIMES_DEFAULT
        self.badMimesText.setText(", ".join(self.BAD_MIMES))
        self._callbacks.saveExtensionSetting("badExtensions",
                                             ", ".join(self.BAD_MIMES))
        return

    def handleBadMimesButton(self, event):
        mimes = self.badMimesText.getText()
        self._callbacks.saveExtensionSetting("badMimes", mimes)
        print 'New mimes blocked: ' + mimes
        bad = mimes.replace(" ", "")
        self.BAD_MIMES = bad.split(",")

    def handleClearButton(self, event):
        print 'Clearing table'
        self._lock.acquire()
        self._log = ArrayList()
        self._fullLog = ArrayList()
        self._lock.release()
        return

    def handleRadioConfig(self, event):
        #print ' radio button clicked '
        #print event.getActionCommand()
        self._lock.acquire()

        if event.getActionCommand() == SHOW_ALL_BUTTON_LABEL:
            print "Showing all"
            self._log = self._fullLog
        elif event.getActionCommand() == SHOW_NEW_BUTTON_LABEL:
            print "Showing new scope only"
            tmpLog = ArrayList()
            for item in self._fullLog:
                if not (item._analyzed):
                    tmpLog.add(item)
            self._log = tmpLog
        elif event.getActionCommand() == SHOW_TEST_BUTTON_LABEL:
            print "Showing tested scope only"
            tmpLog = ArrayList()
            for item in self._fullLog:
                if item._analyzed:
                    tmpLog.add(item)
            self._log = tmpLog
        else:
            print "unrecognized radio label"

        self.fireTableDataChanged()
        #self._tableRowSorterAutoProxyAutoAction.toggleSortOrder(1)
        #self.toggleSortOrder(2)

        #self.logTable.toggleSortOrder(2)

        # refresh table?

        self._lock.release()

    #
    # implement ITab
    #

    def getTabCaption(self):
        return "Scope Monitor"

    def getUiComponent(self):
        return self._parentPane

    #
    # implement IHttpListener
    #

    def markAnalyzed(self, messageIsRequest, state):
        #print "markAnalyzed..."
        self._lock.acquire()

        url = self.getEndpoint(messageIsRequest)
        for item in self._log:
            if url == item._url:
                item._analyzed = state
                self._lock.release()
                return
        self._lock.release()
        return

    def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo):
        # only process requests

        #print "processing httpMessage.."
        #print messageIsRequest

        print "processHttpMessage toolFlag: " + str(toolFlag)
        #print " -- " + str(self._callbacks.getToolName(toolFlag)) + " -- "

        if not (self.STATUS):
            return

        #print "global handler status: (true): " + str(self.GLOBAL_HANDLER)
        #print "(processHTTP) messageIsRequest"
        #print messageIsRequest

        isFromPassiveScan = False
        if toolFlag == 1234:
            print "1 processHttpMessage: processing passiveScan item"
            isFromPassiveScan = True

        if toolFlag != 1234:
            if messageIsRequest and not (self.GLOBAL_HANDLER):
                print "1.5 processHttpMessage droping message"
                return

        if self.scopeOptionButton.isSelected():
            url = self._helpers.analyzeRequest(messageInfo).getUrl()
            if not self._callbacks.isInScope(url):
                #print 'Url not in scope, skipping.. '
                return

        #print "still processing httpMessage.., request came from: " + self._callbacks.getToolName(toolFlag)
        if toolFlag == 1234:
            print "2 processHttpMessage: processing passiveScan item; setting toolFlag to proxy (4)"
            toolFlag = 4

        #toolFlag = 4
        if ((self._callbacks.getToolName(toolFlag) != "Repeater")
                and (self._callbacks.getToolName(toolFlag) != "Proxy")
                and (self._callbacks.getToolName(toolFlag) != "Target")):
            #print 'Aborting processHTTP, request came from: ' + str(self._callbacks.getToolName(toolFlag))
            print "Droping request from " + str(
                self._callbacks.getToolName(toolFlag))
            return

        #print "---> still processing from tool: " + str(self._callbacks.getToolName(toolFlag))

        url = self.getEndpoint(messageInfo)
        method = self.getMethod(messageInfo)

        #print "(processHTTP) before extensions check: " + url

        for extension in self.BAD_EXTENSIONS:
            if url.endswith(extension):
                return

        if messageInfo.getResponse():
            mime = self._helpers.analyzeResponse(
                messageInfo.getResponse()).getStatedMimeType()
            #print 'Declared mime:' + mime
            mime = mime.lower()
            if mime in self.BAD_MIMES:
                #print 'Bad mime:' + mime
                return

        #print "[httpMessage] before lock"
        # create a new log entry with the message details
        self._lock.acquire()
        row = self._log.size()

        for item in self._log:
            if url == item._url:
                if method == self._helpers.analyzeRequest(
                        item._requestResponse).getMethod():
                    #print 'duplicate URL+method, skipping.. '
                    self._lock.release()

                    # has it been analyzed?
                    analyzed = False
                    if self._callbacks.getToolName(toolFlag) == "Repeater":
                        if self.repeaterOptionButton.isSelected():
                            analyzed = True
                            #print "[httpMessage] setting analyzed as true"
                    if self.GLOBAL_HANDLER_ANALYZED:
                        analyzed = True

                    item._analyzed = analyzed
                    self.paintItems(messageInfo, item)

                    return

        #print "[httpMessage] before setComment"
        if not (isFromPassiveScan):
            messageInfo.setComment(SCOPE_MONITOR_COMMENT)
        # reached here, must be new entry
        analyzed = False
        if self._callbacks.getToolName(toolFlag) == "Repeater":
            if self.repeaterOptionButton.isSelected():
                analyzed = True
                #print "[httpMessage] setting analyzed as true"
        if self.GLOBAL_HANDLER_ANALYZED:
            analyzed = True

        #print "[httpMessage] after comment"
        #print 'in httpmessage, response:'
        #print self._helpers.analyzeResponse(messageInfo.getResponse())

        date = datetime.datetime.fromtimestamp(
            time.time()).strftime('%H:%M:%S %d %b %Y')
        entry = LogEntry(toolFlag,
                         self._callbacks.saveBuffersToTempFiles(messageInfo),
                         url, analyzed, date, method)
        #print "toolFlag: " + str(toolFlag)

        #print "(processHTTP) Adding URL: " + url
        self._log.add(entry)
        self._fullLog.add(entry)
        self.fireTableRowsInserted(row, row)

        self.paintItems(messageInfo, entry)

        self._lock.release()

        #print "columnCoun:" + str(self.logTable.getColumnCount())

    #
    # extend AbstractTableModel
    #

    def paintItems(self, messageInfo, item):
        '''
        print "in paint Items"
        print "mark color is: (true)" + str(self.markTestedRequestsProxy.isSelected())
        print "global handler analyzed:           :" + str(self.GLOBAL_HANDLER_ANALYZED)
        print "item analyzed should be the same ^^:" + str(item._analyzed)
        '''
        if (self.markTestedRequestsProxy.isSelected()) and (
                item._analyzed and self.GLOBAL_HANDLER_ANALYZED):
            messageInfo.setHighlight("green")
            return

        if self.markNotTestedRequestsProxy.isSelected() and not (
                item._analyzed):
            messageInfo.setHighlight("red")

    def getRowCount(self):
        try:
            return self._log.size()
        except:
            return 0

    def getColumnCount(self):
        return 4

    def getColumnName(self, columnIndex):
        if columnIndex == 0:
            return "Checked"
        if columnIndex == 1:
            return "URL"
        if columnIndex == 2:
            return "Method"
        if columnIndex == 3:
            return "Time"

    def getValueAt(self, rowIndex, columnIndex):
        logEntry = self._log.get(rowIndex)

        #self.setBackground(Color.GREEN)
        return self.returnEntry(rowIndex, columnIndex, logEntry)

        if self.showNewButton.isSelected() and not (logEntry._analyzed):
            return self.returnEntry(rowIndex, columnIndex, logEntry)
        elif self.showTestedButton.isSelected() and logEntry._analyzed:
            return self.returnEntry(rowIndex, columnIndex, logEntry)
        elif self.showAllButton.isSelected():
            return self.returnEntry(rowIndex, columnIndex, logEntry)

    def returnEntry(self, rowIndex, columnIndex, entry):
        logEntry = self._log.get(rowIndex)
        if columnIndex == 0:
            if logEntry._analyzed:
                return "True"
            else:
                return "False"
        if columnIndex == 1:
            return self._helpers.urlDecode(logEntry._url)
        if columnIndex == 2:
            return logEntry._method
        if columnIndex == 3:
            return logEntry._date
            # return date
        return ""

    #
    # implement IMessageEditorController
    # this allows our request/response viewers to obtain details about the messages being displayed
    #

    def getHttpService(self):
        return self._currentlyDisplayedItem.getHttpService()

    def getRequest(self):
        #print 'getRequest called'
        return self._currentlyDisplayedItem.getRequest()

    def getResponse(self):
        #print 'getResponse called: '
        print self._currentlyDisplayedItem.getResponse()
        return self._currentlyDisplayedItem.getResponse()

    def exportRequest(self, entity, filename):

        line = str(entity._analyzed) + ","
        line = line + self._helpers.urlEncode(entity._url).replace(
            ",", "%2c") + ","  # URL is encoded so we should be good
        line = line + entity._method + ","
        line = line + entity._date
        line = line + '\n'

        #print 'Exporting: "' + line + '"'
        return line

    def exportUrlEncode(self, url):
        return self._helpers.urlEncode(url).replace(",", "%2c")

    def exportState(self, filename):
        filename = self.selectPathText.getText()

        if filename == "":
            filename = self._callbacks.loadExtensionSetting("exportFile")
            print 'Empty filename, skipping export'
            return
        else:
            self._callbacks.saveExtensionSetting("exportFile", filename)

        print 'saving state to: ' + filename

        savedUrls = []

        self._lockFile.acquire()
        try:
            with open(filename, 'r') as fr:
                savedEntries = fr.read().splitlines()
                savedUrls = []
                for savedEntry in savedEntries:
                    savedUrls.append(savedEntry.split(",")[1])
                #print "savedUrls len: " + str(len(savedUrls))
                #print "savedUrls:"
                #print savedUrls
                fr.close()
        except IOError:
            print "Autosaving skipped as file doesn't exist yet"

        with open(filename, 'a+') as f:

            for item in self._log:
                if self.exportUrlEncode(item._url) not in savedUrls:
                    line = self.exportRequest(item, "xx")
                    f.write(line)
            f.close()
        self._lockFile.release()

        return

    def importState(self, filename):
        filename = self.selectPathText.getText()

        if filename == "":
            filename = self._callbacks.loadExtensionSetting("exportFile")
            print 'Empty filename, skipping import'
            return
        else:
            self._callbacks.saveExtensionSetting("exportFile", filename)

        print 'loading state from: ' + filename

        self.STATUS = False

        self._lockFile.acquire()
        with open(filename, 'r') as f:

            proxy = self._callbacks.getProxyHistory()

            proxyItems = []
            for item in proxy:
                if item.getComment():
                    if SCOPE_MONITOR_COMMENT in item.getComment():
                        proxyItems.append(item)

            print 'proxyItems has: ' + str(len(proxyItems))
            # TODO - if no proxy items, sraight to import

            lines = f.read().splitlines()
            for line in lines:
                data = line.split(",")
                url = data[1]
                url = self._helpers.urlDecode(url)

                #print 'Saving: ' + url
                if not self._callbacks.isInScope(URL(url)):
                    print '-- imported url not in scope, skipping.. '
                    continue

                analyzed = False
                if data[0] == "True":
                    analyzed = True

                #print '.. simulating url search.. '
                requestResponse = None
                for request in proxyItems:
                    if url == self.getEndpoint(request):
                        #print 'Match found when importing for url: ' + url
                        requestResponse = request
                        break

                self._log.add(
                    LogEntry("", requestResponse, url, analyzed, data[3],
                             data[2]))

            self._lockFile.release()
        print 'finished loading.. '
        #print 'size: ' + str(self._log.size())
        self.fireTableDataChanged()

        if self.startButton.getText() == MONITOR_ON_LABEL:
            self.STATUS = True

        return

    def autoSave(self, sc):
        #print 'autosaving.. lol what'
        if self.autoSaveOption.isSelected():
            print "[" + self.getTime(
            ) + "] autosaving to " + self._callbacks.loadExtensionSetting(
                "exportFile")
            self.exportState("")

        self.SC.enter(self.AUTOSAVE_TIMEOUT, 1, self.autoSave, (self.SC, ))
        return

    def getTime(self):
        date = datetime.datetime.fromtimestamp(
            time.time()).strftime('%H:%M:%S')
        return date
Example #35
0
class BurpExtender(IBurpExtender, IContextMenuFactory, ITab,
                   IExtensionStateListener, IMessageEditorController,
                   IHttpListener):
    '''
    IBurpExtender:               Hook into burp and inherit base classes
    ITab:                        Create new tabs inside burp
    IMessageEditorTabFactory:    Access createNewInstance
    '''
    def registerExtenderCallbacks(self, callbacks):

        # Set encoding to utf-8 to avoid some errors
        reload(sys)
        sys.setdefaultencoding('utf8')

        # Keep a reference to callback object and helper object
        self._callbacks = callbacks
        self._helpers = callbacks.getHelpers()

        # Set the extension name that shows in the burp extension menu
        callbacks.setExtensionName("InjectionScanner")

        # Create the log and a lock on which to synchronize when adding log entries
        self._log = ArrayList()
        self._logLock = Lock()
        self._httpLock = Lock()

        # The length of the basis used to fetch abnormal data, default to zero
        self._basisLen = 0

        # 1: {POST. GET}; 2: {urlencoded, json, xml}
        self._postGet = 'NaN'
        self._dataType = 'NaN'

        # Scan list
        self._simpleList = [
            '\'', '\"', '/', '/*', '#', ')', '(', ')\'', '(\'', 'and 1=1',
            'and 1=2', 'and 1>2', 'and 12', '+', 'and+12', '/**/and/**/1'
        ]
        self._xmlList = ['a', 'b', 'c', 'd', 'e']  # Not setted

        # Response mutex: True = is blocking; False = free to go
        # self._mutexR = False

        # Other classes instance
        self._dataTable = Guis_DefaultTM()
        self._logTable = Guis_AbstractTM(self)
        self._xh = XMLHandler()
        listeners = Guis_Listeners(self, self._logTable)
        '''
        Setting GUIs
        '''
        # Divide the whole pane two: one upper and one lower pane
        self._mainSplitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT)
        self._mainSplitpane.setResizeWeight(0.4)

        # Initizlize request table
        dataTable = JTable(self._dataTable)
        dataScrollPane = JScrollPane(dataTable)
        dataScrollPane.setPreferredSize(Dimension(0, 125))
        self._dataTable.addTableModelListener(listeners)

        # Initialize log table
        logTable = Guis_LogTable(self._logTable)
        logScrollPane = JScrollPane(logTable)
        logScrollPane.setPreferredSize(Dimension(0, 125))

        # Split the upper pane to two panes
        tableSplitpane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT)
        tableSplitpane.setResizeWeight(0.5)

        # Set the data table to the left and log to the right
        tableSplitpane.setLeftComponent(dataScrollPane)
        tableSplitpane.setRightComponent(logScrollPane)

        # Tabs with request/response viewers
        tabs = JTabbedPane()
        self._requestViewer = callbacks.createMessageEditor(self, False)
        self._responseViewer = callbacks.createMessageEditor(self, False)
        tabs.addTab("Request", self._requestViewer.getComponent())
        tabs.addTab("Response", self._responseViewer.getComponent())

        # Create buttons that do operation with the test
        self._basisLabel = JLabel('Basis: ' + str(self._basisLen))
        self._levelLabel = JLabel('Level:')
        self._setBasisButton = JButton('Set Basis')
        self._hitOnceButton = JButton('Hit Once')
        self._autoScanButton = JButton('Auto Scan')
        self._clearLogButton = JButton('Clear Log')
        self._cancelButton = JButton('Cancel')
        self._levelSelection = JComboBox()

        self._levelSelection.addItem('1')
        self._levelSelection.addItem('2')
        self._levelSelection.addItem('3')
        self._hitOnceButton.addActionListener(listeners)
        self._autoScanButton.addActionListener(listeners)
        self._clearLogButton.addActionListener(listeners)
        self._setBasisButton.addActionListener(listeners)
        self._cancelButton.addActionListener(listeners)
        self._basisLabel.setPreferredSize(Dimension(100, 20))

        # Create bottom pane for holding the buttons
        buttonPane = JPanel()
        buttonPane.setLayout(BorderLayout())
        centerPane = JPanel()
        leftPane = JPanel()
        rightPane = JPanel()
        leftPane.add(self._basisLabel)
        centerPane.add(self._setBasisButton)
        centerPane.add(self._hitOnceButton)
        centerPane.add(self._autoScanButton)
        centerPane.add(self._cancelButton)
        centerPane.add(self._clearLogButton)
        rightPane.add(self._levelLabel)
        rightPane.add(self._levelSelection)
        buttonPane.add(centerPane, BorderLayout.CENTER)
        buttonPane.add(leftPane, BorderLayout.WEST)
        buttonPane.add(rightPane, BorderLayout.EAST)

        # Create and set the bottom panel that holds viewers and buttons
        utilPane = JPanel()
        utilPane.setLayout(BorderLayout())
        utilPane.add(tabs, BorderLayout.CENTER)
        utilPane.add(buttonPane, BorderLayout.SOUTH)

        self._mainSplitpane.setLeftComponent(tableSplitpane)
        self._mainSplitpane.setRightComponent(utilPane)

        # Customize UI components
        callbacks.customizeUiComponent(self._mainSplitpane)
        callbacks.customizeUiComponent(dataTable)
        callbacks.customizeUiComponent(dataScrollPane)
        callbacks.customizeUiComponent(logTable)
        callbacks.customizeUiComponent(logScrollPane)
        callbacks.customizeUiComponent(tabs)
        callbacks.customizeUiComponent(buttonPane)
        callbacks.customizeUiComponent(utilPane)
        callbacks.customizeUiComponent(self._basisLabel)
        callbacks.customizeUiComponent(self._setBasisButton)
        callbacks.customizeUiComponent(self._hitOnceButton)
        callbacks.customizeUiComponent(self._autoScanButton)
        callbacks.customizeUiComponent(self._clearLogButton)
        callbacks.customizeUiComponent(self._levelSelection)
        callbacks.customizeUiComponent(self._cancelButton)

        # Add the custom tab to Burp's UI
        callbacks.addSuiteTab(self)

        # Register the context menu and message editor for new tabs
        callbacks.registerContextMenuFactory(self)

        # Register as a HTTP listener
        callbacks.registerHttpListener(self)

        return

    '''
    ITab implementation
    '''

    def getTabCaption(self):
        return 'InjectionScanner'

    def getUiComponent(self):
        return self._mainSplitpane

    '''
    IContextMenuFactory implementation
    '''

    def createMenuItems(self, invocation):
        menu = []

        # Which part of the interface the user selects
        ctx = invocation.getInvocationContext()

        # Message viewer request will show menu item if selected by the user
        if ctx == 0 or ctx == 2:
            menu.append(
                swing.JMenuItem("Send to InjectionScanner",
                                None,
                                actionPerformed=lambda x, inv=invocation: self.
                                sendToExtender(inv)))

        return menu if menu else None

    '''
    IMessageEditorController Implementation
    '''

    def getHttpService(self):
        return self._currentlyDisplayedItem.getHttpService()

    def getRequest(self):
        return self._currentlyDisplayedItem.getRequest()

    def getResponse(self):
        return self._currentlyDisplayedItem.getResponse()

    '''
    IHttpListener implementation
    '''

    def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo):

        # Skip this function if the message is request
        if messageIsRequest:
            return

        # Lock the log entry in case race condition
        self._logLock.acquire()
        row = self._log.size()

        # Fetch request message
        requestBody = messageInfo.getRequest()
        requestInfo = self._helpers.analyzeResponse(requestBody)
        requestHeaders = requestInfo.getHeaders()
        if self._postGet == 'POST':
            requestData = self._helpers.bytesToString(
                requestBody[requestInfo.getBodyOffset():])
        elif self._postGet == 'GET':
            for header in requestHeaders:

                if 'GET' in header:
                    # If the request is GET, update the GET data
                    requestUrl = re.sub('^GET\s+', '', header, re.IGNORECASE)
                    requestUrl = re.sub('\sHTTP/1.1\S*', '', requestUrl,
                                        re.IGNORECASE)

                    if '?' in requestUrl:
                        requestData = re.sub('\S*\?', '', requestUrl,
                                             re.IGNORECASE)

                    else:
                        print('processHttpMessage: no parameter in GET url')
        else:
            print('processHttpMessage: _postGet not defined')
            self._logLock.release()
            return

        # Fetch the http type (GET/POST)
        httpType = requestHeaders[0].split(' ')

        # Fetch response message
        responseBody = messageInfo.getResponse()
        responseInfo = self._helpers.analyzeResponse(responseBody)
        responseHeaders = responseInfo.getHeaders()
        self._responseLength = ''

        # Fetch the content length
        self._responseLength = self.fetchContentLength(responseHeaders)

        # If the response message is auto-generated, ignore it. If not, add it into the log list
        if self._callbacks.getToolName(toolFlag) != 'Proxy':

            self._log.add(
                LogEntry(httpType[0], requestData,
                         self._callbacks.saveBuffersToTempFiles(messageInfo),
                         self._responseLength))
            self._logTable.fireTableRowsInserted(row, row)

        self._logLock.release()

    '''
    Fetch content length from the headers given
    '''

    def fetchContentLength(self, fromHeaders):

        for header in fromHeaders:
            if re.search('^Content-Length', header, re.IGNORECASE) is not None:
                return re.sub('^Content-Length\:\s+', '', header,
                              re.IGNORECASE)

    '''
    When the user select 'Send to InjectionScanner', call this function
    '''

    def sendToExtender(self, invocation):

        # Init/reset request data before sending to extender
        self.initRequestInfo()

        try:
            # Initialize basic information
            invMessage = invocation.getSelectedMessages()
            requestMessage = invMessage[0]
            requestInfo = self._helpers.analyzeRequest(requestMessage)
            self._requestBody = requestMessage.getRequest()

            # Set the _currentlyDisplayedItem so each time the data is sent to the extender
            self._currentlyDisplayedItem = self._callbacks.saveBuffersToTempFiles(
                requestMessage)

            # Fetch the request data
            bodyLen = len(self._helpers.bytesToString(self._requestBody))
            if requestInfo.getBodyOffset() < bodyLen:
                self._requestData = self._helpers.bytesToString(
                    self._requestBody[requestInfo.getBodyOffset():])
            elif requestInfo.getBodyOffset() == bodyLen:
                self._requestData = ''
            else:
                print('sendToExtender: body length < body offset')

            # Fetch the headers and Http service
            requestHeaders = list(requestInfo.getHeaders())
            self._httpService = requestMessage.getHttpService()

            # Initialize POST/GET identifier and User-Agent
            for header in requestHeaders:
                if re.search('^POST', header, re.IGNORECASE) is not None:
                    self._postGet = 'POST'

                elif re.search('^GET', header, re.IGNORECASE) is not None:
                    self._postGet = 'GET'

                    # If the request is GET, initialize the url and GET data
                    self._requestUrl = re.sub('^GET\s+', '', header,
                                              re.IGNORECASE)
                    self._requestUrl = re.sub('\sHTTP/1.1\S*', '',
                                              self._requestUrl, re.IGNORECASE)

                    if '?' in self._requestUrl:
                        self._requestDataGet = re.sub('\S*\?', '',
                                                      self._requestUrl,
                                                      re.IGNORECASE)

                    else:
                        print('sendToExtender: no parameter in GET url')

                # If the request if POST, fetch the request data type by content type
                if self._postGet == 'POST' and re.search(
                        '^Content-Type', header, re.IGNORECASE) is not None:

                    contentType = re.sub('^Content-Type', '', header,
                                         re.IGNORECASE)
                    if 'urlencoded' in contentType:
                        self._dataType = 'urlencoded'

                    elif 'json' in contentType:
                        self._dataType = 'json'

                    elif 'xml' in contentType or 'http' in conentType:
                        self._dataType = 'xml'

                    else:
                        print(
                            'sendToExtender: _dataType is not supported, do not scan'
                        )

                # Initialze the User-Agent if it exists
                if re.search('^User-Agent', header, re.IGNORECASE) is not None:
                    self._userAgent = re.sub('^User-Agent\:\s+', '', header,
                                             re.IGNORECASE)

            # If there's no content type in the header,fetch from data
            if self._postGet == 'POST' and self._dataType == '':

                if self._requestData != '':

                    if self._requestData[
                            0] == '{' and '}' in self._requestData and ':' in self._requestData:
                        self._dataType = 'json'

                    elif self._requestData[0] == '<' and self._requestData[
                            -1] == '>':
                        self._dataType = 'xml'

                    else:
                        self._dataType = 'urlencoded'

                else:
                    print(
                        'sendToExtender: _postGet is POST but _requestData is null'
                    )

            # Clear the table before adding elements
            self._dataTable.setRowCount(0)

            # Update request viewer
            self.updateRequestViewer()

            # Fill request data
            self.fillRequestData()

        except Exception as e:
            print(e)

    '''
    Fill the data into the request table
    '''

    def fillRequestData(self):

        # If _postGet is GET, also adds URL to the table
        if self._postGet == 'GET':

            dataList = self._requestDataGet.split('&')
            for data in dataList:

                if '=' in data:
                    x = data.split('=', 1)
                    self._dataDict[str(x[0])] = str(x[1])
                    self._dataTable.addRow([str(x[0]), str(x[1])])
                    self._dataLen += 1

            self._dataTable.addRow(['URL', self._requestUrl])
            self._UrlRow = self._dataLen

            if self._userAgent != '':
                self._dataTable.addRow(['User-Agent', self._userAgent])

        elif self._postGet == 'POST':

            if self._dataType == 'urlencoded':

                dataList = self._requestData.split('&')
                for data in dataList:

                    if '=' in data:
                        x = data.split('=', 1)
                        self._dataDict[str(x[0])] = str(x[1])
                        self._dataTable.addRow([str(x[0]), str(x[1])])
                        self._dataLen += 1

            elif self._dataType == 'json':

                self._dataDict = json.loads(self._requestData)
                for key in self._dataDict:

                    # Convert '"' to '\"' to be the same as that in the data
                    value = str(self._dataDict[key])
                    if '\"' in value:
                        value = value.replace('\"', '\\\"')
                    self._dataDict[key] = value

                    self._dataTable.addRow([str(key), self._dataDict[key]])
                    self._dataLen += 1

            elif self._dataType == 'xml':

                # Use xml package to convert the xml string to dict
                # Note1: the xml dict will be in reverse order
                # Note2: the arrtibute will also be added into dict, need to be pop
                # Note3: special characters like \" will be considered as "
                xml.sax.parseString(self._requestData, self._xh)
                self._attr = re.sub('\>(\S*\s*)*', '', self._requestData[1:],
                                    re.IGNORECASE)

                self._dataDict = self._xh.getDict()
                self._dataDict.pop(self._attr)

                for key in self._dataDict:
                    self._dataTable.addRow(
                        [str(key), str(self._dataDict[key])])
                    self._dataLen += 1

            else:
                print('fillRequestData: _dataType not defined')

            if self._userAgent != '':
                self._dataTable.addRow(['User-Agent', self._userAgent])
                self._savedUserAgent = self._userAgent

        else:
            print('fillRequestData: _postGet not defined')

    '''
    Receive & update the response after sending request to the server
    '''

    def receiveResponse(self):

        # Init/reset response data before receiving response
        self.initResponseInfo()

        # Launch the http thread
        self._httpThread = Thread(target=self.makeRequest,
                                  args=(
                                      self._httpService,
                                      self._requestBody,
                                  ))
        self._httpThread.start()

    '''
    Make Http request to a service
    '''

    def makeRequest(self, httpService, requestBody):
        self._httpLock.acquire()

        # Disable the hit buttons before starting the thread
        self._hitOnceButton.setEnabled(False)
        self._autoScanButton.setEnabled(False)

        self._responseMessage = self._callbacks.makeHttpRequest(
            httpService, requestBody)

        # Enable the hit buttons
        self._hitOnceButton.setEnabled(True)
        self._autoScanButton.setEnabled(True)

        # Unblock the mutex
        self._httpLock.release()

    '''
    updateRequestViewer
    '''

    def updateRequestViewer(self):
        self._requestViewer.setMessage(self.getRequest(), True)

    '''
    updateResponseViewer
    '''

    def updateResponseViewer(self):
        self._responseViewer.setMessage(self.getResponse(), False)

    '''
    Level 1 auto: only loop through the data, do not modify the 'submit' section
    '''

    def autoScan1(self):
        # TODO: Add a 'cancel' button to stop when the user think it takes too long
        # TODO: Add XML support
        if self._postGet == 'GET':

            for i in range(0, self._dataLen):

                title = self._dataTable.getValueAt(i, 0)
                baseValue = self._dataDict[title]

                for value in self._simpleList:

                    # TODO: update more value that should not be changed
                    if 'submit' not in title.lower(
                    ) and 'submit' not in self._dataDict[title].lower(
                    ) and 'search' not in title.lower(
                    ) and 'search' not in self._dataDict[title].lower():

                        # Update the table in case the loop interrupt in the middle
                        # Note that the URL will be automatically updated due to this code, so no need to manually update the URL section
                        self._dataTable.setValueAt(value, i, 1)

                        # Send & request the HTTP request/response
                        self.updateRequestViewer()
                        self.receiveResponse()

                # Reset the table
                self._dataTable.setValueAt(baseValue, i, 1)

        if self._postGet == 'POST':

            if self._dataType == 'urlencoded' or self._dataType == 'json':

                for i in range(0, self._dataLen):

                    title = self._dataTable.getValueAt(i, 0)
                    baseValue = self._dataDict[title]

                    if 'submit' in title.lower() or 'submit' in self._dataDict[
                            title].lower() or 'search' in title.lower(
                            ) or 'search' in self._dataDict[title].lower():
                        continue

                    for value in self._simpleList:

                        self._dataTable.setValueAt(value, i, 1)

                        self.updateRequestViewer()
                        self.receiveResponse()

                    # Reset the table
                    self._dataTable.setValueAt(baseValue, i, 1)

            elif self._dataType == 'xml':

                for i in range(0, self._dataLen):

                    title = self._dataTable.getValueAt(i, 0)
                    baseValue = self._dataDict[title]

                    for value in self._xmlList:

                        # Update the table in case the loop interrupt in the middle
                        self._dataTable.setValueAt(value, i, 1)

                        # Send & request the HTTP request/response
                        self.updateRequestViewer()
                        self.receiveResponse()

                    # Reset the table
                    self._dataTable.setValueAt(baseValue, i, 1)

    '''
    Level 2 auto: loop through the data as well as the user agent (if exist)
    '''

    def autoScan2(self):

        # If the User-Agent does not exist, only performs level 1 auto
        if self._userAgent != '':

            baseUserAgent = self._userAgent
            baseExpression = 'User-Agent: ' + baseUserAgent

            for value in self._simpleList:
                oldExpression = 'User-Agent: ' + self._userAgent
                newExpression = 'User-Agent: ' + value

                # Update the values accordingly
                requestBodyString = self._helpers.bytesToString(
                    self._requestBody)
                self._requestBody = requestBodyString.replace(
                    oldExpression, newExpression)
                self._userAgent = value

                self.updateRequestViewer()
                self.receiveResponse()

            # Reset the value back to original after each loop
            requestBodyString = self._helpers.bytesToString(self._requestBody)
            self._requestBody = requestBodyString.replace(
                newExpression, baseExpression)
            self._savedUserAgent = baseUserAgent
            self.updateRequestViewer()

        # Perform level 1 scan also
        self.autoScan1()

    '''
    Level 3 auto: Alpha: use the timer to perform blind insertion
    '''

    # TODO: 目前只支持GET/urlencoded,后续添加更多支持
    def autoScan3(self):

        self._timeReach = False
        timer = Timer(5, self.timeReach)

        # Modify the first element to perform blind injection
        title = self._dataTable.getValueAt(i, 0)
        oldExpression = title + '=' + self._dataDict[title]
        newExpression = title + '=' + '1\' and if(1=0,1, sleep(10)) --+'

        if self._postGet == 'GET':

            # Update the values accordingly
            requestBodyString = self._helpers.bytesToString(self._requestBody)
            self._requestBody = requestBodyString.replace(
                oldExpression, newExpression)
            self._requestDataGet = self._requestDataGet.replace(
                oldExpression, newExpression)
            self._requestUrl = self._requestUrl.replace(
                oldExpression, newExpression)
            self._dataDict[title] = '1\' and if(1=0,1, sleep(10)) --+'
            self._requestModel.setValueAt('1\' and if(1=0,1, sleep(10)) --+',
                                          0, 1)

        elif self._postGet == 'POST':

            if self._dataType == 'urlencoded':

                # Update the values accordingly
                requestBodyString = self._helpers.bytesToString(
                    self._requestBody)
                self._requestBody = requestBodyString.replace(
                    oldExpression, newExpression)
                self._requestData = self._requestData.replace(
                    oldExpression, newExpression)
                self._dataDict[title] = '1\' and if(1=0,1, sleep(10)) --+'
                self._requestModel.setValueAt(
                    '1\' and if(1=0,1, sleep(10)) --+', 0, 1)

            else:
                print('autoScan3: _dataType not supported')

        else:
            print('autoScan3: _postGet not defined')

        timer.start()

        self.updateRequestViewer()
        self.receiveResponse()

        # Print the result
        if self._timeReach:
            print('Delay scan succeed')
        else:
            print('Delay scan failed')

        # Cancel the timer
        timer.cancel()

    def timeReach(self):
        self._timeReach = True

    '''
    Fetch the 'abnormal' payloads that shows very different response length from the normal ones
    '''

    def getAbnormal(self, basis, coefficient):

        # If the basis is not set, do nothing
        abnormList = ArrayList()
        if basis == 0:
            return None

        # Fetch the abnormals from the log list
        for log in self._log:
            if float(log._responseLen) / float(basis) < coefficient or float(
                    basis) / float(log._responseLen) < coefficient:
                abnormList.append(log._payload)

        return abnormList

    '''
    Turn a simple dict of key/value pairs into XML
    '''

    def dictToXml(self, tag, d):

        elem = Element(tag)

        for key, val in d.items():
            child = Element(key)
            child.text = str(val)
            # Add element in reverse order so that the result is correct
            elem.insert(0, child)

        return elem

    '''
    initRequestInfo
    '''

    def initRequestInfo(self):
        self._postGet = ''
        self._userAgent = ''
        self._requestUrl = ''
        self._requestBody = ''
        self._requestData = ''
        self._requestDataGet = ''
        self._httpService = None
        self._dataDict = {}
        self._dataType = ''
        self._dataLen = 0
        self._attr = ''
        self._contentLength = 0
        self._currentlyDisplayedItem = None

    '''
    initResponseInfo
    '''

    def initResponseInfo(self):
        self._responseBody = None
        self._responseMessage = None
        self._responseLength = ''

    '''
    printRequest
    '''

    def printRequest(self):
        print('----------------')
        print(self._postGet)
        print('----------------')
        print(self._userAgent)
        print('----------------')
        print(self._requestUrl)
        print('----------------')
        print(self._requestBody)
        print('----------------')
        print(self._requestData)
        print('----------------')
        print(self._requestDataGet)
        print('----------------')
        print(self._httpService)
        print('----------------')
        print(self._dataDict)
        print('----------------')
        print(self._dataLen)
        print('----------------')
        print(self._attr)
        print('----------------')

    '''
    printResponse
    '''

    def printResponse(self):
        print('----------------')
        print(self._responseBody)
        print('----------------')
        print(self._responseMessage)
        print('----------------')
        print(self._responseLength)
        print('----------------')
Example #36
0
class ProtoBufEditorTab(burp.IMessageEditorTab):
    """Tab in interceptor/repeater for editing protobuf message.
    Decodes them to JSON and back.
    The message type is attached to this object.
    """
    def __init__(self, extender, controller, editable):

        self._extender = extender
        self._callbacks = extender.callbacks
        self._helpers = extender.helpers

        self._controller = controller

        self._text_editor = self._callbacks.createTextEditor()
        self._text_editor.setEditable(editable)
        self._editable = editable

        self._component = JSplitPane(JSplitPane.HORIZONTAL_SPLIT)
        self._component.setLeftComponent(self._text_editor.getComponent())
        self._component.setRightComponent(self.createButtonPane())
        self._component.setResizeWeight(0.8)

        self.message_type = None
        self._is_request = None
        self._encoder = None
        self._original_json = None
        self._content_info = None
        self._request_content_info = None
        self._request = None
        self._original_content = None

    def getTabCaption(self):
        """Return message tab caption"""
        return "Protobuf"

    def getMessage(self):
        """Transform the JSON format back to the binary protobuf message"""
        try:
            if self.message_type is None or not self.isModified():
                return self._original_content

            json_data = self._text_editor.getText().tostring()

            protobuf_data = blackboxprotobuf.protobuf_from_json(
                json_data, self.message_type)

            protobuf_data = self.encodePayload(protobuf_data)
            if 'set_protobuf_data' in dir(user_funcs):
                result = user_funcs.set_protobuf_data(
                    protobuf_data, self._original_content, self._is_request,
                    self._content_info, self._helpers, self._request,
                    self._request_content_info)
                if result is not None:
                    return result

            headers = self._content_info.getHeaders()
            return self._helpers.buildHttpMessage(headers, str(protobuf_data))

        except Exception as exc:
            self._callbacks.printError(traceback.format_exc())
            JOptionPane.showMessageDialog(
                self._component, "Error encoding protobuf: " + str(exc))
            # Resets state
            return self._original_content

    def setMessage(self, content, is_request, retry=True):
        """Get the data from the request/response and parse into JSON.
           sets self.message_type
        """
        # Save original content
        self._original_content = content
        if is_request:
            self._content_info = self._helpers.analyzeRequest(
                self._controller.getHttpService(), content)
        else:
            self._content_info = self._helpers.analyzeResponse(content)
        self._is_request = is_request
        self._request = None
        self._request_content_info = None

        if not is_request:
            self._request = self._controller.getRequest()
            self._request_content_info = self._helpers.analyzeRequest(
                self._controller.getHttpService(), self._request)

        message_hash = self.getMessageHash()

        # Try to find saved messsage type
        self.message_type = None
        if message_hash in self._extender.known_types:
            self.message_type = self._extender.known_types[message_hash]

        try:
            protobuf_data = None
            if 'get_protobuf_data' in dir(user_funcs):
                protobuf_data = user_funcs.get_protobuf_data(
                    content, is_request, self._content_info, self._helpers,
                    self._request, self._request_content_info)
            if protobuf_data is None:
                protobuf_data = content[self._content_info.getBodyOffset(
                ):].tostring()

            protobuf_data = self.decodePayload(protobuf_data)
            json_data, self.message_type = blackboxprotobuf.protobuf_to_json(
                protobuf_data, self.message_type)

            # Save the message type
            self._extender.known_types[message_hash] = self.message_type

            self._original_json = json_data
            self._text_editor.setText(json_data)
            success = True
        except Exception as exc:
            success = False
            self._callbacks.printError(traceback.format_exc())

        # Bring out of exception handler to avoid nexting handlers
        if not success:
            if retry:
                # Clear existing type info and retry
                prev_type = self.message_type
                self.message_type = None
                if message_hash in self._extender.known_types:
                    del self._extender.known_types[message_hash]
                try:
                    self.setMessage(content, is_request, False)
                except Exception as exc:
                    # If it still won't parse, restore the types
                    self.message_type = prev_type
                    self._extender.known_types[message_hash] = prev_type
            else:
                self._text_editor.setText("Error parsing protobuf")

    def decodePayload(self, payload):
        """Add support for decoding a few default methods. Including Base64 and GZIP"""
        if payload.startswith(bytearray([0x1f, 0x8b, 0x08])):
            gzip_decompress = zlib.decompressobj(-zlib.MAX_WBITS)
            self._encoder = 'gzip'
            return gzip_decompress.decompress(payload)

        # Try to base64 decode
        try:
            protobuf = base64.b64decode(payload, validate=True)
            self._encoder = 'base64'
            return protobuf
        except Exception as exc:
            pass

        #try:
        #    protobuf = base64.urlsafe_b64decode(payload)
        #    self._encoder = 'base64_url'
        #    return protobuf
        #except Exception as exc:
        #    pass

        self._encoder = None
        return payload

    def encodePayload(self, payload):
        """If we detected an encoding like gzip or base64 when decoding, redo
           that encoding step here
        """
        if self._encoder == 'base64':
            return base64.b64encode(payload)
        elif self._encoder == 'base64_url':
            return base64.urlsafe_b64encode(payload)
        elif self._encoder == 'gzip':
            gzip_compress = zlib.compressobj(-1, zlib.DEFLATED,
                                             -zlib.MAX_WBITS)
            self._encoder = 'gzip'
            return gzip_compress.compress(payload)
        else:
            return payload

    def getSelectedData(self):
        """Get text currently selected in message"""
        return self._text_editor.getSelectedText()

    def getUiComponent(self):
        """Return Java AWT component for this tab"""
        return self._component

    def isEnabled(self, content, is_request):
        """Try to detect a protobuf in the message to enable the tab. Defaults
           to content-type header of 'x-protobuf'. User overridable
        """
        # TODO implement some more default checks
        if is_request:
            info = self._helpers.analyzeRequest(content)
        else:
            info = self._helpers.analyzeResponse(content)

        if 'detect_protobuf' in dir(user_funcs):
            result = user_funcs.detect_protobuf(content, is_request, info,
                                                self._helpers)
            if result is not None:
                return result

        # Bail early if there is no body
        if info.getBodyOffset() == len(content):
            return False

        protobuf_content_types = ['x-protobuf', 'application/protobuf']
        # Check all headers for x-protobuf
        for header in info.getHeaders():
            if 'content-type' in header.lower():
                for protobuf_content_type in protobuf_content_types:
                    if protobuf_content_type in header.lower():
                        return True

        return False

    def isModified(self):
        """Return if the message was modified"""
        return self._text_editor.isTextModified()

    def createButtonPane(self):
        """Create a new button pane for the message editor tab"""
        self._button_listener = EditorButtonListener(self)

        panel = JPanel()
        panel.setLayout(BoxLayout(panel, BoxLayout.Y_AXIS))

        if self._editable:
            panel.add(self.createButton("Validate", "validate"))
        panel.add(self.createButton("Save Type", "save-type"))
        panel.add(self.createButton("Load Type", "load-type"))
        panel.add(self.createButton("Edit Type", "edit-type"))
        panel.add(self.createButton("Reset", "reset"))
        return panel

    def createButton(self, text, command):
        """Create a new button with the given text and command"""
        button = JButton(text)
        button.setAlignmentX(Component.CENTER_ALIGNMENT)
        button.setActionCommand(command)
        button.addActionListener(self._button_listener)
        return button

    def validateMessage(self):
        """Callback for validate button. Attempts to encode the message with
           the current type definition
        """
        try:
            json_data = self._text_editor.getText().tostring()
            blackboxprotobuf.protobuf_from_json(json_data, self.message_type)
            # If it works, save the message
            self._original_json = json_data
        except Exception as exc:
            JOptionPane.showMessageDialog(self._component, str(exc))
            self._callbacks.printError(traceback.format_exc())

    def resetMessage(self):
        """Drop any changes and reset the message. Callback for "reset"
           button
        """
        self._text_editor.setText(self._original_json)

    def getMessageHash(self):
        """Compute an "identifier" for the message which is used for sticky
           type definitions. User modifiable
        """
        message_hash = None
        if 'hash_message' in dir(user_funcs):
            message_hash = user_funcs.hash_message(
                self._original_content, self._is_request, self._content_info,
                self._helpers, self._request, self._request_content_info)
        if message_hash is None:
            # Base it off just the URL and request/response

            content_info = self._content_info if self._is_request else self._request_content_info
            url = content_info.getUrl().getPath()
            message_hash = (url, self._is_request)
        return message_hash

    def saveTypeMenu(self):
        """Open an input dialog to save the current type definiton"""
        type_defs = blackboxprotobuf.known_messages.keys()
        type_defs.insert(0, "New...")
        selection = JOptionPane.showInputDialog(self._component,
                                                "Select name for type",
                                                "Type selection",
                                                JOptionPane.PLAIN_MESSAGE,
                                                None, type_defs, None)
        if selection is None:
            return
        elif selection == "New...":
            selection = JOptionPane.showInputDialog("Enter new name")
        blackboxprotobuf.known_messages[selection] = self.message_type
        self._extender.suite_tab.updateList()

    def loadTypeMenu(self):
        """Open an input menu dialog to load a type definition"""
        type_defs = blackboxprotobuf.known_messages.keys()
        selection = JOptionPane.showInputDialog(self._component, "Select type",
                                                "Type selection",
                                                JOptionPane.PLAIN_MESSAGE,
                                                None, type_defs, None)

        if selection is None:
            return

        message_type = blackboxprotobuf.known_messages[selection]

        try:
            self.applyType(message_type)
        except Exception as exc:
            self._callbacks.printError(traceback.format_exc())
            JOptionPane.showMessageDialog(self._component,
                                          "Error applying type: " + str(exc))

    def applyType(self, typedef):
        """Apply a new typedef to the message. Throws an exception if type is invalid."""
        # Convert to protobuf as old type and re-interpret as new type
        old_message_type = self.message_type
        json_data = self._text_editor.getText().tostring()
        protobuf_data = blackboxprotobuf.protobuf_from_json(
            json_data, old_message_type)
        new_json, message_type = blackboxprotobuf.protobuf_to_json(
            str(protobuf_data), typedef)

        # Should exception out before now if there is an issue
        # Set the message type and reparse with the new type
        self.message_type = message_type
        self._text_editor.setText(str(new_json))

        message_hash = self.getMessageHash()
        self._extender.known_types[message_hash] = message_type
Example #37
0
    def draw(self):
        """  init autorize tabs
        """

        self._extender.logTable = Table(self._extender)

        tableWidth = self._extender.logTable.getPreferredSize().width
        self._extender.logTable.getColumn("ID").setPreferredWidth(
            Math.round(tableWidth / 50 * 2))
        self._extender.logTable.getColumn("Method").setPreferredWidth(
            Math.round(tableWidth / 50 * 3))
        self._extender.logTable.getColumn("URL").setPreferredWidth(
            Math.round(tableWidth / 50 * 25))
        self._extender.logTable.getColumn("Orig. Length").setPreferredWidth(
            Math.round(tableWidth / 50 * 4))
        self._extender.logTable.getColumn("Modif. Length").setPreferredWidth(
            Math.round(tableWidth / 50 * 4))
        self._extender.logTable.getColumn("Unauth. Length").setPreferredWidth(
            Math.round(tableWidth / 50 * 4))
        self._extender.logTable.getColumn(
            "Authorization Enforcement Status").setPreferredWidth(
                Math.round(tableWidth / 50 * 4))
        self._extender.logTable.getColumn(
            "Authorization Unauth. Status").setPreferredWidth(
                Math.round(tableWidth / 50 * 4))

        self._extender.tableSorter = TableRowSorter(self._extender.tableModel)
        rowFilter = TableRowFilter(self._extender)
        self._extender.tableSorter.setRowFilter(rowFilter)
        self._extender.logTable.setRowSorter(self._extender.tableSorter)

        self._extender._splitpane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT)
        self._extender._splitpane.setResizeWeight(1)
        self._extender.scrollPane = JScrollPane(self._extender.logTable)
        self._extender._splitpane.setLeftComponent(self._extender.scrollPane)
        self._extender.scrollPane.getVerticalScrollBar().addAdjustmentListener(
            AutoScrollListener(self._extender))

        copyURLitem = JMenuItem("Copy URL")
        copyURLitem.addActionListener(CopySelectedURL(self._extender))

        sendRequestMenu = JMenuItem("Send Original Request to Repeater")
        sendRequestMenu.addActionListener(
            SendRequestRepeater(self._extender, self._extender._callbacks,
                                True))

        sendRequestMenu2 = JMenuItem("Send Modified Request to Repeater")
        sendRequestMenu2.addActionListener(
            SendRequestRepeater(self._extender, self._extender._callbacks,
                                False))

        sendResponseMenu = JMenuItem("Send Responses to Comparer")
        sendResponseMenu.addActionListener(
            SendResponseComparer(self._extender, self._extender._callbacks))

        retestSelecteditem = JMenuItem("Retest selected request")
        retestSelecteditem.addActionListener(
            RetestSelectedRequest(self._extender))

        deleteSelectedItem = JMenuItem("Delete")
        deleteSelectedItem.addActionListener(
            DeleteSelectedRequest(self._extender))

        self._extender.menu = JPopupMenu("Popup")
        self._extender.menu.add(sendRequestMenu)
        self._extender.menu.add(sendRequestMenu2)
        self._extender.menu.add(sendResponseMenu)
        self._extender.menu.add(copyURLitem)
        self._extender.menu.add(retestSelecteditem)
        # self.menu.add(deleteSelectedItem) disabling this feature until bug will be fixed.
        message_editor = MessageEditor(self._extender)

        self._extender.tabs = JTabbedPane()
        self._extender._requestViewer = self._extender._callbacks.createMessageEditor(
            message_editor, False)
        self._extender._responseViewer = self._extender._callbacks.createMessageEditor(
            message_editor, False)

        self._extender._originalrequestViewer = self._extender._callbacks.createMessageEditor(
            message_editor, False)
        self._extender._originalresponseViewer = self._extender._callbacks.createMessageEditor(
            message_editor, False)

        self._extender._unauthorizedrequestViewer = self._extender._callbacks.createMessageEditor(
            message_editor, False)
        self._extender._unauthorizedresponseViewer = self._extender._callbacks.createMessageEditor(
            message_editor, False)

        self._extender.tabs.addTab(
            "Modified Request", self._extender._requestViewer.getComponent())
        self._extender.tabs.addTab(
            "Modified Response", self._extender._responseViewer.getComponent())

        self._extender.tabs.addTab(
            "Original Request",
            self._extender._originalrequestViewer.getComponent())
        self._extender.tabs.addTab(
            "Original Response",
            self._extender._originalresponseViewer.getComponent())

        self._extender.tabs.addTab(
            "Unauthenticated Request",
            self._extender._unauthorizedrequestViewer.getComponent())
        self._extender.tabs.addTab(
            "Unauthenticated Response",
            self._extender._unauthorizedresponseViewer.getComponent())

        self._extender.tabs.addTab("Configuration", self._extender.pnl)
        self._extender.tabs.setSelectedIndex(6)
        self._extender._splitpane.setRightComponent(self._extender.tabs)
Example #38
0
class BurpExtender(IBurpExtender, ITab, IHttpListener, IMessageEditorController, AbstractTableModel):
    
    #
    # implement IBurpExtender
    #
    
    def	registerExtenderCallbacks(self, callbacks):
        # 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("Test Auth | Cookie Repalce ")
        
        # create the log and a lock on which to synchronize when adding log entries
        self._log = ArrayList()
        self._lock = Lock()
        
        # main split pane
        self._splitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT)

        # user jpanel add compenents
        
        self._panel=JPanel()
        self._panel.setLayout(BorderLayout())

        subpanel=JPanel()
        button =JButton("OK")
        subpanel.add(button)
    

        self._panel.add(subpanel,BorderLayout.NORTH)

        # table of log entries
        logTable = Table(self)
        scrollPane = JScrollPane(logTable)
        self._splitpane.setLeftComponent(scrollPane)

        self._panel.add(self._splitpane,BorderLayout.CENTER)

        # tabs with request/response viewers
        tabs = JTabbedPane()
        self._requestViewer = callbacks.createMessageEditor(self, False)
        self._responseViewer = callbacks.createMessageEditor(self, False)
        tabs.addTab("Request", self._requestViewer.getComponent())
        tabs.addTab("Response", self._responseViewer.getComponent())
        self._splitpane.setRightComponent(tabs)
        
        # customize our UI components
        callbacks.customizeUiComponent(self._splitpane)
        # callbacks.customizeUiComponent(logTable)
        # callbacks.customizeUiComponent(scrollPane)
        # callbacks.customizeUiComponent(tabs)

        callbacks.customizeUiComponent(self._panel)
        callbacks.customizeUiComponent(subpanel)
        # callbacks.customizeUiComponent(button)
        
        # add the custom tab to Burp's UI
        callbacks.addSuiteTab(self)
        
        # register ourselves as an HTTP listener
        callbacks.registerHttpListener(self)
        
        return
        
    #
    # implement ITab
    #
    
    def getTabCaption(self):
        return "Auth Test"
    
    def getUiComponent(self):
        return self._panel
        
    #
    # implement IHttpListener
    #
    
    def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo):
        # only process requests
        if messageIsRequest:
            return

        if messageInfo.getHttpService().getHost()!=host:
            return 
        
        if toolFlag==4:
            bytesRequest=messageInfo.getRequest()
            requestInfo=self._helpers.analyzeRequest(messageInfo.getHttpService(),bytesRequest)
            bytesRequestBody=bytesRequest[requestInfo.getBodyOffset():]

            file = requestInfo.getUrl().getFile()

            if file in extract_file or re.match(reobj,file):
                return

            path=requestInfo.getUrl().getPath()

            if '.' in path:
                ext = path.split('.')[-1]
            else:
                ext = ''

            if ext  in ["jpg","png","gif","ico","mp4","js","css","map","html"]:
                return

            headers=requestInfo.getHeaders()
            newHeaders=[]
            for header in headers:
                if header.startswith("Cookie:"):
                    newHeaders.append(Cookie)
                else:
                    newHeaders.append(header)
                
            
            bytesNewRequest=self._helpers.buildHttpMessage(newHeaders,bytesRequestBody)
            
            newRequestResponse=self._callbacks.makeHttpRequest(messageInfo.getHttpService(),bytesNewRequest)
            

            responseInfo=self._helpers.analyzeResponse(newRequestResponse.getResponse())

            # if abs(len(newRequestResponse.getResponse())-len(messageInfo.getResponse()))>500:
            #     return


            # create a new log entry with the message details
            self._lock.acquire()
            row = self._log.size()

            log_entry=LogEntry(toolFlag, 
                requestInfo.getMethod(),
                self._callbacks.saveBuffersToTempFiles(newRequestResponse), 
                responseInfo.getStatusCode(),
                self._helpers.analyzeRequest(messageInfo).getUrl())
            
            self._log.add(log_entry)
            self.fireTableRowsInserted(row, row)
            self._lock.release()

    #
    # extend AbstractTableModel
    #
    
    def getRowCount(self):
        try:
            return self._log.size()
        except:
            return 0

    def getColumnCount(self):
        return 4

    def getColumnName(self, columnIndex):
        if columnIndex == 0:
            return "Tool"
        if columnIndex == 1:
            return "Method"
        if columnIndex == 2:
            return "Status"
        if columnIndex == 3:
            return "URL"
        return ""

    def getValueAt(self, rowIndex, columnIndex):
        logEntry = self._log.get(rowIndex)
        if columnIndex == 0:
            return self._callbacks.getToolName(logEntry._tool)
        if columnIndex == 1:
            return logEntry._method
        if columnIndex == 2:
            return logEntry._status
        if columnIndex == 3:
            return logEntry._url.toString()
        return ""

    #
    # implement IMessageEditorController
    # this allows our request/response viewers to obtain details about the messages being displayed
    #
    
    def getHttpService(self):
        return self._currentlyDisplayedItem.getHttpService()

    def getRequest(self):
        return self._currentlyDisplayedItem.getRequest()

    def getResponse(self):
        return self._currentlyDisplayedItem.getResponse()
Example #39
0
    def registerExtenderCallbacks(self, callbacks):

        self._panel = JPanel()
        self._panel.setLayout(BorderLayout())
        #self._panel.setSize(400,400)

        # sourrounding try\except because Burp is not giving enough info
        try:

            # creating all the UI elements
            # create the split pane
            self._split_pane_horizontal = JSplitPane(
                JSplitPane.HORIZONTAL_SPLIT)
            self._split_panel_vertical = JSplitPane(JSplitPane.VERTICAL_SPLIT)

            # create panels
            self._panel_top = JPanel()
            self._panel_top.setLayout(BorderLayout())
            self._panel_bottom = JPanel()
            self._panel_bottom.setLayout(BorderLayout())
            self._panel_right = JPanel()
            self._panel_right.setLayout(BorderLayout())
            self._panel_request = JPanel()
            self._panel_request.setLayout(BorderLayout())
            self._panel_response = JPanel()
            self._panel_response.setLayout(BorderLayout())

            # create the tabbed pane used to show request\response
            self._tabbed_pane = JTabbedPane(JTabbedPane.TOP)

            # create the tabbed pane used to show aslan++\concretization file
            self._tabbed_pane_editor = JTabbedPane(JTabbedPane.TOP)

            # create the bottom command for selecting the SQL file and
            # generating the model
            self._button_generate = JButton(
                'Generate!', actionPerformed=self._generate_model)
            self._button_save = JButton('Save',
                                        actionPerformed=self._save_model)
            self._button_select_sql = JButton(
                'Select SQL', actionPerformed=self._select_sql_file)
            self._text_field_sql_file = JTextField(20)

            self._panel_bottom_commands = JPanel()
            layout = GroupLayout(self._panel_bottom_commands)
            layout.setAutoCreateGaps(True)
            layout.setAutoCreateContainerGaps(True)
            seq_layout = layout.createSequentialGroup()
            seq_layout.addComponent(self._text_field_sql_file)
            seq_layout.addComponent(self._button_select_sql)
            seq_layout.addComponent(self._button_generate)
            seq_layout.addComponent(self._button_save)
            layout.setHorizontalGroup(seq_layout)

            # create the message editors that will be used to show request and response
            self._message_editor_request = callbacks.createMessageEditor(
                None, True)
            self._message_editor_response = callbacks.createMessageEditor(
                None, True)

            # create the table that will be used to show the messages selected for
            # the translation

            self._columns_names = ('Host', 'Method', 'URL')
            dataModel = NonEditableModel(self._table_data, self._columns_names)
            self._table = JTable(dataModel)
            self._scrollPane = JScrollPane()
            self._scrollPane.getViewport().setView((self._table))

            popmenu = JPopupMenu()
            delete_item = JMenuItem("Delete")
            delete_item.addActionListener(self)
            popmenu.add(delete_item)
            self._table.setComponentPopupMenu(popmenu)
            self._table.addMouseListener(self)

            # add all the elements
            self._panel_request.add(
                self._message_editor_request.getComponent())
            self._panel_response.add(
                self._message_editor_response.getComponent())

            self._tabbed_pane.addTab("Request", self._panel_request)
            self._tabbed_pane.addTab("Response", self._panel_response)

            self._panel_top.add(self._scrollPane, BorderLayout.CENTER)

            self._panel_bottom.add(self._tabbed_pane, BorderLayout.CENTER)
            scroll = JScrollPane(self._panel_bottom)

            self._panel_right.add(self._tabbed_pane_editor,
                                  BorderLayout.CENTER)
            self._panel_right.add(self._panel_bottom_commands,
                                  BorderLayout.PAGE_END)

            self._split_panel_vertical.setTopComponent(self._panel_top)
            self._split_panel_vertical.setBottomComponent(scroll)
            self._split_pane_horizontal.setLeftComponent(
                self._split_panel_vertical)
            self._split_pane_horizontal.setRightComponent(self._panel_right)

            self._panel.addComponentListener(self)
            self._panel.add(self._split_pane_horizontal)

            self._callbacks = callbacks
            callbacks.setExtensionName("WAFEx")
            callbacks.addSuiteTab(self)
            callbacks.registerContextMenuFactory(self)
        except Exception as e:
            exc_type, exc_obj, exc_tb = sys.exc_info()
            fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
            print(exc_type, fname, exc_tb.tb_lineno)
Example #40
0
class BurpExtender(IBurpExtender, ITab, IMessageEditorController, AbstractTableModel, IContextMenuFactory):

    def registerExtenderCallbacks(self, callbacks):
        # 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("PT Vulnerabilities Manager")
        
        self.config = SafeConfigParser()
        self.createSection('projects')
        self.createSection('general')
        self.config.read('config.ini')
        self.chooser = JFileChooser()
        # create the log and a lock on which to synchronize when adding log entries
        self._log = ArrayList()
        self._lock = Lock()
        
        self.logTable = Table(self)
        self.logTable.getColumnModel().getColumn(0).setMaxWidth(35)
        self.logTable.getColumnModel().getColumn(1).setMinWidth(100)

        self._requestViewer = self._callbacks.createMessageEditor(self, False)
        self._responseViewer = self._callbacks.createMessageEditor(self, False)

        self.initVulnerabilityTab()
        self.initProjSettingsTab()
        self.initTabs()
        self.initCallbacks()

        if self.projPath.getText() != None:
            self.loadVulnerabilities(self.projPath.getText())

        print "Thank you for installing PT Vulnerabilities Manager v1.0 extension"
        print "by Barak Tawily\n\n\n"
        print "Disclaimer:\nThis extension might create folders and files in your hardisk which might be declared as sensitive information, make sure you are creating projects under encrypted partition"
        return

    def initVulnerabilityTab(self):
        #
        ##  init vulnerability tab
        #

        nameLabel = JLabel("Vulnerability Name:")
        nameLabel.setBounds(10, 10, 140, 30)

        self.addButton = JButton("Add",actionPerformed=self.addVuln)
        self.addButton.setBounds(10, 500, 100, 30) 

        rmVulnButton = JButton("Remove",actionPerformed=self.rmVuln)
        rmVulnButton.setBounds(465, 500, 100, 30)

        mitigationLabel = JLabel("Mitigation:")
        mitigationLabel.setBounds(10, 290, 150, 30)
        
        addSSBtn = JButton("Add SS",actionPerformed=self.addSS)
        addSSBtn.setBounds(750, 40, 110, 30) 

        deleteSSBtn = JButton("Remove SS",actionPerformed=self.removeSS)
        deleteSSBtn.setBounds(750, 75, 110, 30) 

        piclistLabel = JLabel("Images list:")
        piclistLabel.setBounds(580, 10, 140, 30)

        self.screenshotsList = DefaultListModel()
        self.ssList = JList(self.screenshotsList)
        self.ssList.setBounds(580, 40, 150, 250)
        self.ssList.addListSelectionListener(ssChangedHandler(self))
        self.ssList.setBorder(BorderFactory.createLineBorder(Color.GRAY))

        previewPicLabel = JLabel("Selected image preview: (click to open in image viewer)")
        previewPicLabel.setBounds(580, 290, 500, 30)


        copyImgMenu = JMenuItem("Copy")
        copyImgMenu.addActionListener(copyImg(self))

        self.imgMenu = JPopupMenu("Popup")
        self.imgMenu.add(copyImgMenu)

        self.firstPic = JLabel()
        self.firstPic.setBorder(BorderFactory.createLineBorder(Color.GRAY))
        self.firstPic.setBounds(580, 320, 550, 400)
        self.firstPic.addMouseListener(imageClicked(self))

        self.vulnName = JTextField("")
        self.vulnName.getDocument().addDocumentListener(vulnTextChanged(self))
        self.vulnName.setBounds(140, 10, 422, 30)

        sevirities = ["Unclassified", "Critical","High","Medium","Low"]
        self.threatLevel = JComboBox(sevirities);
        self.threatLevel.setBounds(140, 45, 140, 30)

        colors = ["Color:", "Green", "Red"]
        self.colorCombo = JComboBox(colors);
        self.colorCombo.setBounds(465, 45, 100, 30)
        self.colorCombo

        severityLabel = JLabel("Threat Level:")
        severityLabel.setBounds(10, 45, 100, 30)

        descriptionLabel = JLabel("Description:")
        descriptionLabel.setBounds(10, 80, 100, 30)

        self.descriptionString = JTextArea("", 5, 30)
        self.descriptionString.setWrapStyleWord(True);
        self.descriptionString.setLineWrap(True)
        self.descriptionString.setBounds(10, 110, 555, 175)
        descriptionStringScroll = JScrollPane(self.descriptionString)
        descriptionStringScroll.setBounds(10, 110, 555, 175)
        descriptionStringScroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED)


        self.mitigationStr = JTextArea("", 5, 30)
        self.mitigationStr.setWrapStyleWord(True);
        self.mitigationStr.setLineWrap(True)
        self.mitigationStr.setBounds(10, 320, 555, 175)

        mitigationStrScroll = JScrollPane(self.mitigationStr)
        mitigationStrScroll.setBounds(10, 320, 555, 175)
        mitigationStrScroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED)

        self.pnl = JPanel()
        self.pnl.setBounds(0, 0, 1000, 1000);
        self.pnl.setLayout(None);
        self.pnl.add(addSSBtn)
        self.pnl.add(piclistLabel)
        self.pnl.add(nameLabel)
        self.pnl.add(deleteSSBtn)
        self.pnl.add(rmVulnButton)
        self.pnl.add(severityLabel)
        self.pnl.add(mitigationLabel)
        self.pnl.add(descriptionLabel)
        self.pnl.add(previewPicLabel)
        self.pnl.add(mitigationStrScroll)
        self.pnl.add(descriptionStringScroll)
        self.pnl.add(self.ssList)
        self.pnl.add(self.firstPic)
        self.pnl.add(self.addButton)
        self.pnl.add(self.vulnName)
        self.pnl.add(self.threatLevel)
        self.pnl.add(self.colorCombo)
        
    def initProjSettingsTab(self):
        # init project settings 
        
        projNameLabel = JLabel("Name:")
        projNameLabel.setBounds(10, 50, 140, 30)

        self.projName = JTextField("")
        self.projName.setBounds(140, 50, 320, 30)
        self.projName.getDocument().addDocumentListener(projTextChanged(self))

        detailsLabel = JLabel("Details:")
        detailsLabel.setBounds(10, 120, 140, 30)

        reportLabel = JLabel("Generate Report:")
        reportLabel.setBounds(10, 375, 140, 30)

        types = ["DOCX","HTML","XLSX"]
        self.reportType = JComboBox(types)
        self.reportType.setBounds(10, 400, 140, 30)

        generateReportButton = JButton("Generate", actionPerformed=self.generateReport)
        generateReportButton.setBounds(160, 400, 90, 30)


        self.projDetails = JTextArea("", 5, 30)
        self.projDetails.setWrapStyleWord(True);
        self.projDetails.setLineWrap(True)

        projDetailsScroll = JScrollPane(self.projDetails)
        projDetailsScroll.setBounds(10, 150, 450, 175)
        projDetailsScroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED)

        projPathLabel = JLabel("Path:")
        projPathLabel.setBounds(10, 90, 140, 30)

        self.projPath = JTextField("")
        self.projPath.setBounds(140, 90, 320, 30)

        chooseProjPathButton = JButton("Browse...",actionPerformed=self.chooseProjPath)
        chooseProjPathButton.setBounds(470, 90, 100, 30)
        
        importProjButton = JButton("Import",actionPerformed=self.importProj)
        importProjButton.setBounds(470, 10, 100, 30)

        exportProjButton = JButton("Export",actionPerformed=self.exportProj)
        exportProjButton.setBounds(575, 10, 100, 30)

        openProjButton = JButton("Open Directory",actionPerformed=self.openProj)
        openProjButton.setBounds(680, 10, 130, 30)

        currentProjectLabel = JLabel("Current:")
        currentProjectLabel.setBounds(10, 10, 140, 30)

        projects = self.config.options('projects')
        self.currentProject = JComboBox(projects)
        self.currentProject.addActionListener(projectChangeHandler(self))
        self.currentProject.setBounds(140, 10, 140, 30)

        self.autoSave = JCheckBox("Auto Save Mode")
        self.autoSave.setEnabled(False)  # implement this feature
        self.autoSave.setBounds(300, 10, 140, 30)
        self.autoSave.setToolTipText("Will save any changed value while focus is out")

        addProjButton = JButton("Add / Update",actionPerformed=self.addProj)
        addProjButton.setBounds(10, 330, 150, 30)

        removeProjButton = JButton("Remove Current",actionPerformed=self.rmProj)
        removeProjButton.setBounds(315, 330, 146, 30)

        generalOptions = self.config.options('general')
        if 'default project' in generalOptions:
            defaultProj = self.config.get('general','default project')
            self.currentProject.getModel().setSelectedItem(defaultProj)
            self.projPath.setText(self.config.get('projects',self.currentProject.getSelectedItem()))

        self.clearProjTab = True
        self.projectSettings = JPanel()
        self.projectSettings.setBounds(0, 0, 1000, 1000)
        self.projectSettings.setLayout(None)
        self.projectSettings.add(reportLabel)
        self.projectSettings.add(detailsLabel)
        self.projectSettings.add(projPathLabel)
        self.projectSettings.add(addProjButton)
        self.projectSettings.add(openProjButton)
        self.projectSettings.add(projNameLabel)
        self.projectSettings.add(projDetailsScroll)
        self.projectSettings.add(importProjButton)
        self.projectSettings.add(exportProjButton)
        self.projectSettings.add(removeProjButton)
        self.projectSettings.add(generateReportButton)
        self.projectSettings.add(chooseProjPathButton)
        self.projectSettings.add(currentProjectLabel)
        self.projectSettings.add(self.projPath)
        self.projectSettings.add(self.autoSave)
        self.projectSettings.add(self.projName)
        self.projectSettings.add(self.reportType)
        self.projectSettings.add(self.currentProject)

    def initTabs(self):
        #
        ##  init autorize tabs
        #
        
        self._splitpane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT)
        self.scrollPane = JScrollPane(self.logTable)
        self._splitpane.setLeftComponent(self.scrollPane)
        colorsMenu = JMenu("Paint")
        redMenu = JMenuItem("Red")
        noneMenu = JMenuItem("None")
        greenMenu = JMenuItem("Green")
        redMenu.addActionListener(paintChange(self, "Red"))
        noneMenu.addActionListener(paintChange(self, None))
        greenMenu.addActionListener(paintChange(self, "Green"))
        colorsMenu.add(redMenu)
        colorsMenu.add(noneMenu)
        colorsMenu.add(greenMenu)
        
        
        self.menu = JPopupMenu("Popup")
        self.menu.add(colorsMenu)

        self.tabs = JTabbedPane()
        
        self.tabs.addTab("Request", self._requestViewer.getComponent())
        self.tabs.addTab("Response", self._responseViewer.getComponent())

        self.tabs.addTab("Vulnerability", self.pnl)

        self.tabs.addTab("Project Settings", self.projectSettings)
        
        self.tabs.setSelectedIndex(2)
        self._splitpane.setRightComponent(self.tabs)

    def initCallbacks(self):
        #
        ##  init callbacks
        #

        # customize our UI components
        self._callbacks.customizeUiComponent(self._splitpane)
        self._callbacks.customizeUiComponent(self.logTable)
        self._callbacks.customizeUiComponent(self.scrollPane)
        self._callbacks.customizeUiComponent(self.tabs)
        self._callbacks.registerContextMenuFactory(self)
        # add the custom tab to Burp's UI
        self._callbacks.addSuiteTab(self)


    def loadVulnerabilities(self, projPath):
        self.clearList(None)
        selected = False
        for root, dirs, files in os.walk(projPath): # make it go only for dirs
            for dirName in dirs:
                xmlPath = projPath+"/"+dirName+"/vulnerability.xml"
                # xmlPath = xmlPath.replace("/","//")
                document = self.getXMLDoc(xmlPath)
                nodeList = document.getDocumentElement().getChildNodes()
                vulnName = nodeList.item(0).getTextContent()
                severity = nodeList.item(1).getTextContent()
                description = nodeList.item(2).getTextContent()
                mitigation = nodeList.item(3).getTextContent()
                color = nodeList.item(4).getTextContent()
                test = vulnerability(vulnName,severity,description,mitigation,color)
                self._lock.acquire()
                row = self._log.size()
                self._log.add(test)
                self.fireTableRowsInserted(row, row)
                self._lock.release()
                if vulnName == self.vulnName.getText():
                    self.logTable.setRowSelectionInterval(row,row)
                    selected = True
        if selected == False and self._log.size() > 0:
            self.logTable.setRowSelectionInterval(0, 0)
            self.loadVulnerability(self._log.get(0))
        
    def createSection(self, sectioName):
        self.config.read('config.ini')
        if not (sectioName in self.config.sections()):
            self.config.add_section(sectioName)
            cfgfile = open("config.ini",'w')
            self.config.write(cfgfile)
            cfgfile.close()

    def saveCfg(self):
        f = open('config.ini', 'w')
        self.config.write(f)
        f.close()

    def getXMLDoc(self, xmlPath):
        try:
            document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(xmlPath)
            return document
        except:
            self._extender.popup("XML file not found")
            return

    def saveXMLDoc(self, doc, xmlPath):
        transformerFactory = TransformerFactory.newInstance()
        transformer = transformerFactory.newTransformer()
        source = DOMSource(doc)
        result = StreamResult(File(xmlPath))
        transformer.transform(source, result)

    def generateReport(self,event):
        if self.reportType.getSelectedItem() == "HTML":
            path = self.reportToHTML()
        if self.reportType.getSelectedItem() == "XLSX":
            path = self.reportToXLS()
        if self.reportType.getSelectedItem() == "DOCX":
            path = self.generateReportFromDocxTemplate('template.docx',"newfile.docx", 'word/document.xml')
        n = JOptionPane.showConfirmDialog(None, "Report generated successfuly:\n%s\nWould you like to open it?" % (path), "PT Manager", JOptionPane.YES_NO_OPTION)
        if n == JOptionPane.YES_OPTION:
            os.system('"' + path + '"') # Bug! stucking burp until the file get closed

    def exportProj(self,event):
        self.chooser.setDialogTitle("Save project")
        Ffilter = FileNameExtensionFilter("Zip files", ["zip"])
        self.chooser.setFileFilter(Ffilter)
        returnVal = self.chooser.showSaveDialog(None)
        if returnVal == JFileChooser.APPROVE_OPTION:
            dst = str(self.chooser.getSelectedFile())
            shutil.make_archive(dst,"zip",self.getCurrentProjPath())
            self.popup("Project export successfuly")

    def importProj(self,event):
        self.chooser.setDialogTitle("Select project zip to directory")
        Ffilter = FileNameExtensionFilter("Zip files", ["zip"])
        self.chooser.setFileFilter(Ffilter)
        returnVal = self.chooser.showOpenDialog(None)
        if returnVal == JFileChooser.APPROVE_OPTION:
            zipPath = str(self.chooser.getSelectedFile())
            self.chooser.setDialogTitle("Select project directory")
            self.chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY)
            returnVal = self.chooser.showOpenDialog(None)
            if returnVal == JFileChooser.APPROVE_OPTION:
                projPath = str(self.chooser.getSelectedFile()) + "/PTManager"
                with zipfile.ZipFile(zipPath, "r") as z:
                    z.extractall(projPath)

                xmlPath = projPath + "/project.xml"
                document = self.getXMLDoc(xmlPath)
                nodeList = document.getDocumentElement().getChildNodes()
                projName = nodeList.item(0).getTextContent()
                nodeList.item(1).setTextContent(projPath)
                self.saveXMLDoc(document, xmlPath)
                self.config.set('projects', projName, projPath)
                self.saveCfg()
                self.reloadProjects()
                self.currentProject.getModel().setSelectedItem(projName)
                self.clearVulnerabilityTab() 

    def reportToXLS(self):
        if not xlsxwriterImported:
            self.popup("xlsxwriter library is not imported")
            return
        workbook = xlsxwriter.Workbook(self.getCurrentProjPath() + '/PT Manager Report.xlsx')
        worksheet = workbook.add_worksheet()
        bold = workbook.add_format({'bold': True})
        worksheet.write(0, 0, "Vulnerability Name", bold)
        worksheet.write(0, 1, "Threat Level", bold)
        worksheet.write(0, 2, "Description", bold)
        worksheet.write(0, 3, "Mitigation", bold)
        row = 1
        for i in range(0,self._log.size()):
            worksheet.write(row, 0, self._log.get(i).getName())
            worksheet.write(row, 1, self._log.get(i).getSeverity())
            worksheet.write(row, 2, self._log.get(i).getDescription())
            worksheet.write(row, 3, self._log.get(i).getMitigation())
            row = row + 1
            # add requests and images as well
        workbook.close()
        return self.getCurrentProjPath() + '/PT Manager Report.xlsx'
        
    def reportToHTML(self):
        htmlContent = """<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="he" dir="ltr">
    <head>
        <title>PT Manager Report</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <style>
        body {
        background-repeat: no-repeat;
        background-attachment: fixed;
        font-family: Arial,Tahoma,sens-serif;
        font-size: 13px;
        margin: auto;
        }

        #warpcenter {
            width: 900px;
            margin: 0px auto;
        }

        table {
            border: 2px dashed #000000;
        }

        td {
            border-top: 2px dashed #000000;
            padding: 10px;
        }

        img {
                border: 0px;
        }
</style>
<script language="javascript">
    function divHideShow(divToHideOrShow) 
    {
        var div = document.getElementById(divToHideOrShow);

        if (div.style.display == "block") 
        {
            div.style.display = "none";
        }
        else 
        {
            div.style.display = "block";
        }

        
    }         
</script>
    </head>

    <body>
        <div id="warpcenter">

<h1> PT Manager Report </h1>
<h2> Project: %s</h1>
    """ % (self.projName.getText())

        for i in range(0,self._log.size()):
            name = self._log.get(i).getName()
            request = "None"
            response = "None"
            path = self.getVulnReqResPath("request",name)
            if os.path.exists(path):
                request = self.newlineToBR(self.getFileContent(path))
                
            path = self.getVulnReqResPath("response",name)
            if os.path.exists(path):
                response = self.newlineToBR(self.getFileContent(path))
            images = ""
            for fileName in os.listdir(self.projPath.getText()+"/"+self.clearStr(name)):
                if fileName.endswith(".jpg"):
                    images += "%s<br><img src=\"%s\"><br><br>" % (fileName, self.projPath.getText()+"/"+self.clearStr(name) + "/" + fileName)
            description = self.newlineToBR(self._log.get(i).getDescription())
            mitigation = self.newlineToBR(self._log.get(i).getMitigation())
            htmlContent +=  self.convertVulntoTable(i,name,self._log.get(i).getSeverity(), description,mitigation, request, response, images)
        htmlContent += "</div></body></html>"
        f = open(self.getCurrentProjPath() + '/PT Manager Report.html', 'w')
        f.writelines(htmlContent)
        f.close()
        return self.getCurrentProjPath() + '/PT Manager Report.html'

    def newlineToBR(self,string):
        return "<br />".join(string.split("\n"))

    def getFileContent(self,path):
        f = open(path, "rb")
        content = f.read()
        f.close()
        return content

    def convertVulntoTable(self, number, name, severity, description, mitigation, request = "None", response = "None", images = "None"):
        return """<div style="width: 100%%;height: 30px;text-align: center;background-color:#E0E0E0;font-size: 17px;font-weight: bold;color: #000;padding-top: 10px;">%s <a href="javascript:divHideShow('Table_%s');" style="color:#191970">(OPEN / CLOSE)</a></div>
        <div id="Table_%s" style="display: none;">
            <table width="100%%" cellspacing="0" cellpadding="0" style="margin: 0px auto;text-align: left;border-top: 0px;">
                <tr>
                    <td>
                        <div style="font-size: 16px;font-weight: bold;">
                        <span style="color:#000000">Threat Level: </span> 
                        <span style="color:#8b8989">%s</span>
                                            </td>
                                        </tr>
                                        <tr>
                                            <td>
                        <div style="font-size: 16px;font-weight: bold;">
                        <span style="color:#000000">Description</span> 
                        <a href="javascript:divHideShow('Table_%s_Command_03');" style="color:#191970">OPEN / CLOSE >>></a>
                        </div>

                        <div id="Table_%s_Command_03" style="display: none;margin-top: 25px;">
                        %s
                        </div>
                                            </td>
                                        </tr>
                                        <tr>
                                            <td>
                        <div style="font-size: 16px;font-weight: bold;">
                        <span style="color:#000000">Mitigration</span> 
                        <a href="javascript:divHideShow('Table_%s_Command_04');" style="color:#191970">OPEN / CLOSE >>></a>
                        </div>

                        <div id="Table_%s_Command_04" style="display: none;margin-top: 25px;">
                        %s
                        <b>
                                            </td>
                                        </tr>

                                        <tr>
                                            <td>
                        <div style="font-size: 16px;font-weight: bold;">
                        <span style="color:#000000">Request</span> 
                        <a href="javascript:divHideShow('Table_%s_Command_05');" style="color:#191970">OPEN / CLOSE >>></a>
                        </div>

                        <div id="Table_%s_Command_05" style="display: none;margin-top: 25px;">
                        %s
                        <b>
                                            </td>
                                        </tr>


                                                        <tr>
                                            <td>
                        <div style="font-size: 16px;font-weight: bold;">
                        <span style="color:#000000">Response</span> 
                        <a href="javascript:divHideShow('Table_%s_Command_06');" style="color:#191970">OPEN / CLOSE >>></a>
                        </div>

                        <div id="Table_%s_Command_06" style="display: none;margin-top: 25px;">
                        %s
                        <b>
                                            </td>
                                        </tr>

                                                        <tr>
                                            <td>
                        <div style="font-size: 16px;font-weight: bold;">
                        <span style="color:#000000">Images</span> 
                        <a href="javascript:divHideShow('Table_%s_Command_07');" style="color:#191970">OPEN / CLOSE >>></a>
                        </div>

                        <div id="Table_%s_Command_07" style="display: none;margin-top: 25px;">
                        %s
                        <b>
                    </td>
                </tr>
            </table>
        </div><br><br>""" % (name,number,number,severity,number,number,description,number,number,mitigation,number,number,request,number,number,response,number,number,images)

    def clearVulnerabilityTab(self, rmVuln=True):
        if rmVuln:
            self.vulnName.setText("")
        self.descriptionString.setText("")
        self.mitigationStr.setText("")
        self.colorCombo.setSelectedIndex(0)
        self.threatLevel.setSelectedIndex(0)
        self.screenshotsList.clear()
        self.addButton.setText("Add")
        self.firstPic.setIcon(None)

    def saveRequestResponse(self, type, requestResponse, vulnName):
        path = self.getVulnReqResPath(type,vulnName)
        f = open(path, 'wb')
        f.write(requestResponse)
        f.close()

    def openProj(self, event):
        os.system('explorer ' + self.projPath.getText())

    def getVulnReqResPath(self, requestOrResponse, vulnName):
        return self.getCurrentProjPath() + "/" + self.clearStr(vulnName) + "/"+requestOrResponse+"_" + self.clearStr(vulnName)

    def htmlEscape(self,data):
        return data.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;').replace('"', '&quot;').replace("'", '&#39;')

    def generateReportFromDocxTemplate(self, zipname, newZipName, filename):      
        newZipName = self.getCurrentProjPath() + "/" + newZipName
        with zipfile.ZipFile(zipname, 'r') as zin:
            with zipfile.ZipFile(newZipName, 'w') as zout:
                zout.comment = zin.comment
                for item in zin.infolist():
                    if item.filename != filename:
                        zout.writestr(item, zin.read(item.filename))
                    else:
                        xml_content = zin.read(item.filename)
                        result = re.findall("(.*)<w:body>(?:.*)<\/w:body>(.*)",xml_content)[0]
                        newXML = result[0]
                        templateBody = re.findall("<w:body>(.*)<\/w:body>", xml_content)[0]
                        newBody = ""

                        for i in range(0,self._log.size()):
                            tmp = templateBody
                            tmp = tmp.replace("$vulnerability", self.htmlEscape(self._log.get(i).getName()))
                            tmp = tmp.replace("$severity", self.htmlEscape(self._log.get(i).getSeverity()))
                            tmp = tmp.replace("$description", self.htmlEscape(self._log.get(i).getDescription()))
                            tmp = tmp.replace("$mitigation", self.htmlEscape(self._log.get(i).getMitigation()))
                            newBody = newBody + tmp
                         
                        newXML = newXML + newBody
                        newXML = newXML + result[1]

        with zipfile.ZipFile(newZipName, mode='a', compression=zipfile.ZIP_DEFLATED) as zf:
            zf.writestr(filename, newXML)
        return newZipName


    def chooseProjPath(self, event):
        self.chooser.setDialogTitle("Select target directory")
        self.chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY)
        returnVal = self.chooser.showOpenDialog(None)
        if returnVal == JFileChooser.APPROVE_OPTION:
            projPath = str(self.chooser.getSelectedFile()) + "/PTManager"
            os.makedirs(projPath)
            self.projPath.setText(projPath)

    def reloadProjects(self):
        self.currentProject.setModel(DefaultComboBoxModel(self.config.options('projects')))

    def rmProj(self, event):
        if self.popUpAreYouSure() == JOptionPane.YES_OPTION:
            self._requestViewer.setMessage("None", False)
            self._responseViewer.setMessage("None", False)
            shutil.rmtree(self.projPath.getText())
            self.config.remove_option('projects',self.currentProject.getSelectedItem())
            self.reloadProjects()
            self.currentProject.setSelectedIndex(0)
            self.loadVulnerabilities(self.projPath.getText())

    def popup(self,msg):
        JOptionPane.showMessageDialog(None,msg)

    def addProj(self, event):
        projPath = self.projPath.getText()
        if projPath == None or projPath == "":
            self.popup("Please select path")
            return
        self.config.set('projects', self.projName.getText(), projPath)
        self.saveCfg()
        xml = ET.Element('project')
        name = ET.SubElement(xml, "name")
        path = ET.SubElement(xml, "path")
        details = ET.SubElement(xml, "details")
        autoSaveMode = ET.SubElement(xml, "autoSaveMode")

        name.text = self.projName.getText()
        path.text = projPath
        details.text = self.projDetails.getText()
        autoSaveMode.text = str(self.autoSave.isSelected())
        tree = ET.ElementTree(xml)
        try:
            tree.write(self.getCurrentProjPath()+'/project.xml')
        except:
            self.popup("Invalid path")
            return

        self.reloadProjects()
        self.clearVulnerabilityTab()
        self.clearList(None)
        self.currentProject.getModel().setSelectedItem(self.projName.getText())

    def resize(self, image, width, height):
        bi = BufferedImage(width, height, BufferedImage.TRANSLUCENT)
        g2d = bi.createGraphics()
        g2d.addRenderingHints(RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY))
        g2d.drawImage(image, 0, 0, width, height, None)
        g2d.dispose()
        return bi;

    def clearStr(self, var):
        return var.replace(" " , "_").replace("\\" , "").replace("/" , "").replace(":" , "").replace("*" , "").replace("?" , "").replace("\"" , "").replace("<" , "").replace(">" , "").replace("|" , "").replace("(" , "").replace(")" , "")

    def popUpAreYouSure(self):
        dialogResult = JOptionPane.showConfirmDialog(None,"Are you sure?","Warning",JOptionPane.YES_NO_OPTION)
        if dialogResult == 0:
            return 0
        return 1

    def removeSS(self,event):
        if self.popUpAreYouSure() == JOptionPane.YES_OPTION:
            os.remove(self.getCurrentVulnPath() + "/" + self.ssList.getSelectedValue())
            self.ssList.getModel().remove(self.ssList.getSelectedIndex())
            self.firstPic.setIcon(ImageIcon(None))
            # check if there is images and select the first one
            # bug in linux

    def addSS(self,event):
        clipboard = Toolkit.getDefaultToolkit().getSystemClipboard()
        try:
            image = clipboard.getData(DataFlavor.imageFlavor)
        except:
            self.popup("Clipboard not contains image")
            return
        vulnPath = self.projPath.getText() + "/" + self.clearStr(self.vulnName.getText())
        if not os.path.exists(vulnPath):
            os.makedirs(vulnPath)
        name = self.clearStr(self.vulnName.getText()) + str(random.randint(1, 99999))+".jpg"
        fileName = self.projPath.getText()+"/"+ self.clearStr(self.vulnName.getText()) + "/" + name
        file = File(fileName)
        bufferedImage = BufferedImage(image.getWidth(None), image.getHeight(None), BufferedImage.TYPE_INT_RGB);
        g = bufferedImage.createGraphics();
        g.drawImage(image, 0, 0, bufferedImage.getWidth(), bufferedImage.getHeight(), Color.WHITE, None);
        ImageIO.write(bufferedImage, "jpg", file)
        self.addVuln(self)
        self.ssList.setSelectedValue(name,True)

    def rmVuln(self, event):
        if self.popUpAreYouSure() == JOptionPane.YES_OPTION:
            self._requestViewer.setMessage("None", False)
            self._responseViewer.setMessage("None", False)
            shutil.rmtree(self.getCurrentVulnPath())
            self.clearVulnerabilityTab()
            self.loadVulnerabilities(self.getCurrentProjPath())

    def addVuln(self, event):
        if self.colorCombo.getSelectedItem() == "Color:":
            colorTxt = None
        else:
            colorTxt = self.colorCombo.getSelectedItem()
        self._lock.acquire()
        row = self._log.size()
        vulnObject = vulnerability(self.vulnName.getText(),self.threatLevel.getSelectedItem(),self.descriptionString.getText(),self.mitigationStr.getText() ,colorTxt)
        self._log.add(vulnObject) 
        self.fireTableRowsInserted(row, row)
        self._lock.release()

        vulnPath = self.projPath.getText() + "/" + self.clearStr(self.vulnName.getText())
        if not os.path.exists(vulnPath):
            os.makedirs(vulnPath)

        xml = ET.Element('vulnerability')
        name = ET.SubElement(xml, "name")
        severity = ET.SubElement(xml, "severity")
        description = ET.SubElement(xml, "description")
        mitigation = ET.SubElement(xml, "mitigation")
        color = ET.SubElement(xml, "color")
        name.text = self.vulnName.getText()
        severity.text = self.threatLevel.getSelectedItem()
        description.text = self.descriptionString.getText()
        mitigation.text = self.mitigationStr.getText()
        color.text = colorTxt
        tree = ET.ElementTree(xml)
        tree.write(vulnPath+'/vulnerability.xml')

        self.loadVulnerabilities(self.getCurrentProjPath())
        self.loadVulnerability(vulnObject)

    def vulnNameChanged(self):
            if os.path.exists(self.getCurrentVulnPath()) and self.vulnName.getText() != "":
                self.addButton.setText("Update")
            elif self.addButton.getText() != "Add":
                options = ["Create a new vulnerability", "Change current vulnerability name"]
                n = JOptionPane.showOptionDialog(None,
                    "Would you like to?",
                    "Vulnerability Name",
                    JOptionPane.YES_NO_CANCEL_OPTION,
                    JOptionPane.QUESTION_MESSAGE,
                    None,
                    options,
                    options[0]);

                if n == 0:
                    self.clearVulnerabilityTab(False)
                    self.addButton.setText("Add")
                else:
                    newName = JOptionPane.showInputDialog(
                    None,
                    "Enter new name:",
                    "Vulnerability Name",
                    JOptionPane.PLAIN_MESSAGE,
                    None,
                    None,
                    self.vulnName.getText())
                    row = self.logTable.getSelectedRow()
                    old = self.logTable.getValueAt(row,1)                   
                    self.changeVulnName(newName,old)
                
    def changeVulnName(self,new,old):
        newpath = self.getCurrentProjPath() + "/" + new
        oldpath = self.getCurrentProjPath() + "/" + old
        os.rename(oldpath,newpath)
        self.changeCurrentVuln(new,0, newpath + "/vulnerability.xml")

    def getCurrentVulnPath(self):
        return self.projPath.getText() + "/" + self.clearStr(self.vulnName.getText())

    def getCurrentProjPath(self):
        return self.projPath.getText()

    def loadSS(self, imgPath):
        image = ImageIO.read(File(imgPath))
        if image.getWidth() <= 550 and image.getHeight() <= 400:
            self.firstPic.setIcon(ImageIcon(image))
            self.firstPic.setSize(image.getWidth(),image.getHeight())
        else:
            self.firstPic.setIcon(ImageIcon(self.resize(image,550, 400)))
            self.firstPic.setSize(550,400)

    def clearProjectTab(self):
        self.projPath.setText("")
        self.projDetails.setText("")

    def clearList(self, event):
        self._lock.acquire()
        self._log = ArrayList()
        row = self._log.size()
        self.fireTableRowsInserted(row, row)
        self._lock.release()

    #
    # implement IContextMenuFactory
    #
    def createMenuItems(self, invocation):
        responses = invocation.getSelectedMessages();
        if responses > 0:
            ret = LinkedList()
            requestMenuItem = JMenuItem("Send to PT Manager");
            requestMenuItem.addActionListener(handleMenuItems(self,responses[0], "request"))
            ret.add(requestMenuItem);
            return(ret);
        return null;
    #
    # implement ITab
    #
    def getTabCaption(self):
        return "PT Manager"
    
    def getUiComponent(self):
        return self._splitpane

        #
    # extend AbstractTableModel
    #
    
    def getRowCount(self):
        try:
            return self._log.size()
        except:
            return 0

    def getColumnCount(self):
        return 3

    def getColumnName(self, columnIndex):
        if columnIndex == 0:
            return "#"
        if columnIndex == 1:
            return "Vulnerability Name"
        if columnIndex == 2:
            return "Threat Level"
        return ""

    def getValueAt(self, rowIndex, columnIndex):
        vulnObject = self._log.get(rowIndex)
        if columnIndex == 0:
            return rowIndex+1
        if columnIndex == 1:
            return vulnObject.getName()
        if columnIndex == 2:
            return vulnObject.getSeverity()
        if columnIndex == 3:
            return vulnObject.getMitigation()
        if columnIndex == 4:
            return vulnObject.getColor()

        return ""

    def changeCurrentVuln(self,value,fieldNumber, xmlPath = "def"):
        if xmlPath == "def":
            xmlPath = self.getCurrentVulnPath() + "/vulnerability.xml"
        document = self.getXMLDoc(xmlPath)
        nodeList = document.getDocumentElement().getChildNodes()
        nodeList.item(fieldNumber).setTextContent(value)
        self.saveXMLDoc(document, xmlPath)
        self.loadVulnerabilities(self.getCurrentProjPath())

    def loadVulnerability(self, vulnObject):
        self.addButton.setText("Update")
        self.vulnName.setText(vulnObject.getName())
        self.threatLevel.setSelectedItem(vulnObject.getSeverity())
        self.descriptionString.setText(vulnObject.getDescription())
        self.mitigationStr.setText(vulnObject.getMitigation())

        if vulnObject.getColor() == "" or vulnObject.getColor() == None:
            self.colorCombo.setSelectedItem("Color:")
        else:
            self.colorCombo.setSelectedItem(vulnObject.getColor())
        self.screenshotsList.clear()

        for fileName in os.listdir(self.projPath.getText()+"/"+self.clearStr(vulnObject.getName())):
            if fileName.endswith(".jpg"):
                self.screenshotsList.addElement(fileName)
                imgPath = self.projPath.getText()+"/"+self.clearStr(vulnObject.getName())+'/'+fileName
                # imgPath = imgPath.replace("/","//")
                self.loadSS(imgPath)

        if (self.screenshotsList.getSize() == 0):
            self.firstPic.setIcon(None)
        else:
            self.ssList.setSelectedIndex(0)

        path = self.getVulnReqResPath("request",vulnObject.getName())
        if os.path.exists(path):
            f = self.getFileContent(path)
            self._requestViewer.setMessage(f, False)
        else:
            self._requestViewer.setMessage("None", False)
        
        path = self.getVulnReqResPath("response",vulnObject.getName())
        if os.path.exists(path):
            f = self.getFileContent(path)
            self._responseViewer.setMessage(f, False)
        else:
            self._responseViewer.setMessage("None", False)
Example #41
0
    def registerExtenderCallbacks(self, callbacks):
        # smart xss feature (print conclusion and observation)
        # mark resulsts
        # add automatic check pages in the same domain

        self.tagPayloads = [
            "<b>test", "<b onmouseover=test()>test",
            "<img src=err onerror=test()>", "<script>test</script>"
            "", "<scr ipt>test</scr ipt>", "<SCRIPT>test;</SCRIPT>",
            "<scri<script>pt>test;</scr</script>ipt>",
            "<SCRI<script>PT>test;</SCR</script>IPT>",
            "<scri<scr<script>ipt>pt>test;</scr</sc</script>ript>ipt>",
            "<IMG \"\"\"><SCRIPT>test</SCRIPT>\">",
            "<IMG '''><SCRIPT>test</SCRIPT>'>", "<SCR%00IPT>test</SCR%00IPT>",
            "<IFRAME SRC='f' onerror=\"test\"></IFRAME>",
            "<IFRAME SRC='f' onerror='test'></IFRAME>",
            "<<SCRIPT>test//<</SCRIPT>", "<img src=\"1\" onerror=\"test\">",
            "<img src='1' onerror='test'",
            "<STYLE TYPE=\"text/javascript\">test;</STYLE>",
            "<<SCRIPT>test//<</SCRIPT>"
        ]
        self.attributePayloads = [
            "\"\"\"><SCRIPT>test", "'''><SCRIPT>test'",
            "\"><script>test</script>", "\"><script>test</script><\"",
            "'><script>test</script>", "'><script>test</script><'",
            "\";test;\"", "';test;'", ";test;", "\";test;//",
            "\"onmouseover=test ", "onerror=\"test\"", "onerror='test'",
            "onload=\"test\"", "onload='test'"
        ]
        self.xssKey = 'xssme'
        # 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("XSSor")

        self.affectedResponses = ArrayList()
        self._log = ArrayList()
        self._lock = Lock()

        # main split pane
        self._splitpane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT)

        # table of log entries
        logTable = Table(self)
        scrollPane = JScrollPane(logTable)
        self._splitpane.setLeftComponent(scrollPane)

        # tabs with request/response viewers
        tabs = JTabbedPane()
        self._requestViewer = callbacks.createMessageEditor(self, False)
        self._responseViewer = callbacks.createMessageEditor(self, False)
        tabs.addTab("Request", self._requestViewer.getComponent())
        tabs.addTab("Response", self._responseViewer.getComponent())

        clearAPListBtn = JButton("Clear List",
                                 actionPerformed=self.clearAPList)
        clearAPListBtn.setBounds(10, 85, 120, 30)
        apListLabel = JLabel('Affected Pages List:')
        apListLabel.setBounds(10, 10, 140, 30)
        self.affectedModel = DefaultListModel()
        self.affectedList = JList(self.affectedModel)
        self.affectedList.addListSelectionListener(listSelectedChange(self))
        scrollAList = JScrollPane(self.affectedList)
        scrollAList.setVerticalScrollBarPolicy(
            JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED)
        scrollAList.setBounds(150, 10, 550, 200)
        scrollAList.setBorder(LineBorder(Color.BLACK))

        APtabs = JTabbedPane()
        self._requestAPViewer = callbacks.createMessageEditor(self, False)
        self._responseAPViewer = callbacks.createMessageEditor(self, False)
        APtabs.addTab("Request", self._requestAPViewer.getComponent())
        APtabs.addTab("Affeced Page Response",
                      self._responseAPViewer.getComponent())
        APtabs.setBounds(0, 250, 700, 350)
        APtabs.setSelectedIndex(1)

        self.APpnl = JPanel()
        self.APpnl.setBounds(0, 0, 1000, 1000)
        self.APpnl.setLayout(None)
        self.APpnl.add(scrollAList)
        self.APpnl.add(clearAPListBtn)
        self.APpnl.add(APtabs)
        self.APpnl.add(apListLabel)
        tabs.addTab("Affected Pages", self.APpnl)
        self.intercept = 0

        ## init conf panel
        startLabel = JLabel("Plugin status:")
        startLabel.setBounds(10, 10, 140, 30)

        payloadLabel = JLabel("Basic Payload:")
        payloadLabel.setBounds(10, 50, 140, 30)

        self.basicPayload = "<script>alert(1)</script>"
        self.basicPayloadTxt = JTextArea(self.basicPayload, 5, 30)
        self.basicPayloadTxt.setBounds(120, 50, 305, 30)

        self.bruteForceMode = JCheckBox("Brute Force Mode")
        self.bruteForceMode.setBounds(120, 80, 300, 30)
        self.bruteForceMode.addItemListener(handleBFModeChange(self))

        self.tagPayloadsCheck = JCheckBox("Tag paylods")
        self.tagPayloadsCheck.setBounds(120, 100, 300, 30)
        self.tagPayloadsCheck.setSelected(True)
        self.tagPayloadsCheck.setEnabled(False)
        self.tagPayloadsCheck.addItemListener(handleBFModeList(self))

        self.attributePayloadsCheck = JCheckBox("Attribute payloads")
        self.attributePayloadsCheck.setBounds(260, 100, 300, 30)
        self.attributePayloadsCheck.setSelected(True)
        self.attributePayloadsCheck.setEnabled(False)
        self.attributePayloadsCheck.addItemListener(handleBFModeList(self))

        payloadListLabel = JLabel("Payloads list (for BF mode):")
        payloadListLabel.setBounds(10, 130, 140, 30)

        self.payloadsModel = DefaultListModel()
        self.payloadsList = JList(self.payloadsModel)
        scrollPayloadsList = JScrollPane(self.payloadsList)
        scrollPayloadsList.setVerticalScrollBarPolicy(
            JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED)
        scrollPayloadsList.setBounds(120, 170, 300, 200)
        scrollPayloadsList.setBorder(LineBorder(
            Color.BLACK))  # add buttons to remove payloads and add

        for payload in self.tagPayloads:
            self.payloadsModel.addElement(payload)

        for payload in self.attributePayloads:
            self.payloadsModel.addElement(payload)

        self.startButton = JButton("XSSor is off",
                                   actionPerformed=self.startOrStop)
        self.startButton.setBounds(120, 10, 120, 30)
        self.startButton.setBackground(Color(255, 100, 91, 255))

        consoleTab = JTabbedPane()
        self.consoleLog = JTextArea("", 5, 30)
        scrollLog = JScrollPane(self.consoleLog)
        scrollLog.setVerticalScrollBarPolicy(
            JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED)
        scrollLog.setBounds(120, 170, 550, 200)
        scrollLog.setBorder(LineBorder(Color.BLACK))
        scrollLog.getVerticalScrollBar().addAdjustmentListener(
            autoScrollListener(self))
        consoleTab.addTab("Console", scrollLog)
        consoleTab.setBounds(0, 400, 500, 200)

        self.pnl = JPanel()
        self.pnl.setBounds(0, 0, 1000, 1000)
        self.pnl.setLayout(None)
        self.pnl.add(self.startButton)
        self.pnl.add(startLabel)
        self.pnl.add(payloadLabel)
        self.pnl.add(self.basicPayloadTxt)
        self.pnl.add(self.bruteForceMode)
        self.pnl.add(payloadListLabel)
        self.pnl.add(scrollPayloadsList)
        self.pnl.add(self.attributePayloadsCheck)
        self.pnl.add(self.tagPayloadsCheck)
        self.pnl.add(consoleTab)

        tabs.addTab("Configuration", self.pnl)
        tabs.setSelectedIndex(3)
        self._splitpane.setRightComponent(tabs)

        # customize our UI components
        callbacks.customizeUiComponent(self._splitpane)
        callbacks.customizeUiComponent(logTable)
        callbacks.customizeUiComponent(scrollPane)
        callbacks.customizeUiComponent(tabs)

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

        # register ourselves as an HTTP listener
        callbacks.registerHttpListener(self)
        self._callbacks.registerContextMenuFactory(self)

        print "Thank you for installing XSSor v0.1 extension"
        print "Created by Barak Tawily"
        print "\nGithub:\nhttps://github.com/Quitten/XSSor"
        return
Example #42
0
 def run( self ) :
     #-----------------------------------------------------------------------
     # Size the frame to use 1/2 of the screen
     #-----------------------------------------------------------------------
     screenSize = Toolkit.getDefaultToolkit().getScreenSize()
     frameSize  = Dimension( screenSize.width >> 1, screenSize.height >> 1 )
     frame = JFrame(
         'javadocInfo_10',
         size = frameSize,
         defaultCloseOperation = JFrame.EXIT_ON_CLOSE
     )
     #-----------------------------------------------------------------------
     # Reposition the frame to be in the center of the screen
     #-----------------------------------------------------------------------
     frame.setLocation(
         ( screenSize.width  - frameSize.width  ) >> 1,
         ( screenSize.height - frameSize.height ) >> 1
     )
     #-----------------------------------------------------------------------
     # Initialize the list to have exactly 1 element
     #-----------------------------------------------------------------------
     model = DefaultListModel()
     model.addElement( 'One moment please...' )
     self.List = JList(
         model,
         valueChanged  = self.pick,
         selectionMode = ListSelectionModel.SINGLE_SELECTION
     )
     #-----------------------------------------------------------------------
     # Put the List in a ScrollPane and place it in the middle of a pane
     #-----------------------------------------------------------------------
     pane = JPanel( layout = BorderLayout() )
     pane.add(
         JScrollPane(
             self.List,
             minimumSize = ( 300, 50 )
         ),
         BorderLayout.CENTER
     )
     #-----------------------------------------------------------------------
     # Add a TextField [for the URL of the selected entry] at the bottom
     #-----------------------------------------------------------------------
     self.text = JTextField(
         'Enter text...',
         caretUpdate = self.caretUpdate
     )
     pane.add( self.text, BorderLayout.SOUTH )
     #-----------------------------------------------------------------------
     # Add the pane and a scrollable TextArea to a SplitPane in the frame
     #-----------------------------------------------------------------------
     self.area = JEditorPane(
         'text/html',
         '<html><h3>Nothing selected</h3></html>',
         editable = 0
     )
     self.splitPane = JSplitPane(
         JSplitPane.HORIZONTAL_SPLIT,
         pane,
         self.area
     )
     self.splitPane.setDividerLocation( 234 )
     frame.add( self.splitPane )
     #-----------------------------------------------------------------------
     # Create a separate thread to locate & proces the remote URL
     #-----------------------------------------------------------------------
     self.Links   = {}    # Initialize the Links dictionary
     self.classes = None  # complete list of all classes found
     soupTask(
         self.List,       # The visible JList instance
         self.text,       # User input field
         JAVADOC_URL,     # Remote web page URL to be processed
         self.Links,      # Dictionary of links found
     ).execute()
     frame.setVisible( 1 )
class BurpExtender(IBurpExtender, IContextMenuFactory, ActionListener, IMessageEditorController, ITab, ITextEditor, IHttpService, IScanIssue, IHttpRequestResponseWithMarkers):

    def __init__(self):
        self.menuItem = JMenuItem('Generate Finding')
        self.menuItem.addActionListener(self)   

    # implement IBurpExtender
    def registerExtenderCallbacks(self, callbacks):
    
        # keep a reference to our callbacks object (Burp Extensibility Feature)
        self._callbacks = callbacks   
        self._helpers = callbacks.getHelpers()

        # set our extension name
        callbacks.setExtensionName("Generate Finding")
        callbacks.registerContextMenuFactory(self)

        # -- Request Response Viewers -- #

        # create the lower half for the Request Response tabs...
        # Request and response from selection
        self._tabbedPane = JTabbedPane()
        tabs = self._tabbedPane
        self._requestViewer = callbacks.createMessageEditor(self, True)
        self._responseViewer = callbacks.createMessageEditor(self, True)
        self._requestHighlight = callbacks.createTextEditor()
        self._responseHighlight = callbacks.createTextEditor()
        tabs.addTab("Supporting Request", self._requestViewer.getComponent())
        tabs.addTab("Supporting Response", self._responseViewer.getComponent())
        tabs.addTab("Request Marker Selection", self._requestHighlight.getComponent())
        tabs.addTab("Response Marker Selection", self._responseHighlight.getComponent())
        #self._mainFrame.setRightComponent(tabs) # set to the lower split pane
        print "*" * 60
        print "[+] Request/Response tabs created"
    

        # -- Define Issue Details GUI & Layout-- #

        # Labels and Input boxes...
        # Issue Name
        self.issueNameLabel = JLabel(" Issue Name:")
        self.issueNameValue = JTextArea(text = str(issueNamePlaceholder), 
                         editable = True,
                         wrapStyleWord = True,
                         lineWrap = True,
                         alignmentX = Component.LEFT_ALIGNMENT,
                         size = (1, 20)
                         )

        # Issue Detail
        self.issueDetailLabel = JLabel(" Issue Detail:")

        #self.issueDetailValue = JTextField(str(issueDetailPlaceholder), 15)
        self.issueDetailValue = JTextArea(text = str(issueDetailPlaceholder), 
                         editable = True,
                         wrapStyleWord = True,
                         lineWrap = True,
                         alignmentX = Component.LEFT_ALIGNMENT,
                         size = (100, 20)
                         )

        # IssueBackground
        self.issueBackgroundLabel = JLabel(" Issue Background:")
        self.issueBackgroundValue = JTextArea(text = str(issueBackgroundPlaceholder), 
                         editable = True,
                         wrapStyleWord = True,
                         lineWrap = True,
                         alignmentX = Component.LEFT_ALIGNMENT,
                         size = (100, 20)
                         )

        # Remediation Detail
        self.issueRemediationLabel = JLabel(" Remediation Detail:")
        self.issueRemediationValue = JTextArea(text = str(remediationDetailPlaceholder), 
                         editable = True,
                         wrapStyleWord = True,
                         lineWrap = True,
                         alignmentX = Component.LEFT_ALIGNMENT,
                         size = (100, 20)
                         )
 
         # Remediation Background
        self.issueRemBackgroundLabel = JLabel(" Remediation Background:")
        self.issueRemBackgroundValue = JTextArea(text = str(remediationBackgroundPlaceholder), 
                         editable = True,
                         wrapStyleWord = True,
                         lineWrap = True,
                         alignmentX = Component.LEFT_ALIGNMENT,
                         size = (100, 20)
                         )  

        # Issue URL
        self.issueURLLabel = JLabel(" URL (path = http://domain/path):")
        self.issueURLValue = JTextArea(text = str(issueURLPlaceholder), 
                         editable = True,
                         wrapStyleWord = True,
                         lineWrap = True,
                         alignmentX = Component.LEFT_ALIGNMENT,
                         size = (1, 20)
                         )                       

        # Issue Port
        self.issuePortLabel = JLabel(" Port:")
        self.issuePortValue = JTextArea(text = str(issuePortPlaceholder), 
                         editable = True,
                         wrapStyleWord = True,
                         lineWrap = True,
                         alignmentX = Component.LEFT_ALIGNMENT,
                         size = (1, 20)
                         )

        # Confidence
        self.confidenceValuesList = ("Certain","Firm","Tentative")
        self.issueConfienceLabel = JLabel(" Confidence [Certain, Firm or Tentative]")
        self.issueConfidenceValue = JComboBox(self.confidenceValuesList)

        # Severity
        self.severityValuesList = ("High","Medium","Low","Information")
        self.issueSeverityLabel = JLabel(" Severity [High, Medium Low or Informational]")
        self.issueSeverityValue = JComboBox(self.severityValuesList)

        # Add Finding button

        self.addFindingButton = JButton("Generate Finding", actionPerformed=self.createScanIssue, alignmentX=Component.CENTER_ALIGNMENT) 


        # -- Group items for display -- #         

        # Group items 
        self.grpIssueSummary = JPanel(GridLayout(0,1))
        self.grpIssueSummary.add(self.issueNameLabel)
        self.grpIssueSummary.add(self.issueNameValue)
        self.grpIssueSummary.add(self.issueDetailLabel)
        self.grpIssueSummary.add(self.issueDetailValue)
        self.grpIssueSummary.add(self.issueBackgroundLabel)
        self.grpIssueSummary.add(self.issueBackgroundValue)
        self.grpIssueSummary.add(self.issueRemediationLabel)
        self.grpIssueSummary.add(self.issueRemediationValue)
        self.grpIssueSummary.add(self.issueRemBackgroundLabel)
        self.grpIssueSummary.add(self.issueRemBackgroundValue)
        self.grpIssueSummary.add(self.issueURLLabel)
        self.grpIssueSummary.add(self.issueURLValue)
        self.grpIssueSummary.add(self.issuePortLabel)
        self.grpIssueSummary.add(self.issuePortValue)
        self.grpIssueSummary.add(self.issueURLLabel)
        self.grpIssueSummary.add(self.issueURLValue)
        self.grpIssueSummary.add(self.issuePortLabel)
        self.grpIssueSummary.add(self.issuePortValue)

        self.grpRatingBoxes = JPanel()
        self.grpRatingBoxes.add(self.issueSeverityLabel)
        self.grpRatingBoxes.add(self.issueSeverityValue)
        self.grpRatingBoxes.add(self.issueConfienceLabel)
        self.grpRatingBoxes.add(self.issueConfidenceValue)
        self.grpRatingBoxes.add(self.addFindingButton)


        # add grps to details frame
        self._detailsPanel = JPanel(GridLayout(0,1))
        self._detailsPanel.add(self.grpIssueSummary)
        self._detailsPanel.add(self.grpRatingBoxes)


        self._findingDetailsPane = JScrollPane(self._detailsPanel)
        # create the main frame to hold details
        self._detailsViewer = self._findingDetailsPane # creates a form for details
        #tabs.addTab("Finding Details", self._detailsViewer)

        self._mainFrame = JSplitPane(JSplitPane.VERTICAL_SPLIT, self._detailsViewer, tabs)
        self._mainFrame.setOneTouchExpandable(True);
        self._mainFrame.setDividerLocation(0.5)
        self._mainFrame.setResizeWeight(0.50)

        print "[+] Finding details panel created"
        print "[+] Rendering..."

        # customize our UI components
        callbacks.customizeUiComponent(self._mainFrame)
        callbacks.customizeUiComponent(self._tabbedPane)
        callbacks.customizeUiComponent(self._detailsPanel)
        callbacks.customizeUiComponent(tabs)
        
        # add the custom tab to Burp's UI
        callbacks.addSuiteTab(self)
        print "[+] Done"
        print "[!] Added suite tab initialize complete!"

        return



    def getTabCaption(self):
        return "Generate Finding" 



    def getUiComponent(self):
        return self._mainFrame



    # initiaizes when button is clicked in 'Generate Finding Tab'
    def createScanIssue(self, event):

        print "[!] Finding Detail: "

        print "\t[+] Name:\n\t\t", self.issueNameValue.getText().strip()
        name = self.issueNameValue.getText()
        print "\t[+] Description:\n\t\t", self.issueDetailValue.getText().strip()
        description = self.issueDetailValue.getText()
        print "\t[+] Background:\n\t\t", self.issueBackgroundValue.getText().strip()
        background = self.issueBackgroundValue.getText()
        print "\t[+] Remediation:\n\t\t", self.issueRemediationValue.getText().strip()
        remediation = self.issueRemediationValue.getText()
        print "\t[+] Remediation Background:\n\t\t", self.issueRemBackgroundValue.getText().strip()
        remBackground = self.issueRemBackgroundValue.getText()
        print "\t[+] URL Detail:\n\t\t", self.issueURLValue.getText()
        urlDetail = self.issueURLValue.getText()
        print "\t[+] Port Number:\n\t\t", self.issuePortValue.getText()
        portNumber = self.issuePortValue.getText()
        print "\t[+] Confidence Rating:\n\t\t", self.issueConfidenceValue.getSelectedItem()
        confidenceRating = self.issueConfidenceValue.getSelectedItem()
        print "\t[+] Severity Rating:\n\t\t", self.issueSeverityValue.getSelectedItem()
        severityRating = self.issueSeverityValue.getSelectedItem()
        #print "\t[+] Payload Markers:\n\t\t", self.getSelectionBounds()

        # get highlighted data from request/response tabs in 'Generate Finding'
        #print "[!] Request Selected data:", self._requestViewer.getSelectedData()
        #highRequest = self._requestViewer.getSelectedData()
        #print "converted:", self._helpers.bytesToString(highRequest) 
        #print "[!] Response Selected data:", self._responseViewer.getSelectedData()
        #highResponse = self._responseViewer.getSelectedData()
        #print "converted:", self._helpers.bytesToString(highResponse) 

        # current message is used - should work as long as menu item 'Generate Finding' is not reset or used before finding has been generated.
        requestResponse = self.current_message

        print "\t[+] RequestResponse:\n\t\t", requestResponse
        print "\t[+] Service:\n\t\t", requestResponse.getHttpService()        


        # Collect request and Response Markers...
        #print "[**] Request Bounds: ", self._requestHighlight.getSelectionBounds() 
        requestBounds = self._requestHighlight.getSelectionBounds()
        #print "[**] Response Bounds: ", self._responseHighlight.getSelectionBounds() 
        responseBounds = self._responseHighlight.getSelectionBounds()

        # applyMarkers to request/response
        # callbacks.applyMarkers(requestResponse, None, [array('i', (data[1], data[2]))])
        self.reqMarkers = [requestBounds[0],requestBounds[1]]
        print "\t[+] Request Reporting Markers:\n\t\t", self.reqMarkers
        self.resMarkers = [responseBounds[0],responseBounds[1]]
        print "\t[+] Response Reporting Markers:\n\t\t", self.resMarkers

        print "*" * 60
        print "[!] Attempting to create custom scan issue."
        # Call AddScanItem class to create scan issue!!
        finding_array = [urlDetail, name, 134217728, severityRating, confidenceRating, background, remBackground, description, remediation, requestResponse]

        issue = ScanIssue(self, finding_array, self.current_message, self.reqMarkers, self.resMarkers, self._helpers, self._callbacks)
        self._callbacks.addScanIssue(issue)

        # Done
        print "[+] Finding Generated!"


    def getRequestResponseText(self):

        messages = self.ctxMenuInvocation.getSelectedMessages()

        # parses currently selected finding to a string
        if len(messages) == 1 :

            for self.m in messages:

                requestResponse = self.m
                # add requestResponseWithMarkers to be global so can be included in scanIssue
                self.current_message = requestResponse

                # get request data and convert to string
                requestDetail = requestResponse.getRequest()  
                try: 
                    requestData = self._helpers.bytesToString(requestDetail) # converts & Prints out the entire request as string     
                except:
                    requestData = '[-] No Request Detail in this RequestResponse'
                    pass
                # get response data and convert to string
                responseDetail = requestResponse.getResponse()
                try:
                    responseData = self._helpers.bytesToString(responseDetail) # converts & Prints out the entire request as string 
                except:
                    responseData = '[-] No Response Detail in this RequestResponse' 
                    pass 
                requestData = self._helpers.bytesToString(requestDetail) # converts & Prints out the entire request as string     


            # send request string to 'Supporting Request' tab - 'True' because it is a request!
            self._requestViewer.setMessage(requestData, True)
            # for higlighting markers..
            self._requestHighlight.setText(requestData)

            # send response string to 'Supporting Response' tab
            self._responseViewer.setMessage(responseData, False) # set False as is a response not request... 
            # for higlighting markers..
            self._responseHighlight.setText(responseData)
           


    def getFindingDetails(self):

            messages = self.ctxMenuInvocation.getSelectedMessages()

            print "*" * 60
            print "[+] Handling selected request: ", self.current_message

            if len(messages) == 1:
                for m in messages:           

                    # URL
                    #print "[!] Selected Request's URL: \n", self._helpers.analyzeRequest(m).getUrl()
                    self.issueURLValue.setText(str(self._helpers.analyzeRequest(m).getUrl())) # update finding info

                    # Protocol
                    #print "[!] Request's Protocol: \n", m.getProtocol()

                    # Request Port
                    #print "[!] Request's Port: \n", m.getPort()
                    self.issuePortValue.setText(str(m.getPort())) # update finding info
                    print "*" * 60


# API hook...

    def getHttpMessages(self):

        return [self.m]


# Actions on menu click...

    def actionPerformed(self, actionEvent):
        print "*" * 60
        print "[+] Request sent to 'Generate Finding'"
        try:
            # When clicked!! 
            self.getRequestResponseText()
            self.getFindingDetails()
        except:
            tb = traceback.format_exc()
            print tb


# create Menu

    def createMenuItems(self, ctxMenuInvocation):
        self.ctxMenuInvocation = ctxMenuInvocation
        return [self.menuItem]
Example #44
0
class View:
    def __init__(self):
        self.data = Data()
        self.checklist = self.data.get_checklist()
        self.issues = self.data.get_issues()

        self.set_checklist_tree()
        self.set_tree()
        self.set_pane()
        self.set_tabbed_panes()
        self.set_settings()

        self.set_tsl()

    def set_checklist(self, file_name):
        self.data.set_checklist(file_name)
        self.checklist = self.data.get_checklist()

    def get_checklist(self):
        return self.checklist

    def get_issues(self):
        return self.issues

    # TODO: Create the checklist dynamically for all nodes based on JSON structure
    # Creates a DefaultMutableTreeNode using the JSON file data
    def set_checklist_tree(self):
        self.checklist_tree = DefaultMutableTreeNode("HUNT - Methodology")

        for item in self.checklist:
            node = DefaultMutableTreeNode(item)
            self.checklist_tree.add(node)

            is_functionality = node.toString() == "Functionality"

            if is_functionality:
                functionality_node = node

        functionality = self.checklist["Functionality"]

        # TODO: Sort the functionality by name and by test name
        for functionality_name in functionality:
            tests = functionality[functionality_name]["tests"]
            node = DefaultMutableTreeNode(functionality_name)

            for test_name in tests:
                node.add(DefaultMutableTreeNode(test_name))

            functionality_node.add(node)

    def get_checklist_tree(self):
        return self.checklist_tree

    # Creates a JTree object from the checklist
    def set_tree(self):
        self.tree = JTree(self.checklist_tree)
        self.tree.getSelectionModel().setSelectionMode(
            TreeSelectionModel.SINGLE_TREE_SELECTION)

    def get_tree(self):
        return self.tree

    # TODO: Change to briefcase icon for brief, P1-P5 icons for vulns,
    #       bullseye icon for Targets, etc
    # Create a JSplitPlane with a JTree to the left and JTabbedPane to right
    def set_pane(self):
        status = JTextArea()
        status.setLineWrap(True)
        status.setText("Nothing selected")
        self.status = status

        self.pane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
                               JScrollPane(self.tree), JTabbedPane())

        self.pane.setDividerLocation(310)
        self.pane.getLeftComponent().setMinimumSize(Dimension(310, 300))

    def get_pane(self):
        return self.pane

    # Creates the tabs dynamically using data from the JSON file
    def set_tabbed_panes(self):
        functionality = self.checklist["Functionality"]
        self.tabbed_panes = {}

        for functionality_name in functionality:
            tests = functionality[functionality_name]["tests"]

            for test_name in tests:
                key = functionality_name + "." + test_name
                tabbed_pane = self.set_tabbed_pane(functionality_name,
                                                   test_name)
                self.tabbed_panes[key] = self.tabbed_pane

    def get_tabbed_panes(self):
        return self.tabbed_panes

    # Creates a JTabbedPane for each vulnerability per functionality
    def set_tabbed_pane(self, functionality_name, test_name):
        description_tab = self.set_description_tab(functionality_name,
                                                   test_name)
        bugs_tab = self.set_bugs_tab()
        resources_tab = self.set_resource_tab(functionality_name, test_name)
        notes_tab = self.set_notes_tab()

        self.tabbed_pane = JTabbedPane()
        self.tabbed_pane.add("Description", description_tab)
        self.tabbed_pane.add("Bugs", bugs_tab)
        self.tabbed_pane.add("Resources", resources_tab)
        self.tabbed_pane.add("Notes", notes_tab)

    # Creates the description panel
    def set_description_tab(self, fn, vn):
        description_text = str(
            self.checklist["Functionality"][fn]["tests"][vn]["description"])
        description_textarea = JTextArea()
        description_textarea.setLineWrap(True)
        description_textarea.setText(description_text)
        description_panel = JScrollPane(description_textarea)

        return description_panel

    # TODO: Add functionality to remove tabs
    # Creates the bugs panel
    def set_bugs_tab(self):
        bugs_tab = JTabbedPane()

        return bugs_tab

    # Creates the resources panel
    def set_resource_tab(self, fn, vn):
        resource_urls = self.checklist["Functionality"][fn]["tests"][vn][
            "resources"]
        resource_text = ""

        for url in resource_urls:
            resource_text = resource_text + str(url) + "\n"

        resource_textarea = JTextArea()
        resource_textarea.setLineWrap(True)
        resource_textarea.setWrapStyleWord(True)
        resource_textarea.setText(resource_text)
        resources_panel = JScrollPane(resource_textarea)

        return resources_panel

    def set_notes_tab(self):
        notes_textarea = JTextArea()

        return notes_textarea

    def set_tsl(self):
        self.tsl = TSL(self)
        self.tree.addTreeSelectionListener(self.tsl)

        return

    def get_tsl(self):
        return self.tsl

    def set_settings(self):
        self.settings = JPanel()
        layout = GroupLayout(self.settings)
        self.settings.setLayout(layout)
        layout.setAutoCreateGaps(True)

        load_file_button = JButton("Load JSON File")
        load_file_button.setActionCommand("load")
        load_file_button.addActionListener(
            SettingsAction(self, load_file_button, None))
        save_file_button = JButton("Save JSON File")
        save_file_button.setActionCommand("save")
        save_file_button.addActionListener(
            SettingsAction(None, save_file_button, self.tabbed_panes))

        horizontal_group1 = layout.createParallelGroup(
            GroupLayout.Alignment.LEADING)
        horizontal_group1.addComponent(load_file_button)
        horizontal_group1.addComponent(save_file_button)

        horizontal_group = layout.createSequentialGroup()
        horizontal_group.addGroup(horizontal_group1)

        layout.setHorizontalGroup(horizontal_group)

        vertical_group1 = layout.createParallelGroup(
            GroupLayout.Alignment.BASELINE)
        vertical_group1.addComponent(load_file_button)
        vertical_group2 = layout.createParallelGroup(
            GroupLayout.Alignment.BASELINE)
        vertical_group2.addComponent(save_file_button)

        vertical_group = layout.createSequentialGroup()
        vertical_group.addGroup(vertical_group1)
        vertical_group.addGroup(vertical_group2)

        layout.setVerticalGroup(vertical_group)

    def get_settings(self):
        return self.settings

    def set_request_tab_pane(self, request_response):
        raw_request = request_response.getRequest()
        request_body = StringUtil.fromBytes(raw_request)
        request_body = request_body.encode("utf-8")

        request_tab_textarea = JTextArea(request_body)
        request_tab_textarea.setLineWrap(True)

        return JScrollPane(request_tab_textarea)

    def set_response_tab_pane(self, request_response):
        raw_response = request_response.getResponse()
        response_body = StringUtil.fromBytes(raw_response)
        response_body = response_body.encode("utf-8")

        response_tab_textarea = JTextArea(response_body)
        response_tab_textarea.setLineWrap(True)

        return JScrollPane(response_tab_textarea)

    def set_bugs_tabbed_pane(self, request_tab, response_tab):
        bugs_tabbed_pane = JTabbedPane()

        bugs_tabbed_pane.add("Request", request_tab)
        bugs_tabbed_pane.add("Response", response_tab)

        return bugs_tabbed_pane
    def	registerExtenderCallbacks(self, callbacks):
    
        # keep a reference to our Burp callbacks object
        self._callbacks = callbacks
        # obtain an Burp extension helpers object
        self._helpers = callbacks.getHelpers()
        # set our extension name
        callbacks.setExtensionName("AuthMatrix - v0.5.2")

        # DB that holds everything users, roles, and messages
        self._db = MatrixDB()

        # For saving/loading config
        self._fc = JFileChooser()        

        # Used by ActionListeners
        selfExtender = self
        self._selectedColumn = -1
        self._selectedRow = -1


        # Table of User entries
        self._userTable = UserTable(self, model = UserTableModel(self._db))
        roleScrollPane = JScrollPane(self._userTable)
        self._userTable.redrawTable()

        # Table of Request (AKA Message) entries
        self._messageTable = MessageTable(self, model = MessageTableModel(self._db))
        messageScrollPane = JScrollPane(self._messageTable)
        self._messageTable.redrawTable()


        # Semi-Generic Popup stuff
        def addPopup(component, popup):
            class genericMouseListener(MouseAdapter):
                def mousePressed(self, e):
                    if e.isPopupTrigger():
                        self.showMenu(e)
                def mouseReleased(self, e):
                    if e.isPopupTrigger():
                        self.showMenu(e)
                def showMenu(self, e):
                    if type(component) is JTableHeader:
                        table = component.getTable()
                        column = component.columnAtPoint(e.getPoint())
                        if type(table) is MessageTable and column >= selfExtender._db.STATIC_MESSAGE_TABLE_COLUMN_COUNT or type(table) is UserTable and column >= selfExtender._db.STATIC_USER_TABLE_COLUMN_COUNT:
                            selfExtender._selectedColumn = column
                        else:
                            return
                    else:
                        selfExtender._selectedRow = component.rowAtPoint(e.getPoint())
                    popup.show(e.getComponent(), e.getX(), e.getY())
            component.addMouseListener(genericMouseListener())

        class actionRunMessage(ActionListener):
            def actionPerformed(self,e):
                if selfExtender._selectedRow >= 0:
                    if selfExtender._selectedRow not in selfExtender._messageTable.getSelectedRows():
                        indexes = [selfExtender._db.getMessageByRow(selfExtender._selectedRow)._index]
                    else:
                        indexes = [selfExtender._db.getMessageByRow(rowNum)._index for rowNum in selfExtender._messageTable.getSelectedRows()]
                    t = Thread(target=selfExtender.runMessagesThread, args = [indexes])
                    t.start()
                    selfExtender._selectedColumn = -1
                    # Redrawing the table happens in colorcode within the thread

        class actionRemoveMessage(ActionListener):
            def actionPerformed(self,e):
                if selfExtender._selectedRow >= 0:
                    if selfExtender._selectedRow not in selfExtender._messageTable.getSelectedRows():
                        indexes = [selfExtender._db.getMessageByRow(selfExtender._selectedRow)._index]
                    else:
                        indexes = [selfExtender._db.getMessageByRow(rowNum)._index for rowNum in selfExtender._messageTable.getSelectedRows()]
                    for i in indexes:
                        selfExtender._db.deleteMessage(i)
                    selfExtender._selectedColumn = -1
                    selfExtender._messageTable.redrawTable()

        class actionRemoveUser(ActionListener):
            def actionPerformed(self,e):
                if selfExtender._selectedRow >= 0:
                    if selfExtender._selectedRow not in selfExtender._userTable.getSelectedRows():
                        indexes = [selfExtender._db.getUserByRow(selfExtender._selectedRow)._index]
                    else:
                        indexes = [selfExtender._db.getUserByRow(rowNum)._index for rowNum in selfExtender._userTable.getSelectedRows()]
                    for i in indexes:
                        selfExtender._db.deleteUser(i)
                    selfExtender._selectedColumn = -1
                    selfExtender._userTable.redrawTable()

        # TODO combine these next two classes
        class actionRemoveRoleHeaderFromMessageTable(ActionListener):
            def actionPerformed(self,e):
                if selfExtender._selectedColumn >= 0:
                    selfExtender._db.deleteRole(selfExtender._db.getRoleByMessageTableColumn(selfExtender._selectedColumn)._index)
                    selfExtender._selectedColumn = -1
                    selfExtender._userTable.redrawTable()
                    selfExtender._messageTable.redrawTable()

        class actionRemoveRoleHeaderFromUserTable(ActionListener):
            def actionPerformed(self,e):
                if selfExtender._selectedColumn >= 0:
                    selfExtender._db.deleteRole(selfExtender._db.getRoleByUserTableColumn(selfExtender._selectedColumn)._index)
                    selfExtender._selectedColumn = -1
                    selfExtender._userTable.redrawTable()
                    selfExtender._messageTable.redrawTable()


        # Message Table popups
        messagePopup = JPopupMenu()
        addPopup(self._messageTable,messagePopup)
        messageRun = JMenuItem("Run Request(s)")
        messageRun.addActionListener(actionRunMessage())
        messagePopup.add(messageRun)
        messageRemove = JMenuItem("Remove Request(s)")
        messageRemove.addActionListener(actionRemoveMessage())
        messagePopup.add(messageRemove)

        messageHeaderPopup = JPopupMenu()
        addPopup(self._messageTable.getTableHeader(),messageHeaderPopup)
        roleRemoveFromMessageTable = JMenuItem("Remove Role")
        roleRemoveFromMessageTable.addActionListener(actionRemoveRoleHeaderFromMessageTable())
        messageHeaderPopup.add(roleRemoveFromMessageTable)

        # User Table popup
        userPopup = JPopupMenu()
        addPopup(self._userTable,userPopup)
        userRemove = JMenuItem("Remove Users(s)")
        userRemove.addActionListener(actionRemoveUser())
        userPopup.add(userRemove)

        userHeaderPopup = JPopupMenu()
        addPopup(self._userTable.getTableHeader(),userHeaderPopup)
        roleRemoveFromUserTable = JMenuItem("Remove Role")
        roleRemoveFromUserTable.addActionListener(actionRemoveRoleHeaderFromUserTable())
        userHeaderPopup.add(roleRemoveFromUserTable)

        # Top pane
        topPane = JSplitPane(JSplitPane.VERTICAL_SPLIT,roleScrollPane,messageScrollPane)

        # request tabs added to this tab on click in message table
        self._tabs = JTabbedPane()

        # Button pannel
        buttons = JPanel()
        runButton = JButton("Run", actionPerformed=self.runClick)
        newUserButton = JButton("New User", actionPerformed=self.getInputUserClick)
        newRoleButton = JButton("New Role", actionPerformed=self.getInputRoleClick)
        #debugButton = JButton("Debug", actionPerformed=self.printDB)
        saveButton = JButton("Save", actionPerformed=self.saveClick)
        loadButton = JButton("Load", actionPerformed=self.loadClick)
        clearButton = JButton("Clear", actionPerformed=self.clearClick)
        buttons.add(runButton)
        buttons.add(newUserButton)
        buttons.add(newRoleButton)
        #buttons.add(debugButton)
        buttons.add(saveButton)
        buttons.add(loadButton)
        buttons.add(clearButton)

        bottomPane = JSplitPane(JSplitPane.VERTICAL_SPLIT, self._tabs, buttons)

        # Main Pane
        self._splitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT, topPane, bottomPane)
        


        # customize our UI components
        callbacks.customizeUiComponent(self._splitpane)
        callbacks.customizeUiComponent(topPane)
        callbacks.customizeUiComponent(bottomPane)
        callbacks.customizeUiComponent(messageScrollPane)
        callbacks.customizeUiComponent(roleScrollPane)
        callbacks.customizeUiComponent(self._messageTable)
        callbacks.customizeUiComponent(self._userTable)
        callbacks.customizeUiComponent(self._tabs)
        callbacks.customizeUiComponent(buttons)

        self._splitpane.setResizeWeight(0.5)
        topPane.setResizeWeight(0.3)
        bottomPane.setResizeWeight(0.95)


        # Handles checkbox color coding
        # Must be bellow the customizeUiComponent calls
        self._messageTable.setDefaultRenderer(Boolean, SuccessBooleanRenderer(self._db))


        # add the custom tab to Burp's UI
        callbacks.addSuiteTab(self)        
        # register SendTo option
        callbacks.registerContextMenuFactory(self)

        return
Example #46
0
class BurpExtender(IBurpExtender, ITab, IHttpListener, IMessageEditorController, AbstractTableModel, IContextMenuFactory):

    def registerExtenderCallbacks(self, callbacks):
        # 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("Autorize")
        
        # create the log and a lock on which to synchronize when adding log entries
        self._log = ArrayList()
        self._lock = Lock()
        self._enfocementStatuses = ["Authorization bypass!","Authorization enforced??? (please configure enforcement detector)","Authorization enforced!"]
        self.intercept = 0

        self.initInterceptionFilters()

        self.initEnforcementDetector()

        self.initEnforcementDetectorUnauthorized()

        self.initExport()

        self.initConfigurationTab()

        self.initTabs()
        
        self.initCallbacks()

        self.currentRequestNumber = 1
        
        print "Thank you for installing Autorize v0.12 extension"
        print "Created by Barak Tawily" 
        print "Contributors: Barak Tawily, Federico Dotta"
        print "\nGithub:\nhttps://github.com/Quitten/Autorize"
        return
        

    def initExport(self):
        #
        ## init enforcement detector tab
        #

        exportLType = JLabel("File Type:")
        exportLType.setBounds(10, 10, 100, 30)
       
        exportLES = JLabel("Enforcement Statuses:")
        exportLES.setBounds(10, 50, 160, 30)

        exportFileTypes = ["HTML","CSV"]
        self.exportType = JComboBox(exportFileTypes)
        self.exportType.setBounds(100, 10, 200, 30)

        exportES = ["All Statuses", self._enfocementStatuses[0], self._enfocementStatuses[1], self._enfocementStatuses[2]]
        self.exportES = JComboBox(exportES)
        self.exportES.setBounds(100, 50, 200, 30)

        exportLES = JLabel("Statuses:")
        exportLES.setBounds(10, 50, 100, 30)

        self.exportButton = JButton("Export",actionPerformed=self.export)
        self.exportButton.setBounds(390, 25, 100, 30)

        self.exportPnl = JPanel()
        self.exportPnl.setLayout(None);
        self.exportPnl.setBounds(0, 0, 1000, 1000);
        self.exportPnl.add(exportLType)
        self.exportPnl.add(self.exportType)
        self.exportPnl.add(exportLES)
        self.exportPnl.add(self.exportES)
        self.exportPnl.add(self.exportButton)

    def initEnforcementDetector(self):
        #
        ## init enforcement detector tab
        #

        # These two variable appears to be unused...
        self.EDFP = ArrayList()
        self.EDCT = ArrayList()

        EDLType = JLabel("Type:")
        EDLType.setBounds(10, 10, 140, 30)

        EDLContent = JLabel("Content:")
        EDLContent.setBounds(10, 50, 140, 30)

        EDLabelList = JLabel("Filter List:")
        EDLabelList.setBounds(10, 165, 140, 30)

        EDStrings = ["Headers (simple string): (enforced message headers contains)", "Headers (regex): (enforced messege headers contains)", "Body (simple string): (enforced messege body contains)", "Body (regex): (enforced messege body contains)", "Full request (simple string): (enforced messege contains)", "Full request (regex): (enforced messege contains)", "Content-Length: (constant Content-Length number of enforced response)"]
        self.EDType = JComboBox(EDStrings)
        self.EDType.setBounds(80, 10, 430, 30)
       
        self.EDText = JTextArea("", 5, 30)
        self.EDText.setBounds(80, 50, 300, 110)

        self.EDModel = DefaultListModel();
        self.EDList = JList(self.EDModel);
        self.EDList.setBounds(80, 175, 300, 110)
        self.EDList.setBorder(LineBorder(Color.BLACK))

        self.EDAdd = JButton("Add filter",actionPerformed=self.addEDFilter)
        self.EDAdd.setBounds(390, 85, 120, 30)
        self.EDDel = JButton("Remove filter",actionPerformed=self.delEDFilter)
        self.EDDel.setBounds(390, 210, 120, 30)

        self.EDPnl = JPanel()
        self.EDPnl.setLayout(None);
        self.EDPnl.setBounds(0, 0, 1000, 1000);
        self.EDPnl.add(EDLType)
        self.EDPnl.add(self.EDType)
        self.EDPnl.add(EDLContent)
        self.EDPnl.add(self.EDText)
        self.EDPnl.add(self.EDAdd)
        self.EDPnl.add(self.EDDel)
        self.EDPnl.add(EDLabelList)
        self.EDPnl.add(self.EDList)

    def initEnforcementDetectorUnauthorized(self):
        #
        ## init enforcement detector tab
        #

        EDLType = JLabel("Type:")
        EDLType.setBounds(10, 10, 140, 30)

        EDLContent = JLabel("Content:")
        EDLContent.setBounds(10, 50, 140, 30)

        EDLabelList = JLabel("Filter List:")
        EDLabelList.setBounds(10, 165, 140, 30)

        EDStrings = ["Headers (simple string): (enforced message headers contains)", "Headers (regex): (enforced messege headers contains)", "Body (simple string): (enforced messege body contains)", "Body (regex): (enforced messege body contains)", "Full request (simple string): (enforced messege contains)", "Full request (regex): (enforced messege contains)", "Content-Length: (constant Content-Length number of enforced response)"]
        self.EDTypeUnauth = JComboBox(EDStrings)
        self.EDTypeUnauth.setBounds(80, 10, 430, 30)
       
        self.EDTextUnauth = JTextArea("", 5, 30)
        self.EDTextUnauth.setBounds(80, 50, 300, 110)

        self.EDModelUnauth = DefaultListModel();
        self.EDListUnauth = JList(self.EDModelUnauth);
        self.EDListUnauth.setBounds(80, 175, 300, 110)
        self.EDListUnauth.setBorder(LineBorder(Color.BLACK))

        self.EDAddUnauth = JButton("Add filter",actionPerformed=self.addEDFilterUnauth)
        self.EDAddUnauth.setBounds(390, 85, 120, 30)
        self.EDDelUnauth = JButton("Remove filter",actionPerformed=self.delEDFilterUnauth)
        self.EDDelUnauth.setBounds(390, 210, 120, 30)

        self.EDPnlUnauth = JPanel()
        self.EDPnlUnauth.setLayout(None);
        self.EDPnlUnauth.setBounds(0, 0, 1000, 1000);
        self.EDPnlUnauth.add(EDLType)
        self.EDPnlUnauth.add(self.EDTypeUnauth)
        self.EDPnlUnauth.add(EDLContent)
        self.EDPnlUnauth.add(self.EDTextUnauth)
        self.EDPnlUnauth.add(self.EDAddUnauth)
        self.EDPnlUnauth.add(self.EDDelUnauth)
        self.EDPnlUnauth.add(EDLabelList)
        self.EDPnlUnauth.add(self.EDListUnauth)        

    def initInterceptionFilters(self):
        #
        ##  init interception filters tab
        #

        IFStrings = ["Scope items only: (Content is not required)","URL Contains (simple string): ","URL Contains (regex): ","URL Not Contains (simple string): ","URL Not Contains (regex): "]
        self.IFType = JComboBox(IFStrings)
        self.IFType.setBounds(80, 10, 430, 30)
       
        self.IFModel = DefaultListModel();
        self.IFList = JList(self.IFModel);
        self.IFList.setBounds(80, 175, 300, 110)
        self.IFList.setBorder(LineBorder(Color.BLACK))

        self.IFText = JTextArea("", 5, 30)
        self.IFText.setBounds(80, 50, 300, 110)

        IFLType = JLabel("Type:")
        IFLType.setBounds(10, 10, 140, 30)

        IFLContent = JLabel("Content:")
        IFLContent.setBounds(10, 50, 140, 30)

        IFLabelList = JLabel("Filter List:")
        IFLabelList.setBounds(10, 165, 140, 30)

        self.IFAdd = JButton("Add filter",actionPerformed=self.addIFFilter)
        self.IFAdd.setBounds(390, 85, 120, 30)
        self.IFDel = JButton("Remove filter",actionPerformed=self.delIFFilter)
        self.IFDel.setBounds(390, 210, 120, 30)

        self.filtersPnl = JPanel()
        self.filtersPnl.setLayout(None);
        self.filtersPnl.setBounds(0, 0, 1000, 1000);
        self.filtersPnl.add(IFLType)
        self.filtersPnl.add(self.IFType)
        self.filtersPnl.add(IFLContent)
        self.filtersPnl.add(self.IFText)
        self.filtersPnl.add(self.IFAdd)
        self.filtersPnl.add(self.IFDel)
        self.filtersPnl.add(IFLabelList)
        self.filtersPnl.add(self.IFList)


    def initConfigurationTab(self):
        #
        ##  init configuration tab
        #
        self.prevent304 = JCheckBox("Prevent 304 Not Modified status code")
        self.prevent304.setBounds(290, 25, 300, 30)

        self.ignore304 = JCheckBox("Ignore 304/204 status code responses")
        self.ignore304.setBounds(290, 5, 300, 30)
        self.ignore304.setSelected(True)

        self.autoScroll = JCheckBox("Auto Scroll")
        #self.autoScroll.setBounds(290, 45, 140, 30)
        self.autoScroll.setBounds(160, 40, 140, 30)

        self.doUnauthorizedRequest = JCheckBox("Check unauthenticated")
        self.doUnauthorizedRequest.setBounds(290, 45, 300, 30)
        self.doUnauthorizedRequest.setSelected(True)

        startLabel = JLabel("Authorization checks:")
        startLabel.setBounds(10, 10, 140, 30)
        self.startButton = JButton("Autorize is off",actionPerformed=self.startOrStop)
        self.startButton.setBounds(160, 10, 120, 30)
        self.startButton.setBackground(Color(255, 100, 91, 255))

        self.clearButton = JButton("Clear List",actionPerformed=self.clearList)
        self.clearButton.setBounds(10, 40, 100, 30)

        self.replaceString = JTextArea("Cookie: Insert=injected; header=here;", 5, 30)
        self.replaceString.setWrapStyleWord(True);
        self.replaceString.setLineWrap(True)
        self.replaceString.setBounds(10, 80, 470, 180)

        self.filtersTabs = JTabbedPane()
        self.filtersTabs.addTab("Enforcement Detector", self.EDPnl)
        self.filtersTabs.addTab("Detector Unauthenticated", self.EDPnlUnauth)
        self.filtersTabs.addTab("Interception Filters", self.filtersPnl)
        self.filtersTabs.addTab("Export", self.exportPnl)

        self.filtersTabs.setBounds(0, 280, 2000, 700)

        self.pnl = JPanel()
        self.pnl.setBounds(0, 0, 1000, 1000);
        self.pnl.setLayout(None);
        self.pnl.add(self.startButton)
        self.pnl.add(self.clearButton)
        self.pnl.add(self.replaceString)
        self.pnl.add(startLabel)
        self.pnl.add(self.autoScroll)
        self.pnl.add(self.ignore304)
        self.pnl.add(self.prevent304)
        self.pnl.add(self.doUnauthorizedRequest)
        self.pnl.add(self.filtersTabs)

    def initTabs(self):
        #
        ##  init autorize tabs
        #
        
        self.logTable = Table(self)

        self.logTable.setAutoCreateRowSorter(True)        

        tableWidth = self.logTable.getPreferredSize().width        
        self.logTable.getColumn("ID").setPreferredWidth(Math.round(tableWidth / 50 * 2))
        self.logTable.getColumn("URL").setPreferredWidth(Math.round(tableWidth / 50 * 24))
        self.logTable.getColumn("Orig. Length").setPreferredWidth(Math.round(tableWidth / 50 * 4))
        self.logTable.getColumn("Modif. Length").setPreferredWidth(Math.round(tableWidth / 50 * 4))
        self.logTable.getColumn("Unauth. Length").setPreferredWidth(Math.round(tableWidth / 50 * 4))
        self.logTable.getColumn("Authorization Enforcement Status").setPreferredWidth(Math.round(tableWidth / 50 * 4))
        self.logTable.getColumn("Authorization Unauth. Status").setPreferredWidth(Math.round(tableWidth / 50 * 4))

        self._splitpane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT)
        self._splitpane.setResizeWeight(1)
        self.scrollPane = JScrollPane(self.logTable)
        self._splitpane.setLeftComponent(self.scrollPane)
        self.scrollPane.getVerticalScrollBar().addAdjustmentListener(autoScrollListener(self))
        self.menuES0 = JCheckBoxMenuItem(self._enfocementStatuses[0],True)
        self.menuES1 = JCheckBoxMenuItem(self._enfocementStatuses[1],True)
        self.menuES2 = JCheckBoxMenuItem(self._enfocementStatuses[2],True)
        self.menuES0.addItemListener(menuTableFilter(self))
        self.menuES1.addItemListener(menuTableFilter(self))
        self.menuES2.addItemListener(menuTableFilter(self))

        copyURLitem = JMenuItem("Copy URL");
        copyURLitem.addActionListener(copySelectedURL(self))
        self.menu = JPopupMenu("Popup")
        self.menu.add(copyURLitem)
        self.menu.add(self.menuES0)
        self.menu.add(self.menuES1)
        self.menu.add(self.menuES2)

        self.tabs = JTabbedPane()
        self._requestViewer = self._callbacks.createMessageEditor(self, False)
        self._responseViewer = self._callbacks.createMessageEditor(self, False)

        self._originalrequestViewer = self._callbacks.createMessageEditor(self, False)
        self._originalresponseViewer = self._callbacks.createMessageEditor(self, False)

        self._unauthorizedrequestViewer = self._callbacks.createMessageEditor(self, False)
        self._unauthorizedresponseViewer = self._callbacks.createMessageEditor(self, False)        

        self.tabs.addTab("Modified Request", self._requestViewer.getComponent())
        self.tabs.addTab("Modified Response", self._responseViewer.getComponent())

        self.tabs.addTab("Original Request", self._originalrequestViewer.getComponent())
        self.tabs.addTab("Original Response", self._originalresponseViewer.getComponent())

        self.tabs.addTab("Unauthenticated Request", self._unauthorizedrequestViewer.getComponent())
        self.tabs.addTab("Unauthenticated Response", self._unauthorizedresponseViewer.getComponent())        

        self.tabs.addTab("Configuration", self.pnl)
        self.tabs.setSelectedIndex(6)
        self._splitpane.setRightComponent(self.tabs)

    def initCallbacks(self):
        #
        ##  init callbacks
        #

        # customize our UI components
        self._callbacks.customizeUiComponent(self._splitpane)
        self._callbacks.customizeUiComponent(self.logTable)
        self._callbacks.customizeUiComponent(self.scrollPane)
        self._callbacks.customizeUiComponent(self.tabs)
        self._callbacks.customizeUiComponent(self.filtersTabs)
        self._callbacks.registerContextMenuFactory(self)
        # add the custom tab to Burp's UI
        self._callbacks.addSuiteTab(self)


    #
    ## Events functions
    #
    def startOrStop(self, event):
        if self.startButton.getText() == "Autorize is off":
            self.startButton.setText("Autorize is on")
            self.startButton.setBackground(Color.GREEN)
            self.intercept = 1
            self._callbacks.registerHttpListener(self)
        else:
            self.startButton.setText("Autorize is off")
            self.startButton.setBackground(Color(255, 100, 91, 255))
            self.intercept = 0
            self._callbacks.removeHttpListener(self)

    def addEDFilter(self, event):
        typeName = self.EDType.getSelectedItem().split(":")[0]
        self.EDModel.addElement(typeName + ": " + self.EDText.getText())

    def delEDFilter(self, event):
        index = self.EDList.getSelectedIndex();
        if not index == -1:
            self.EDModel.remove(index);

    def addEDFilterUnauth(self, event):
        typeName = self.EDTypeUnauth.getSelectedItem().split(":")[0]
        self.EDModelUnauth.addElement(typeName + ": " + self.EDTextUnauth.getText())

    def delEDFilterUnauth(self, event):
        index = self.EDListUnauth.getSelectedIndex();
        if not index == -1:
            self.EDModelUnauth.remove(index);            

    def addIFFilter(self, event):
        typeName = self.IFType.getSelectedItem().split(":")[0]
        self.IFModel.addElement(typeName + ": " + self.IFText.getText())

    def delIFFilter(self, event):
        index = self.IFList.getSelectedIndex();
        if not index == -1:
            self.IFModel.remove(index);

    def clearList(self, event):
        self._lock.acquire()
        oldSize = self._log.size()
        self._log.clear()
        self.fireTableRowsDeleted(0, oldSize - 1)
        self._lock.release()

    def export(self, event):
        if self.exportType.getSelectedItem() == "HTML":
            self.exportToHTML()
        else:
            self.exportToCSV()

    def exportToCSV(self):
        parentFrame = JFrame()
        fileChooser = JFileChooser()
        fileChooser.setSelectedFile(File("AutorizeReprort.csv"));
        fileChooser.setDialogTitle("Save Autorize Report")
        userSelection = fileChooser.showSaveDialog(parentFrame)
        if userSelection == JFileChooser.APPROVE_OPTION:
            fileToSave = fileChooser.getSelectedFile()

        enforcementStatusFilter = self.exportES.getSelectedItem()
        csvContent = "id\tURL\tOriginal length\tModified length\tUnauthorized length\tAuthorization Enforcement Status\tAuthorization Unauthenticated Status\n"

        for i in range(0,self._log.size()):

            if enforcementStatusFilter == "All Statuses":
                csvContent += "%d\t%s\t%d\t%d\t%d\t%s\t%s\n" % (self._log.get(i)._id,self._log.get(i)._url, len(self._log.get(i)._originalrequestResponse.getResponse()) if self._log.get(i)._originalrequestResponse != None else 0, len(self._log.get(i)._requestResponse.getResponse()) if self._log.get(i)._requestResponse != None else 0, len(self._log.get(i)._unauthorizedRequestResponse.getResponse()) if self._log.get(i)._unauthorizedRequestResponse != None else 0, self._log.get(i)._enfocementStatus, self._log.get(i)._enfocementStatusUnauthorized)
                
            else:
                if (enforcementStatusFilter == self._log.get(i)._enfocementStatus) or (enforcementStatusFilter == self._log.get(i)._enfocementStatusUnauthorized):
                    csvContent += "%d\t%s\t%d\t%d\t%d\t%s\t%s\n" % (self._log.get(i)._id,self._log.get(i)._url, len(self._log.get(i)._originalrequestResponse.getResponse()) if self._log.get(i)._originalrequestResponse != None else 0, len(self._log.get(i)._requestResponse.getResponse()) if self._log.get(i)._requestResponse != None else 0, len(self._log.get(i)._unauthorizedRequestResponse.getResponse()) if self._log.get(i)._unauthorizedRequestResponse != None else 0, self._log.get(i)._enfocementStatus, self._log.get(i)._enfocementStatusUnauthorized)
        
        f = open(fileToSave.getAbsolutePath(), 'w')
        f.writelines(csvContent)
        f.close()


    def exportToHTML(self):
        parentFrame = JFrame()
        fileChooser = JFileChooser()
        fileChooser.setSelectedFile(File("AutorizeReprort.html"));
        fileChooser.setDialogTitle("Save Autorize Report")
        userSelection = fileChooser.showSaveDialog(parentFrame)
        if userSelection == JFileChooser.APPROVE_OPTION:
            fileToSave = fileChooser.getSelectedFile()

        enforcementStatusFilter = self.exportES.getSelectedItem()
        htmlContent = """<html><title>Autorize Report by Barak Tawily</title>
        <style>
        .datagrid table { border-collapse: collapse; text-align: left; width: 100%; }
         .datagrid {font: normal 12px/150% Arial, Helvetica, sans-serif; background: #fff; overflow: hidden; border: 1px solid #006699; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; }
         .datagrid table td, .datagrid table th { padding: 3px 10px; }
         .datagrid table thead th {background:-webkit-gradient( linear, left top, left bottom, color-stop(0.05, #006699), color-stop(1, #00557F) );background:-moz-linear-gradient( center top, #006699 5%, #00557F 100% );filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#006699', endColorstr='#00557F');background-color:#006699; color:#FFFFFF; font-size: 15px; font-weight: bold; border-left: 1px solid #0070A8; } .datagrid table thead th:first-child { border: none; }.datagrid table tbody td { color: #00496B; border-left: 1px solid #E1EEF4;font-size: 12px;font-weight: normal; }.datagrid table tbody .alt td { background: #E1EEF4; color: #00496B; }.datagrid table tbody td:first-child { border-left: none; }.datagrid table tbody tr:last-child td { border-bottom: none; }.datagrid table tfoot td div { border-top: 1px solid #006699;background: #E1EEF4;} .datagrid table tfoot td { padding: 0; font-size: 12px } .datagrid table tfoot td div{ padding: 2px; }.datagrid table tfoot td ul { margin: 0; padding:0; list-style: none; text-align: right; }.datagrid table tfoot  li { display: inline; }.datagrid table tfoot li a { text-decoration: none; display: inline-block;  padding: 2px 8px; margin: 1px;color: #FFFFFF;border: 1px solid #006699;-webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; background:-webkit-gradient( linear, left top, left bottom, color-stop(0.05, #006699), color-stop(1, #00557F) );background:-moz-linear-gradient( center top, #006699 5%, #00557F 100% );filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#006699', endColorstr='#00557F');background-color:#006699; }.datagrid table tfoot ul.active, .datagrid table tfoot ul a:hover { text-decoration: none;border-color: #006699; color: #FFFFFF; background: none; background-color:#00557F;}div.dhtmlx_window_active, div.dhx_modal_cover_dv { position: fixed !important; }
        table {
        width: 100%;
        table-layout: fixed;
        }
        td {
            border: 1px solid #35f;
            overflow: hidden;
            text-overflow: ellipsis;
        }
        td.a {
            width: 13%;
            white-space: nowrap;
        }
        td.b {
            width: 9%;
            word-wrap: break-word;
        }
        </style>
        <body>
        <h1>Autorize Report<h1>
        <div class="datagrid"><table>
        <thead><tr><th width=\"3%\">ID</th><th width=\"48%\">URL</th><th width=\"9%\">Original length</th><th width=\"9%\">Modified length</th><th width=\"9%\">Unauthorized length</th><th width=\"11%\">Authorization Enforcement Status</th><th width=\"11%\">Authorization Unauthenticated Status</th></tr></thead>
        <tbody>"""

        for i in range(0,self._log.size()):
            color_modified = ""
            if self._log.get(i)._enfocementStatus == self._enfocementStatuses[0]:
                color_modified = "red"
            if self._log.get(i)._enfocementStatus == self._enfocementStatuses[1]:
                color_modified = "yellow"
            if self._log.get(i)._enfocementStatus == self._enfocementStatuses[2]:
                color_modified = "LawnGreen"

            color_unauthorized = ""
            if self._log.get(i)._enfocementStatusUnauthorized == self._enfocementStatuses[0]:
                color_unauthorized = "red"
            if self._log.get(i)._enfocementStatusUnauthorized == self._enfocementStatuses[1]:
                color_unauthorized = "yellow"
            if self._log.get(i)._enfocementStatusUnauthorized == self._enfocementStatuses[2]:
                color_unauthorized = "LawnGreen"

            if enforcementStatusFilter == "All Statuses":
                htmlContent += "<tr><td>%d</td><td><a href=\"%s\">%s</a></td><td>%d</td><td>%d</td><td>%d</td><td bgcolor=\"%s\">%s</td><td bgcolor=\"%s\">%s</td></tr>" % (self._log.get(i)._id,self._log.get(i)._url,self._log.get(i)._url, len(self._log.get(i)._originalrequestResponse.getResponse()) if self._log.get(i)._originalrequestResponse != None else 0, len(self._log.get(i)._requestResponse.getResponse()) if self._log.get(i)._requestResponse != None else 0, len(self._log.get(i)._unauthorizedRequestResponse.getResponse()) if self._log.get(i)._unauthorizedRequestResponse != None else 0, color_modified, self._log.get(i)._enfocementStatus, color_unauthorized, self._log.get(i)._enfocementStatusUnauthorized)
            else:
                if (enforcementStatusFilter == self._log.get(i)._enfocementStatus) or (enforcementStatusFilter == self._log.get(i)._enfocementStatusUnauthorized):
                    htmlContent += "<tr><td>%d</td><td><a href=\"%s\">%s</a></td><td>%d</td><td>%d</td><td>%d</td><td bgcolor=\"%s\">%s</td><td bgcolor=\"%s\">%s</td></tr>" % (self._log.get(i)._id,self._log.get(i)._url,self._log.get(i)._url, len(self._log.get(i)._originalrequestResponse.getResponse()) if self._log.get(i)._originalrequestResponse != None else 0, len(self._log.get(i)._requestResponse.getResponse()) if self._log.get(i)._requestResponse != None else 0, len(self._log.get(i)._unauthorizedRequestResponse.getResponse()) if self._log.get(i)._unauthorizedRequestResponse != None else 0, color_modified, self._log.get(i)._enfocementStatus, color_unauthorized, self._log.get(i)._enfocementStatusUnauthorized)

        htmlContent += "</tbody></table></div></body></html>"
        f = open(fileToSave.getAbsolutePath(), 'w')
        f.writelines(htmlContent)
        f.close()




    #
    # implement IContextMenuFactory
    #
    def createMenuItems(self, invocation):
        responses = invocation.getSelectedMessages();
        if responses > 0:
            ret = LinkedList()
            requestMenuItem = JMenuItem("Send request to Autorize");
            cookieMenuItem = JMenuItem("Send cookie to Autorize");
            requestMenuItem.addActionListener(handleMenuItems(self,responses[0], "request"))
            cookieMenuItem.addActionListener(handleMenuItems(self, responses[0], "cookie"))   
            ret.add(requestMenuItem);
            ret.add(cookieMenuItem);
            return(ret);
        return null;


    #
    # implement ITab
    #
    def getTabCaption(self):
        return "Autorize"
    
    def getUiComponent(self):
        return self._splitpane
        
    #
    # extend AbstractTableModel
    #
    
    def getRowCount(self):
        try:
            return self._log.size()
        except:
            return 0

    def getColumnCount(self):
        return 7

    def getColumnName(self, columnIndex):
        if columnIndex == 0:
            return "ID"
        if columnIndex == 1:
            return "URL"
        if columnIndex == 2:
            return "Orig. Length"            
        if columnIndex == 3:
            return "Modif. Length" 
        if columnIndex == 4:
            return "Unauth. Length"           
        if columnIndex == 5:
            return "Authorization Enforcement Status"
        if columnIndex == 6:
            return "Authorization Unauth. Status"
        return ""

    def getColumnClass(self, columnIndex):
        if columnIndex == 0:
            return Integer
        if columnIndex == 1:
            return String
        if columnIndex == 2:
            return Integer           
        if columnIndex == 3:
            return Integer 
        if columnIndex == 4:
            return Integer          
        if columnIndex == 5:
            return String
        if columnIndex == 6:
            return String
        return String

    def getValueAt(self, rowIndex, columnIndex):
        logEntry = self._log.get(rowIndex)
        if columnIndex == 0:
            return logEntry._id
        if columnIndex == 1:
            return logEntry._url.toString()
        if columnIndex == 2:
            return len(logEntry._originalrequestResponse.getResponse())
        if columnIndex == 3:
            return len(logEntry._requestResponse.getResponse())
        if columnIndex == 4:
            if logEntry._unauthorizedRequestResponse != None:
                return len(logEntry._unauthorizedRequestResponse.getResponse())
            else:
                #return "-"
                return 0
        if columnIndex == 5:
            return logEntry._enfocementStatus   
        if columnIndex == 6:
            return logEntry._enfocementStatusUnauthorized        
        return ""

    #
    # implement IMessageEditorController
    # this allows our request/response viewers to obtain details about the messages being displayed
    #
    
    def getHttpService(self):
        return self._currentlyDisplayedItem.getHttpService()

    def getRequest(self):
        return self._currentlyDisplayedItem.getRequest()

    def getResponse(self):
        return self._currentlyDisplayedItem.getResponse()


    #
    # implement IHttpListener
    #
    def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo):

        #if (self.intercept == 1) and (toolFlag != self._callbacks.TOOL_EXTENDER):
        if (self.intercept == 1) and (toolFlag == self._callbacks.TOOL_PROXY):
            if self.prevent304.isSelected():
                if messageIsRequest:
                    requestHeaders = list(self._helpers.analyzeRequest(messageInfo).getHeaders())
                    newHeaders = list()
                    found = 0
                    for header in requestHeaders:
                        if not "If-None-Match:" in header and not "If-Modified-Since:" in header:
                            newHeaders.append(header)
                            found = 1
                    if found == 1:
                        requestInfo = self._helpers.analyzeRequest(messageInfo)
                        bodyBytes = messageInfo.getRequest()[requestInfo.getBodyOffset():]
                        bodyStr = self._helpers.bytesToString(bodyBytes)
                        messageInfo.setRequest(self._helpers.buildHttpMessage(newHeaders, bodyStr))


            if not messageIsRequest:
                if not self.replaceString.getText() in self._helpers.analyzeRequest(messageInfo).getHeaders():
                    if self.ignore304.isSelected():
                        firstHeader = self._helpers.analyzeResponse(messageInfo.getResponse()).getHeaders()[0]
                        if "304" in firstHeader or "204" in firstHeader:
                           return
                    if self.IFList.getModel().getSize() == 0:
                        self.checkAuthorization(messageInfo,self._helpers.analyzeResponse(messageInfo.getResponse()).getHeaders(),self.doUnauthorizedRequest.isSelected())
                    else:
                        urlString = str(self._helpers.analyzeRequest(messageInfo).getUrl())
                        
                        do_the_check = 1

                        for i in range(0,self.IFList.getModel().getSize()):

                            if self.IFList.getModel().getElementAt(i).split(":")[0] == "Scope items only":
                                currentURL = URL(urlString)
                                if not self._callbacks.isInScope(currentURL):
                                    do_the_check = 0
                            if self.IFList.getModel().getElementAt(i).split(":")[0] == "URL Contains (simple string)":
                                if self.IFList.getModel().getElementAt(i)[30:] not in urlString:
                                    do_the_check = 0
                            if self.IFList.getModel().getElementAt(i).split(":")[0] == "URL Contains (regex)":
                                regex_string = self.IFList.getModel().getElementAt(i)[22:]
                                p = re.compile(regex_string, re.IGNORECASE)
                                if not p.search(urlString):
                                    do_the_check = 0  
                            if self.IFList.getModel().getElementAt(i).split(":")[0] == "URL Not Contains (simple string)":
                                if self.IFList.getModel().getElementAt(i)[34:] in urlString:
                                    do_the_check = 0
                            if self.IFList.getModel().getElementAt(i).split(":")[0] == "URL Not Contains (regex)":
                                regex_string = self.IFList.getModel().getElementAt(i)[26:]
                                p = re.compile(regex_string, re.IGNORECASE)
                                if p.search(urlString):
                                    do_the_check = 0                                                                       

                        if do_the_check:
                            self.checkAuthorization(messageInfo,self._helpers.analyzeResponse(messageInfo.getResponse()).getHeaders(),self.doUnauthorizedRequest.isSelected())

        return

    def sendRequestToAutorizeWork(self,messageInfo):

        if messageInfo.getResponse() == None:
            message = self.makeMessage(messageInfo,False,False)
            requestResponse = self.makeRequest(messageInfo, message)
            self.checkAuthorization(requestResponse,self._helpers.analyzeResponse(requestResponse.getResponse()).getHeaders(),self.doUnauthorizedRequest.isSelected())
        else:
            self.checkAuthorization(messageInfo,self._helpers.analyzeResponse(messageInfo.getResponse()).getHeaders(),self.doUnauthorizedRequest.isSelected())


    def makeRequest(self, messageInfo, message):
        requestURL = self._helpers.analyzeRequest(messageInfo).getUrl()
        return self._callbacks.makeHttpRequest(self._helpers.buildHttpService(str(requestURL.getHost()), int(requestURL.getPort()), requestURL.getProtocol() == "https"), message)

    def makeMessage(self, messageInfo, removeOrNot, authorizeOrNot):
        requestInfo = self._helpers.analyzeRequest(messageInfo)
        headers = requestInfo.getHeaders()
        if removeOrNot:
            headers = list(headers)
            removeHeaders = ArrayList()
            removeHeaders.add(self.replaceString.getText()[0:self.replaceString.getText().index(":")])

            for header in headers[:]:
                for removeHeader in removeHeaders:
                    if removeHeader in header:
                        headers.remove(header)

            if authorizeOrNot:
                headers.append(self.replaceString.getText())

        msgBody = messageInfo.getRequest()[requestInfo.getBodyOffset():]
        return self._helpers.buildHttpMessage(headers, msgBody)

    def checkBypass(self,oldStatusCode,newStatusCode,oldContentLen,newContentLen,filters,requestResponse):

        analyzedResponse = self._helpers.analyzeResponse(requestResponse.getResponse())
        impression = ""

        if oldStatusCode == newStatusCode:
            if oldContentLen == newContentLen:
                impression = self._enfocementStatuses[0]
            else:

                auth_enforced = 1
                
                for filter in filters:

                    if str(filter).startswith("Headers (simple string): "):
                        if not(filter[25:] in self._helpers.bytesToString(requestResponse.getResponse()[0:analyzedResponse.getBodyOffset()])):
                            auth_enforced = 0

                    if str(filter).startswith("Headers (regex): "):
                        regex_string = filter[17:]
                        p = re.compile(regex_string, re.IGNORECASE)
                        if not p.search(self._helpers.bytesToString(requestResponse.getResponse()[0:analyzedResponse.getBodyOffset()])):
                            auth_enforced = 0

                    if str(filter).startswith("Body (simple string): "):
                        if not(filter[22:] in self._helpers.bytesToString(requestResponse.getResponse()[analyzedResponse.getBodyOffset():])):
                            auth_enforced = 0

                    if str(filter).startswith("Body (regex): "):
                        regex_string = filter[14:]
                        p = re.compile(regex_string, re.IGNORECASE)
                        if not p.search(self._helpers.bytesToString(requestResponse.getResponse()[analyzedResponse.getBodyOffset():])):
                            auth_enforced = 0

                    if str(filter).startswith("Full request (simple string): "):
                        if not(filter[30:] in self._helpers.bytesToString(requestResponse.getResponse())):
                            auth_enforced = 0

                    if str(filter).startswith("Full request (regex): "):
                        regex_string = filter[22:]
                        p = re.compile(regex_string, re.IGNORECASE)
                        if not p.search(self._helpers.bytesToString(requestResponse.getResponse())):
                            auth_enforced = 0

                    if str(filter).startswith("Content-Length: "):
                        if newContentLen != filter:
                            auth_enforced = 0
                
                if auth_enforced:
                    impression = self._enfocementStatuses[2]
                else:
                    impression = self._enfocementStatuses[1]
                         
        else:
            impression = self._enfocementStatuses[2]

        return impression

    def checkAuthorization(self, messageInfo, originalHeaders, checkUnauthorized):
        message = self.makeMessage(messageInfo,True,True)
        requestResponse = self.makeRequest(messageInfo, message)
        analyzedResponse = self._helpers.analyzeResponse(requestResponse.getResponse())
        
        oldStatusCode = originalHeaders[0]
        newStatusCode = analyzedResponse.getHeaders()[0]
        oldContentLen = self.getContentLength(originalHeaders)
        newContentLen = self.getContentLength(analyzedResponse.getHeaders())

        # Check unauthorized request
        if checkUnauthorized:
            messageUnauthorized = self.makeMessage(messageInfo,True,False)
            requestResponseUnauthorized = self.makeRequest(messageInfo, messageUnauthorized)
            analyzedResponseUnauthorized = self._helpers.analyzeResponse(requestResponseUnauthorized.getResponse())  
            statusCodeUnauthorized = analyzedResponseUnauthorized.getHeaders()[0]
            contentLenUnauthorized = self.getContentLength(analyzedResponseUnauthorized.getHeaders())

        EDFilters = self.EDModel.toArray()
        impression = self.checkBypass(oldStatusCode,newStatusCode,oldContentLen,newContentLen,EDFilters,requestResponse)

        if checkUnauthorized:
            EDFiltersUnauth = self.EDModelUnauth.toArray()
            impressionUnauthorized = self.checkBypass(oldStatusCode,statusCodeUnauthorized,oldContentLen,contentLenUnauthorized,EDFiltersUnauth,requestResponseUnauthorized)

        self._lock.acquire()
        
        row = self._log.size()
        
        if checkUnauthorized:
            self._log.add(LogEntry(self.currentRequestNumber,self._callbacks.saveBuffersToTempFiles(requestResponse), self._helpers.analyzeRequest(requestResponse).getUrl(),messageInfo,impression,self._callbacks.saveBuffersToTempFiles(requestResponseUnauthorized),impressionUnauthorized)) # same requests not include again.
        else:
            self._log.add(LogEntry(self.currentRequestNumber,self._callbacks.saveBuffersToTempFiles(requestResponse), self._helpers.analyzeRequest(requestResponse).getUrl(),messageInfo,impression,None,"Disabled")) # same requests not include again.
        
        self.fireTableRowsInserted(row, row)
        self.currentRequestNumber = self.currentRequestNumber + 1
        self._lock.release()
        
    def getContentLength(self, analyzedResponseHeaders):
        for header in analyzedResponseHeaders:
            if "Content-Length:" in header:
                return header;
        return "null"

    def getCookieFromMessage(self, messageInfo):
        headers = list(self._helpers.analyzeRequest(messageInfo.getRequest()).getHeaders())
        for header in headers:
            if "Cookie:" in header:
                return header
        return None
Example #47
0
class BurpExtender(IBurpExtender, ITab, IHttpListener, IMessageEditorController, AbstractTableModel):
    
    #
    # implement IBurpExtender
    #
    
    def	registerExtenderCallbacks(self, callbacks):
    
        # 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("Custom logger")
        
        # create the log and a lock on which to synchronize when adding log entries
        self._log = ArrayList()
        self._lock = Lock()
        
        # main split pane
        self._splitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT)
        
        # table of log entries
        logTable = Table(self)
        scrollPane = JScrollPane(logTable)
        self._splitpane.setLeftComponent(scrollPane)

        # tabs with request/response viewers
        tabs = JTabbedPane()
        self._requestViewer = callbacks.createMessageEditor(self, False)
        self._responseViewer = callbacks.createMessageEditor(self, False)
        tabs.addTab("Request", self._requestViewer.getComponent())
        tabs.addTab("Response", self._responseViewer.getComponent())
        self._splitpane.setRightComponent(tabs)
        
        # customize our UI components
        callbacks.customizeUiComponent(self._splitpane)
        callbacks.customizeUiComponent(logTable)
        callbacks.customizeUiComponent(scrollPane)
        callbacks.customizeUiComponent(tabs)
        
        # add the custom tab to Burp's UI
        callbacks.addSuiteTab(self)
        
        # register ourselves as an HTTP listener
        callbacks.registerHttpListener(self)
        
        return
        
    #
    # implement ITab
    #
    
    def getTabCaption(self):
        return "Logger"
    
    def getUiComponent(self):
        return self._splitpane
        
    #
    # implement IHttpListener
    #
    
    def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo):
    
        # only process response
        if not messageIsRequest:
        
            # create a new log entry with the message details
            self._lock.acquire()
            row = self._log.size()
            self._log.add(LogEntry(toolFlag, self._callbacks.saveBuffersToTempFiles(messageInfo), self._helpers.analyzeRequest(messageInfo).getUrl()))
            self.fireTableRowsInserted(row, row)
            self._lock.release()
        return

    #
    # extend AbstractTableModel
    #
    
    def getRowCount(self):
        try:
            return self._log.size()
        except:
            return 0

    def getColumnCount(self):
        return 2

    def getColumnName(self, columnIndex):
        if columnIndex == 0:
            return "Tool"
        if columnIndex == 1:
            return "URL"
        return ""

    def getValueAt(self, rowIndex, columnIndex):
        logEntry = self._log.get(rowIndex)
        if columnIndex == 0:
            return self._callbacks.getToolName(logEntry._tool)
        if columnIndex == 1:
            return logEntry._url.toString()
        return ""

    #
    # implement IMessageEditorController
    # this allows our request/response viewers to obtain details about the messages being displayed
    #
    
    def getHttpService(self):
        return self._currentlyDisplayedItem.getHttpService()

    def getRequest(self):
        return self._currentlyDisplayedItem.getRequest()

    def getResponse(self):
        return self._currentlyDisplayedItem.getResponse()
Example #48
0
class BurpExtender(IBurpExtender, ITab, IHttpListener,
                   IMessageEditorController, AbstractTableModel,
                   ActionListener, DocumentListener):

    #
    # implement IBurpExtender
    #

    def registerExtenderCallbacks(self, callbacks):

        # 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("Response Clusterer")

        # create the log and a lock on which to synchronize when adding log entries
        self._log = ArrayList()
        self._lock = Lock()

        # main split pane
        self._main_jtabedpane = JTabbedPane()

        # The split pane with the log and request/respponse details
        self._splitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT)

        # table of log entries
        logTable = Table(self)
        scrollPane = JScrollPane(logTable)
        self._splitpane.setLeftComponent(scrollPane)

        # List of log entries
        self._log_entries = []

        # tabs with request/response viewers
        tabs = JTabbedPane()
        self._requestViewer = callbacks.createMessageEditor(self, False)
        self._responseViewer = callbacks.createMessageEditor(self, False)
        tabs.addTab("Request", self._requestViewer.getComponent())
        tabs.addTab("Response", self._responseViewer.getComponent())
        self._splitpane.setRightComponent(tabs)

        #Setup the options
        self._optionsJPanel = JPanel()
        gridBagLayout = GridBagLayout()
        gbc = GridBagConstraints()
        self._optionsJPanel.setLayout(gridBagLayout)

        self.max_clusters = 500
        self.JLabel_max_clusters = JLabel("Maximum amount of clusters: ")
        gbc.gridy = 0
        gbc.gridx = 0
        self._optionsJPanel.add(self.JLabel_max_clusters, gbc)
        self.JTextField_max_clusters = JTextField(str(self.max_clusters), 5)
        self.JTextField_max_clusters.getDocument().addDocumentListener(self)
        gbc.gridx = 1
        self._optionsJPanel.add(self.JTextField_max_clusters, gbc)
        callbacks.customizeUiComponent(self.JLabel_max_clusters)
        callbacks.customizeUiComponent(self.JTextField_max_clusters)

        self.similarity = 0.95
        self.JLabel_similarity = JLabel("Similarity (between 0 and 1)")
        gbc.gridy = 1
        gbc.gridx = 0
        self._optionsJPanel.add(self.JLabel_similarity, gbc)
        self.JTextField_similarity = JTextField(str(self.similarity), 5)
        self.JTextField_similarity.getDocument().addDocumentListener(self)
        gbc.gridx = 1
        self._optionsJPanel.add(self.JTextField_similarity, gbc)
        callbacks.customizeUiComponent(self.JLabel_similarity)
        callbacks.customizeUiComponent(self.JTextField_similarity)

        self.use_quick_similar = False
        self.JLabel_use_quick_similar = JLabel(
            "Use set intersection of space splitted tokens for similarity (default: optimized difflib.SequenceMatcher.quick_ratio)"
        )
        gbc.gridy = 2
        gbc.gridx = 0
        self._optionsJPanel.add(self.JLabel_use_quick_similar, gbc)
        self.JCheckBox_use_quick_similar = JCheckBox("")
        self.JCheckBox_use_quick_similar.addActionListener(self)
        gbc.gridx = 1
        self._optionsJPanel.add(self.JCheckBox_use_quick_similar, gbc)
        callbacks.customizeUiComponent(self.JCheckBox_use_quick_similar)

        self.response_max_size = 10 * 1024  #10kb
        self.JLabel_response_max_size = JLabel("Response max size (bytes)")
        gbc.gridy = 3
        gbc.gridx = 0
        self._optionsJPanel.add(self.JLabel_response_max_size, gbc)
        self.JTextField_response_max_size = JTextField(
            str(self.response_max_size), 5)
        self.JTextField_response_max_size.getDocument().addDocumentListener(
            self)
        gbc.gridx = 1
        self._optionsJPanel.add(self.JTextField_response_max_size, gbc)
        callbacks.customizeUiComponent(self.JLabel_response_max_size)
        callbacks.customizeUiComponent(self.JTextField_response_max_size)

        self.uninteresting_mime_types = ('JPEG', 'CSS', 'GIF', 'script', 'GIF',
                                         'PNG', 'image')
        self.uninteresting_status_codes = ()
        self.uninteresting_url_file_extensions = ('js', 'css', 'zip', 'war',
                                                  'jar', 'doc', 'docx', 'xls',
                                                  'xlsx', 'pdf', 'exe', 'dll',
                                                  'png', 'jpeg', 'jpg', 'bmp',
                                                  'tif', 'tiff', 'gif', 'webp',
                                                  'm3u', 'mp4', 'm4a', 'ogg',
                                                  'aac', 'flac', 'mp3', 'wav',
                                                  'avi', 'mov', 'mpeg', 'wmv',
                                                  'swf', 'woff', 'woff2')

        about = "<html>"
        about += "Author: floyd, @floyd_ch, http://www.floyd.ch<br>"
        about += "modzero AG, http://www.modzero.ch<br>"
        about += "<br>"
        about += "<h3>Getting an overview of the tested website</h3>"
        about += "<p style=\"width:500px\">"
        about += "This plugin clusters all response bodies by similarity and shows a summary, one request/response per cluster. "
        about += 'Adjust similarity in the options if you get too few or too many entries in the "One member of each cluster" '
        about += "tab. The plugin will allow a tester to get an overview of the tested website's responses from all tools (scanner, proxy, etc.). "
        about += "As similarity comparison "
        about += "can use a lot of ressources, only small, in-scope responses that have interesting response codes, "
        about += "file extensions and mime types are processed. "
        about += "</p>"
        about += "</html>"
        self.JLabel_about = JLabel(about)
        self.JLabel_about.setLayout(GridBagLayout())
        self._aboutJPanel = JScrollPane(self.JLabel_about)

        # customize our UI components
        callbacks.customizeUiComponent(self._splitpane)
        callbacks.customizeUiComponent(logTable)
        callbacks.customizeUiComponent(scrollPane)
        callbacks.customizeUiComponent(tabs)

        # add the splitpane and options to the main jtabedpane
        self._main_jtabedpane.addTab("One member of each cluster", None,
                                     self._splitpane, None)
        self._main_jtabedpane.addTab("Options", None, self._optionsJPanel,
                                     None)
        self._main_jtabedpane.addTab("About & README", None, self._aboutJPanel,
                                     None)

        # clusters will grow up to self.max_clusters response bodies...
        self._clusters = set()
        self.Similarity = Similarity()

        # Now load the already stored
        with self._lock:
            log_entries_from_storage = self.load_project_setting("log_entries")
            if log_entries_from_storage:
                for toolFlag, req, resp, url in log_entries_from_storage:
                    try:
                        self.add_new_log_entry(toolFlag, req, resp, url)
                    except Exception as e:
                        print "Exception when deserializing a stored log entry", toolFlag, url
                        print e

        # Important: Do this at the very end (otherwise we could run into troubles locking up entire threads)
        # add the custom tab to Burp's UI
        callbacks.addSuiteTab(self)

        # register ourselves as an HTTP listener
        callbacks.registerHttpListener(self)

    #
    # implement what happens when options are changed
    #

    def changedUpdate(self, document):
        pass

    def removeUpdate(self, document):
        self.actionPerformed(None)

    def insertUpdate(self, document):
        self.actionPerformed(None)

    def actionPerformed(self, actionEvent):
        self.use_quick_similar = self.JCheckBox_use_quick_similar.isSelected()
        try:
            self.max_clusters = int(self.JTextField_max_clusters.getText())
        except:
            self.JTextField_max_clusters.setText("200")

        try:
            self.similarity = float(self.JTextField_similarity.getText())
            if self.similarity > 1.0 or self.similarity < 0.0:
                self.JTextField_similarity.setText("0.9")
        except:
            self.JTextField_similarity.setText("0.9")

        try:
            self.response_max_size = float(
                self.JTextField_response_max_size.getText())
            if self.response_max_size < 0.0:
                self.JTextField_response_max_size.setText(str(10 * 1024))
        except:
            self.JTextField_response_max_size.setText(str(10 * 1024))

        print self.JCheckBox_use_quick_similar.isSelected(
        ), self.JTextField_max_clusters.getText(
        ), self.JTextField_similarity.getText(
        ), self.JTextField_response_max_size.getText()

    #
    # implement ITab
    #

    def getTabCaption(self):
        return "Response Clusterer"

    def getUiComponent(self):
        return self._main_jtabedpane

    #
    # implement IHttpListener
    #

    def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo):
        if not messageIsRequest:
            if len(self._clusters) >= self.max_clusters:
                return
            resp = messageInfo.getResponse()
            if len(resp) >= self.response_max_size:
                print "Message was too long"
                return
            iResponseInfo = self._helpers.analyzeResponse(resp)
            mime_type = iResponseInfo.getStatedMimeType()
            if mime_type in self.uninteresting_mime_types:
                print "Mime type", mime_type, "is ignored"
                return
            if iResponseInfo.getStatusCode(
            ) in self.uninteresting_status_codes:
                print "Status code", iResponseInfo.getStatusCode(
                ), "is ignored"
                return
            req = messageInfo.getRequest()
            iRequestInfo = self._helpers.analyzeRequest(messageInfo)
            if not iRequestInfo.getUrl():
                print "iRequestInfo.getUrl() returned None, so bailing out of analyzing this request"
                return
            if '.' in iRequestInfo.getUrl().getFile() and iRequestInfo.getUrl(
            ).getFile().split(
                    '.')[-1] in self.uninteresting_url_file_extensions:
                print iRequestInfo.getUrl().getFile().split(
                    '.')[-1], "is an ignored file extension"
                return
            if not self._callbacks.isInScope(iRequestInfo.getUrl()):
                print iRequestInfo.getUrl(), "is not in scope"
                return
            body = resp[iResponseInfo.getBodyOffset():]
            with self._lock:
                similarity_func = self.Similarity.similar
                if self.use_quick_similar:
                    similarity_func = self.Similarity.quick_similar
                start_time = time.time()
                for response_code, item in self._clusters:
                    if not response_code == iResponseInfo.getStatusCode():
                        #Different response codes -> different clusters
                        continue
                    if similarity_func(str(body), str(item), self.similarity):
                        return  #break
                else:  #when no break/return occures in the for loop
                    self.add_new_log_entry(toolFlag, req, resp,
                                           iRequestInfo.getUrl().toString())
                    self.save_project_setting("log_entries", self._log_entries)
                taken_time = time.time() - start_time
                if taken_time > 0.5:
                    print "Plugin took", taken_time, "seconds to process request... body length:", len(
                        body), "current cluster length:", len(self._clusters)
                    print "URL:", str(iRequestInfo.getUrl()),

    def add_new_log_entry(self, toolFlag, request, response, service_url):
        self._log_entries.append((toolFlag, request, response, service_url))
        iResponseInfo = self._helpers.analyzeResponse(response)
        body = response[iResponseInfo.getBodyOffset():]
        self._clusters.add((iResponseInfo.getStatusCode(), str(body)))
        row = self._log.size()
        service = CustomHttpService(service_url)
        r = CustomRequestResponse(None, None, service, request, response)
        iRequestInfo = self._helpers.analyzeRequest(r)
        self._log.add(
            LogEntry(toolFlag, self._callbacks.saveBuffersToTempFiles(r),
                     iRequestInfo.getUrl()))
        self.fireTableRowsInserted(row, row)

    #
    # extend AbstractTableModel
    #

    def getRowCount(self):
        try:
            return self._log.size()
        except:
            return 0

    def getColumnCount(self):
        return 2

    def getColumnName(self, columnIndex):
        if columnIndex == 0:
            return "Tool"
        if columnIndex == 1:
            return "URL"
        return ""

    def getValueAt(self, rowIndex, columnIndex):
        logEntry = self._log.get(rowIndex)
        if columnIndex == 0:
            return self._callbacks.getToolName(logEntry._tool)
        if columnIndex == 1:
            return logEntry._url.toString()
        return ""

    #
    # implement IMessageEditorController
    # this allows our request/response viewers to obtain details about the messages being displayed
    #

    def getHttpService(self):
        return self._currentlyDisplayedItem.getHttpService()

    def getRequest(self):
        return self._currentlyDisplayedItem.getRequest()

    def getResponse(self):
        return self._currentlyDisplayedItem.getResponse()

    def save_project_setting(self, name, value):
        value = pickle.dumps(value).encode("base64")
        request = "GET /"+name+" HTTP/1.0\r\n\r\n" \
                  "You can ignore this item in the site map. It was created by the ResponseClusterer extension. The \n" \
                  "reason is that the Burp API is missing a certain functionality to save settings. \n" \
                  "TODO Burp API limitation: This is a hackish way to be able to store project-scope settings.\n" \
                  "We don't want to restore requests/responses of tabs in a totally different Burp project.\n" \
                  "However, unfortunately there is no saveExtensionProjectSetting in the Burp API :(\n" \
                  "So we have to abuse the addToSiteMap API to store project-specific things\n" \
                  "Even when using this hack we currently cannot persist Collaborator interaction checks\n" \
                  "(IBurpCollaboratorClientContext is not serializable and Threads loose their Python class\n" \
                  "functionality when unloaded) due to Burp API limitations."
        response = None
        if value:
            response = "HTTP/1.1 200 OK\r\n" + value
        rr = CustomRequestResponse(
            name, '',
            CustomHttpService('http://responseclustererextension.local/'),
            request, response)
        self._callbacks.addToSiteMap(rr)

    def load_project_setting(self, name):
        rrs = self._callbacks.getSiteMap(
            'http://responseclustererextension.local/' + name)
        if rrs:
            rr = rrs[0]
            if rr.getResponse():
                val = "\r\n".join(
                    FloydsHelpers.jb2ps(rr.getResponse()).split("\r\n")[1:])
                return pickle.loads(val.decode("base64"))
            else:
                return None
        else:
            return None
Example #49
0
class MainPanel():
    """Represents the converted frame from NetBeans."""

    # default issue to populate the panel with
    defaultIssue = Issue(name="Name",
                         severity="Critical",
                         host="Host",
                         path="Path",
                         description="Description",
                         remediation="",
                         reqResp=RequestResponse(request="default request",
                                                 response="default response"))

    def loadPanel(self, issue):
        # type: (Issue) -> ()
        """Populates the panel with issue."""
        if issue is None:
            return

        # check if the input is the correct object
        assert isinstance(issue, Issue)

        # add selected issue to the panel to enable right-click stuff.
        self.selectedIssue = issue
        # set textfields and textareas
        self.textName.text = issue.name
        self.textHost.text = issue.host
        self.textPath.text = issue.path
        self.textAreaDescription.text = issue.description
        self.textAreaRemediation.text = issue.remediation
        self.textSeverity.text = issue.severity
        # request and response tabs
        self.panelRequest.setMessage(issue.getRequest(), True)
        self.panelResponse.setMessage(issue.getResponse(), False)

    # button actions
    def newIssueAction(self, event):
        """Pops up a frame to add a new issue."""
        frm = NewIssueDialog(callbacks=self.callbacks, title="New Issue")
        frm.display(self)

    def gotNewIssue(self, issue):
        """got a new issue."""
        self.tableIssue.addRow(issue)

    def editIssue(self, index, issue):
        """Issue has been edited."""
        self.tableIssue.editRow(index, issue)

    def deleteIssueAction(self, event):
        """Delete the currently selected issue."""
        # this is the button
        # btn = event.getSource()
        row = self.tableIssue.getTableSelectedRow()
        # YOLO
        self.tableIssue.deleteRow(row)
        # it works!

    def exportAction(self, event):
        """Export everything in the table to a file."""
        lastDir = ""
        try:
            # load the last used directory
            # this will probably change as we will use a base64 encoded json as the complete config?
            lastDir = self.callbacks.loadExtensionSetting("lastDir")
        except:
            # if there is not a last used directory in the settings, continue
            pass

        from Utils import saveFileDialog, writeFile
        selectedFile, usedDirectory = saveFileDialog(parent=self.panel,
                                                     startingDir=lastDir,
                                                     title="Export Issues",
                                                     extension="json")

        if selectedFile is not None:
            # write to the file
            writeFile(selectedFile.getAbsolutePath(),
                      self.tableIssue.exportIssues())

        if usedDirectory is not None:
            # overwrite the last used directory
            self.callbacks.saveExtensionSetting("lastDir", usedDirectory)

    def importAction(self, event):
        """Import a file to the table."""
        lastDir = ""
        try:
            # load the last used directory
            # this will probably change as we will use a base64 encoded json as the complete config?
            lastDir = self.callbacks.loadExtensionSetting("lastDir")
        except:
            # if there is not a last used directory in the settings, continue
            pass

        from Utils import openFileDialog
        selectedFile, usedDirectory = openFileDialog(parent=self.panel,
                                                     startingDir=lastDir,
                                                     title="Import Issues",
                                                     extension="json")

        # save the last directory
        self.callbacks.saveExtensionSetting("lastDir", usedDirectory)
        fi = open(selectedFile.getAbsolutePath(), "r")
        # read the file and create a list of Issues
        import json
        # newIssues = json.load(fi, object_hook=dictToIssue)
        # problem here is object_hook runs for every single object so newIssues
        # will have internal objects, even if we tag them

        from RequestResponse import RequestResponse, HttpService
        from base64 import b64decode
        issuesArray = json.load(fi)
        # now issuesArray is an array of dicts.
        # manual JSON deserialization - move this to a method/function?
        # also think about what happens if dictionaries are missing items
        newIssues = list()
        for eachissue in issuesArray:
            # now we have each issue
            # what if dictionaries are missing items?
            ht = HttpService(
                host=eachissue["reqResp"]["httpService"]["host"],
                port=eachissue["reqResp"]["httpService"]["port"],
                protocol=eachissue["reqResp"]["httpService"]["protocol"])
            rr = RequestResponse(
                request=b64decode(eachissue["reqResp"]["request"]),
                response=b64decode(eachissue["reqResp"]["response"]),
                comment=eachissue["reqResp"]["comment"],
                highlight=eachissue["reqResp"]["highlight"],
                httpService=ht)
            iss = Issue(name=eachissue["name"],
                        severity=eachissue["severity"],
                        host=eachissue["host"],
                        path=eachissue["path"],
                        description=eachissue["description"],
                        remediation=eachissue["remediation"],
                        reqResp=rr)

            # iss = Issue()
            # rr = RequestResponse()
            # ht = HttpService()
            newIssues.append(iss)

        # clear the table
        self.tableIssue.clear()
        # add the issues to the table
        # for iss in newIssues:
        #     self.tableIssue.addRow(iss)
        self.tableIssue.populate(newIssues)

    def newIssueFromBurp(self, invocation):
        """Create a New Issue from the context menu."""
        from Utils import getPath, bytesToString, burpToolName
        reqResp = invocation.getSelectedMessages()[0]
        host = str(reqResp.getHttpService())
        path = getPath(self.callbacks, reqResp)
        convertedReqResp = RequestResponse()
        convertedReqResp.fromIHttpRequestResponse(reqResp)
        tmpIssue = Issue(host=host, path=path, reqResp=convertedReqResp)
        # change the title to "New Issue from [TOOL]"?
        frameTitle = "New Issue from %s" % (burpToolName(
            invocation.getToolFlag()))
        frm = NewIssueDialog(callbacks=self.callbacks,
                             issue=tmpIssue,
                             title=frameTitle
                             #  , modality="application"
                             )
        frm.display(self)
        # FOCUS!
        frm.requestFocus()
        # print self.callbacks.getHelpers().bytesToString(reqResp[0].getRequest())

    # mostly converted generated code
    def __init__(self, callbacks, table=None):

        self.callbacks = callbacks
        self.jScrollPane1 = JScrollPane()
        self.jPanel1 = JPanel()
        self.labelName = JLabel("Name")
        self.textName = JTextField()
        self.labelSeverity = JLabel("Severity")
        self.textSeverity = JTextField()
        self.labelHost = JLabel("Host")
        self.labelPath = JLabel("Path")
        self.textHost = JTextField()
        self.textPath = JTextField()
        self.tabIssue = JTabbedPane()
        self.textAreaDescription = JTextArea()
        self.textAreaRemediation = JTextArea()
        # JScrollPanes to hold the two jTextAreas
        # put the textareas in JScrollPanes
        self.jsPaneDescription = JScrollPane(self.textAreaDescription)
        self.jsPaneRemediation = JScrollPane(self.textAreaRemediation)
        self.panelRequest = self.callbacks.createMessageEditor(None, False)
        self.panelResponse = self.callbacks.createMessageEditor(None, False)

        self.loadPanel(self.defaultIssue)

        # buttons
        self.buttonNewIssue = JButton("New Issue",
                                      actionPerformed=self.newIssueAction)
        self.buttonDeleteIssue = JButton(
            "Delete Issue", actionPerformed=self.deleteIssueAction)
        self.buttonImport = JButton("Import",
                                    actionPerformed=self.importAction)
        self.buttonExport = JButton("Export",
                                    actionPerformed=self.exportAction)

        if table is not None:
            self.tableIssue = table
        else:
            from IssueTable import IssueTable
            self.tableIssue = IssueTable()

        # wrap the table in a scrollpane
        self.jScrollPane1.setViewportView(self.tableIssue)

        # top panel containing the table
        from java.awt import Color
        self.jPanel1.setBorder(BorderFactory.createLineBorder(Color(0, 0, 0)))

        # create the labels and textfields
        self.textName.editable = False
        self.textName.setBackground(Color.LIGHT_GRAY)

        self.textSeverity.editable = False
        self.textSeverity.setBackground(Color.LIGHT_GRAY)

        self.textHost.editable = False
        self.textHost.setBackground(Color.LIGHT_GRAY)

        self.textPath.editable = False
        self.textPath.setBackground(Color.LIGHT_GRAY)

        # description textarea
        self.textAreaDescription.editable = False
        self.textAreaDescription.setLineWrap(True)
        self.textAreaDescription.setWrapStyleWord(True)
        self.tabIssue.addTab("Description", self.jsPaneDescription)

        # remediation textarea
        self.textAreaRemediation.editable = False
        self.textAreaRemediation.setLineWrap(True)
        self.textAreaRemediation.setWrapStyleWord(True)
        self.tabIssue.addTab("Remediation", self.jsPaneRemediation)

        # request tab
        self.panelRequest.setMessage("", True)
        self.tabIssue.addTab("Request", self.panelRequest.getComponent())

        # response tab
        self.panelResponse.setMessage("", False)
        self.tabIssue.addTab("Response", self.panelResponse.getComponent())

        # from java.lang import Short
        # jpanel1 is the bottom panel
        jPanel1Layout = GroupLayout(self.jPanel1)
        self.jPanel1.setLayout(jPanel1Layout)
        jPanel1Layout.setHorizontalGroup(
            # GroupLayout.Alignment.CENTER centers the group, in this case it
            # centers the buttons
            jPanel1Layout.createParallelGroup(
                GroupLayout.Alignment.CENTER
            ).addGroup(jPanel1Layout.createSequentialGroup().addContainerGap(
            ).addGroup(
                jPanel1Layout.createParallelGroup(
                    GroupLayout.Alignment.LEADING).
                addGroup(jPanel1Layout.createSequentialGroup().addGroup(
                    jPanel1Layout.createParallelGroup(
                        GroupLayout.Alignment.TRAILING).addComponent(
                            self.labelHost).addComponent(self.labelName)
                ).addPreferredGap(
                    LayoutStyle.ComponentPlacement.UNRELATED).addGroup(
                        jPanel1Layout.createParallelGroup(
                            GroupLayout.Alignment.LEADING).addGroup(
                                jPanel1Layout.createSequentialGroup(
                                ).addComponent(self.textName).addPreferredGap(
                                    LayoutStyle.ComponentPlacement.UNRELATED).
                                addComponent(
                                    self.labelSeverity).addPreferredGap(
                                        LayoutStyle.ComponentPlacement.
                                        RELATED).addComponent(
                                            self.textSeverity,
                                            GroupLayout.PREFERRED_SIZE, 186,
                                            GroupLayout.PREFERRED_SIZE)).
                        addGroup(
                            jPanel1Layout.createSequentialGroup().addComponent(
                                self.textHost, GroupLayout.PREFERRED_SIZE, 330,
                                GroupLayout.PREFERRED_SIZE).addPreferredGap(
                                    LayoutStyle.ComponentPlacement.RELATED
                                ).addComponent(self.labelPath).addPreferredGap(
                                    LayoutStyle.ComponentPlacement.RELATED).
                            addComponent(self.textPath)))).addComponent(
                                self.tabIssue)).addContainerGap()
                       ).addGroup(
                           jPanel1Layout.createSequentialGroup().addComponent(
                               self.buttonNewIssue).addComponent(
                                   self.buttonDeleteIssue).addComponent(
                                       self.buttonImport).addComponent(
                                           self.buttonExport)))

        # link size of buttons
        from javax.swing import SwingConstants
        jPanel1Layout.linkSize(SwingConstants.HORIZONTAL, [
            self.buttonDeleteIssue, self.buttonExport, self.buttonImport,
            self.buttonNewIssue
        ])

        jPanel1Layout.setVerticalGroup(jPanel1Layout.createParallelGroup(
        ).addGroup(
            jPanel1Layout.createSequentialGroup().addContainerGap().addGroup(
                jPanel1Layout.createParallelGroup(
                    GroupLayout.Alignment.BASELINE).addComponent(
                        self.labelName).addComponent(
                            self.textName, GroupLayout.PREFERRED_SIZE,
                            GroupLayout.DEFAULT_SIZE,
                            GroupLayout.PREFERRED_SIZE).addComponent(
                                self.labelSeverity).addComponent(
                                    self.textSeverity,
                                    GroupLayout.PREFERRED_SIZE,
                                    GroupLayout.DEFAULT_SIZE,
                                    GroupLayout.PREFERRED_SIZE)
            ).addPreferredGap(LayoutStyle.ComponentPlacement.RELATED).addGroup(
                jPanel1Layout.createParallelGroup(
                    GroupLayout.Alignment.BASELINE).addComponent(
                        self.textHost, GroupLayout.PREFERRED_SIZE,
                        GroupLayout.DEFAULT_SIZE,
                        GroupLayout.PREFERRED_SIZE).addComponent(
                            self.labelPath).addComponent(
                                self.textPath, GroupLayout.PREFERRED_SIZE,
                                GroupLayout.DEFAULT_SIZE,
                                GroupLayout.PREFERRED_SIZE).addComponent(
                                    self.labelHost)).addPreferredGap(
                                        LayoutStyle.ComponentPlacement.RELATED)
            .addComponent(self.tabIssue).addPreferredGap(
                LayoutStyle.ComponentPlacement.RELATED).addGroup(
                    jPanel1Layout.createParallelGroup().addComponent(
                        self.buttonNewIssue).addComponent(
                            self.buttonDeleteIssue).addComponent(
                                self.buttonImport).addComponent(
                                    self.buttonExport)).addContainerGap()))

        # create the main panel
        self.panel = JSplitPane(JSplitPane.VERTICAL_SPLIT)

        # set the top component
        self.panel.leftComponent = self.jScrollPane1
        self.panel.rightComponent = self.jPanel1
        self.panel.setDividerLocation(150)
    def registerExtenderCallbacks(self, callbacks):

        endianVal = 0

        def generateTextBox(defaultTxt, editable):
            sample = JTextArea(5, 20)
            scrollPane1 = JScrollPane(sample)
            sample.setBounds(0, 0, 400, 400)
            sample.setEditable(editable)
            sample.setLineWrap(True)
            sample.setWrapStyleWord(True)
            sample.setBorder(BorderFactory.createLineBorder(Color.BLACK))
            sample.setText(defaultTxt)

            return sample

        def decodeData(event):

            #Get Base64 token
            full_str = base64.b64decode(self._left_tb1.getText())

            sha_mac = full_str[44:64].encode('hex')
            inflate_data = full_str[76:]
            data = zlib.decompress(inflate_data)

            user_length = data[20]
            loc = 21
            tokenDetails = "User name :" + data[
                loc:loc + int(user_length.encode('hex'), 16)].replace(
                    "\x00", "") + "\n"
            loc = loc + int(user_length.encode('hex'), 16)
            lang_length = data[loc]
            loc = loc + 1

            tokenDetails += "Lang Code :" + data[
                loc:loc + int(lang_length.encode('hex'), 16)].replace(
                    "\x00", "") + "\n"
            tmp1.setText(data[loc:loc +
                              int(lang_length.encode('hex'), 16)].replace(
                                  "\x00", ""))
            loc = loc + int(lang_length.encode('hex'), 16)
            node_length = data[loc]
            loc = loc + 1

            tokenDetails += "Node name :" + data[
                loc:loc + int(node_length.encode('hex'), 16)].replace(
                    "\x00", "") + "\n"
            tmp2.setText(data[loc:loc +
                              int(node_length.encode('hex'), 16)].replace(
                                  "\x00", ""))
            loc = loc + int(node_length.encode('hex'), 16)
            time_length = data[loc]
            loc = loc + 1

            tokenDetails += "Creation time :" + data[
                loc:loc + int(time_length.encode('hex'), 16)].replace(
                    "\x00", "")

            tmp = data[loc:loc + int(time_length.encode('hex'), 16)].replace(
                "\x00", "")
            datestamp = tmp[:len(tmp) - 7]
            tmp3.setText(datestamp)
            # Determine if it's little or big endian
            if (data[4:8].encode('hex') == '04030201'):
                endianVal = 0
            else:
                endianVal = 1

            tmp4.setText(str(endianVal))
            hashcatFormat = sha_mac + ":" + data.encode("hex")

            left_tb2.setText(tokenDetails)
            left_tb3.setText(hashcatFormat)

        def make_field(part, size):
            part = chr(len(part) + size) + part
            return part

        def generateToken(event):

            newtoken = ""

            endianVal = int(tmp4.getText())

            if endianVal == 1:
                username = right_tb2.getText().encode('utf_16_be')
                nodepw = right_tb1.getText().encode('utf_16_le')
                lang = tmp1.getText().encode('utf_16_be')
                nodename = tmp2.getText().encode('utf_16_be')
                datestamp = (tmp3.getText() + '.164266').encode('utf_16_be')
                token_ver = "8.10".encode('utf_16_be')
                unknown_field = "N".encode('utf_16_be')

                uncompressed_data = '\x01\x02\x03\x04\x00\x01\x00\x00\x00\x00\x02\xbc\x00\x00\x00\x00' + make_field(
                    username, 0) + make_field(lang, 0) + make_field(
                        nodename, 0) + make_field(datestamp, 0) + '\x00'
                uncompressed_field = '\x00\x00\x00' + make_field(
                    uncompressed_data, 4)

                inflate_data = zlib.compress(uncompressed_field)

                sha1_mac = hashlib.sha1(uncompressed_field + nodepw).digest()

                uncompressed_length = chr(len(uncompressed_field))
                static_headers1 = '\x01\x02\x03\x04\x00\x01\x00\x00\x00\x00\x02\xbc\x00\x00\x00\x00\x00\x00\x00\x2c\x00\x04\x53\x68\x64\x72\x02' + unknown_field + uncompressed_length + '\x08' + token_ver + '\x14'
                static_headers2 = '\x00\x05\x53\x64\x61\x74\x61'
                body = '\x00\x00\x00' + make_field(
                    static_headers2 + make_field(inflate_data, 0), 4)
                token = '\x00\x00\x00' + make_field(
                    static_headers1 + sha1_mac + body, 4)

                newtoken = base64.b64encode(token)

            elif endianVal == 0:
                username = right_tb2.getText().encode('utf_16_le')
                nodepw = right_tb1.getText().encode('utf_16_le')
                lang = tmp1.getText().encode('utf_16_le')
                nodename = tmp2.getText().encode('utf_16_le')
                datestamp = (tmp3.getText() + '.999543').encode('utf_16_le')
                token_ver = "8.10".encode('utf_16_le')
                unknown_field = "N".encode('utf_16_le')

                uncompressed_data = '\x00\x00\x00\x04\x03\x02\x01\x01\x00\x00\x00\xbc\x02\x00\x00\x00\x00\x00\x00' + make_field(
                    username, 0) + make_field(lang, 0) + make_field(
                        nodename, 0) + make_field(datestamp, 0) + '\x00'
                uncompressed_field = make_field(uncompressed_data, 1)

                inflate_data = zlib.compress(uncompressed_field)

                sha1_mac = hashlib.sha1(uncompressed_field + nodepw).digest()

                uncompressed_length = chr(len(uncompressed_field))

                static_headers1 = '\x00\x00\x00\x04\x03\x02\x01\x01\x00\x00\x00\xbc\x02\x00\x00\x00\x00\x00\x00\x2c\x00\x00\x00\x04\x00\x53\x68\x64\x72\x02' + unknown_field + uncompressed_length + '\x08' + token_ver + '\x14'
                static_headers2 = '\x00\x00\x00\x05\x00\x53\x64\x61\x74\x61'
                body = make_field(
                    static_headers2 + make_field(inflate_data, 0), 1)
                token = make_field(static_headers1 + sha1_mac + body, 1)

                newtoken = base64.b64encode(token)

            right_tb3.setText("PS_TOKEN=" + newtoken + ";")

        # 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("PeopleSoft PSToken Processor")

        # main split pane
        self._splitpane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT)
        self._splitpane.setResizeWeight(0.5)

        c = GridBagConstraints()
        c.weightx = 1
        c.weighty = 1

        c.anchor = GridBagConstraints.NORTHWEST

        #Temp variables

        tmp1 = JLabel("tmp")
        tmp2 = JLabel("tmp")
        tmp3 = JLabel("tmp")
        tmp4 = JLabel("tmp")

        # add left panel
        panel1 = JPanel(GridBagLayout())
        header1 = JLabel("EXTRACTION")
        header1.setFont(Font("Myriad Pro", Font.BOLD, 24))

        left_t1 = JLabel("PS_TOKEN Cookie")
        left_t2 = JLabel("Token Details")
        left_t3 = JLabel("Token Hash + Salt (Hashcat Format)")
        left_t4 = JLabel(
            "Save this into a .hash file and run the following Hashcat command: hashcat -m 13500 <hashfile> <dictionary file>"
        )

        self._left_tb1 = generateTextBox("Your PS_TOKEN value here", True)
        left_tb2 = generateTextBox("Token Details here", False)
        left_tb3 = generateTextBox("Hashcat format here", False)

        btnDecode = JButton("Decode", actionPerformed=decodeData)
        btnGenerate = JButton("Generate", actionPerformed=generateToken)
        #add right panel
        panel2 = JPanel(GridBagLayout())
        header2 = JLabel("GENERATION")
        header2.setFont(Font("Myriad Pro", Font.BOLD, 24))

        right_t1 = JLabel("Node password")
        right_t2 = JLabel("New username")
        right_t3 = JLabel("New Base64 PS_TOKEN")
        right_t4 = JLabel(
            "Match & Replace rule to modify PS_TOKEN (Type: Request Header, enable regex)"
        )
        right_t5 = JLabel("Match rule: PS_TOKEN=[A-Za-z0-9\/\+]*;")
        right_t6 = JLabel("Replace: PS_TOKEN=<new generated PS_TOKEN>;")

        right_tb1 = generateTextBox("Password here", True)
        right_tb2 = generateTextBox("PSADMIN", True)
        right_tb3 = generateTextBox("Your new token here", False)

        panel1.add(header1, c)
        panel2.add(header2, c)

        c.gridx = 0
        c.gridy = 1
        panel1.add(left_t1, c)
        panel2.add(right_t1, c)
        c.gridy += 1
        panel1.add(self._left_tb1, c)
        panel2.add(right_tb1, c)

        c.gridy += 1
        panel1.add(left_t2, c)
        panel2.add(right_t2, c)
        c.gridy += 1
        panel1.add(left_tb2, c)
        panel2.add(right_tb2, c)

        c.gridy += 1
        panel1.add(left_t3, c)
        panel2.add(right_t3, c)
        c.gridy += 1
        panel1.add(left_t4, c)
        panel2.add(right_t4, c)
        c.gridy += 1
        panel1.add(left_tb3, c)
        panel2.add(right_t5, c)
        c.gridy += 1
        panel2.add(right_t6, c)
        c.gridy += 1
        panel2.add(right_tb3, c)
        c.gridy += 1
        panel1.add(btnDecode, c)
        panel2.add(btnGenerate, c)

        self._splitpane.setLeftComponent(panel1)
        self._splitpane.setRightComponent(panel2)

        # customize our UI components
        callbacks.customizeUiComponent(self._splitpane)
        #callbacks.customizeUiComponent(panel1)
        #callbacks.customizeUiComponent(scrollPane)

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

        #add option to do right-click
        callbacks.registerContextMenuFactory(self)

        return
Example #51
0
    def __init__(self, callbacks, table=None):

        self.callbacks = callbacks
        self.jScrollPane1 = JScrollPane()
        self.jPanel1 = JPanel()
        self.labelName = JLabel("Name")
        self.textName = JTextField()
        self.labelSeverity = JLabel("Severity")
        self.textSeverity = JTextField()
        self.labelHost = JLabel("Host")
        self.labelPath = JLabel("Path")
        self.textHost = JTextField()
        self.textPath = JTextField()
        self.tabIssue = JTabbedPane()
        self.textAreaDescription = JTextArea()
        self.textAreaRemediation = JTextArea()
        # JScrollPanes to hold the two jTextAreas
        # put the textareas in JScrollPanes
        self.jsPaneDescription = JScrollPane(self.textAreaDescription)
        self.jsPaneRemediation = JScrollPane(self.textAreaRemediation)
        self.panelRequest = self.callbacks.createMessageEditor(None, False)
        self.panelResponse = self.callbacks.createMessageEditor(None, False)

        self.loadPanel(self.defaultIssue)

        # buttons
        self.buttonNewIssue = JButton("New Issue",
                                      actionPerformed=self.newIssueAction)
        self.buttonDeleteIssue = JButton(
            "Delete Issue", actionPerformed=self.deleteIssueAction)
        self.buttonImport = JButton("Import",
                                    actionPerformed=self.importAction)
        self.buttonExport = JButton("Export",
                                    actionPerformed=self.exportAction)

        if table is not None:
            self.tableIssue = table
        else:
            from IssueTable import IssueTable
            self.tableIssue = IssueTable()

        # wrap the table in a scrollpane
        self.jScrollPane1.setViewportView(self.tableIssue)

        # top panel containing the table
        from java.awt import Color
        self.jPanel1.setBorder(BorderFactory.createLineBorder(Color(0, 0, 0)))

        # create the labels and textfields
        self.textName.editable = False
        self.textName.setBackground(Color.LIGHT_GRAY)

        self.textSeverity.editable = False
        self.textSeverity.setBackground(Color.LIGHT_GRAY)

        self.textHost.editable = False
        self.textHost.setBackground(Color.LIGHT_GRAY)

        self.textPath.editable = False
        self.textPath.setBackground(Color.LIGHT_GRAY)

        # description textarea
        self.textAreaDescription.editable = False
        self.textAreaDescription.setLineWrap(True)
        self.textAreaDescription.setWrapStyleWord(True)
        self.tabIssue.addTab("Description", self.jsPaneDescription)

        # remediation textarea
        self.textAreaRemediation.editable = False
        self.textAreaRemediation.setLineWrap(True)
        self.textAreaRemediation.setWrapStyleWord(True)
        self.tabIssue.addTab("Remediation", self.jsPaneRemediation)

        # request tab
        self.panelRequest.setMessage("", True)
        self.tabIssue.addTab("Request", self.panelRequest.getComponent())

        # response tab
        self.panelResponse.setMessage("", False)
        self.tabIssue.addTab("Response", self.panelResponse.getComponent())

        # from java.lang import Short
        # jpanel1 is the bottom panel
        jPanel1Layout = GroupLayout(self.jPanel1)
        self.jPanel1.setLayout(jPanel1Layout)
        jPanel1Layout.setHorizontalGroup(
            # GroupLayout.Alignment.CENTER centers the group, in this case it
            # centers the buttons
            jPanel1Layout.createParallelGroup(
                GroupLayout.Alignment.CENTER
            ).addGroup(jPanel1Layout.createSequentialGroup().addContainerGap(
            ).addGroup(
                jPanel1Layout.createParallelGroup(
                    GroupLayout.Alignment.LEADING).
                addGroup(jPanel1Layout.createSequentialGroup().addGroup(
                    jPanel1Layout.createParallelGroup(
                        GroupLayout.Alignment.TRAILING).addComponent(
                            self.labelHost).addComponent(self.labelName)
                ).addPreferredGap(
                    LayoutStyle.ComponentPlacement.UNRELATED).addGroup(
                        jPanel1Layout.createParallelGroup(
                            GroupLayout.Alignment.LEADING).addGroup(
                                jPanel1Layout.createSequentialGroup(
                                ).addComponent(self.textName).addPreferredGap(
                                    LayoutStyle.ComponentPlacement.UNRELATED).
                                addComponent(
                                    self.labelSeverity).addPreferredGap(
                                        LayoutStyle.ComponentPlacement.
                                        RELATED).addComponent(
                                            self.textSeverity,
                                            GroupLayout.PREFERRED_SIZE, 186,
                                            GroupLayout.PREFERRED_SIZE)).
                        addGroup(
                            jPanel1Layout.createSequentialGroup().addComponent(
                                self.textHost, GroupLayout.PREFERRED_SIZE, 330,
                                GroupLayout.PREFERRED_SIZE).addPreferredGap(
                                    LayoutStyle.ComponentPlacement.RELATED
                                ).addComponent(self.labelPath).addPreferredGap(
                                    LayoutStyle.ComponentPlacement.RELATED).
                            addComponent(self.textPath)))).addComponent(
                                self.tabIssue)).addContainerGap()
                       ).addGroup(
                           jPanel1Layout.createSequentialGroup().addComponent(
                               self.buttonNewIssue).addComponent(
                                   self.buttonDeleteIssue).addComponent(
                                       self.buttonImport).addComponent(
                                           self.buttonExport)))

        # link size of buttons
        from javax.swing import SwingConstants
        jPanel1Layout.linkSize(SwingConstants.HORIZONTAL, [
            self.buttonDeleteIssue, self.buttonExport, self.buttonImport,
            self.buttonNewIssue
        ])

        jPanel1Layout.setVerticalGroup(jPanel1Layout.createParallelGroup(
        ).addGroup(
            jPanel1Layout.createSequentialGroup().addContainerGap().addGroup(
                jPanel1Layout.createParallelGroup(
                    GroupLayout.Alignment.BASELINE).addComponent(
                        self.labelName).addComponent(
                            self.textName, GroupLayout.PREFERRED_SIZE,
                            GroupLayout.DEFAULT_SIZE,
                            GroupLayout.PREFERRED_SIZE).addComponent(
                                self.labelSeverity).addComponent(
                                    self.textSeverity,
                                    GroupLayout.PREFERRED_SIZE,
                                    GroupLayout.DEFAULT_SIZE,
                                    GroupLayout.PREFERRED_SIZE)
            ).addPreferredGap(LayoutStyle.ComponentPlacement.RELATED).addGroup(
                jPanel1Layout.createParallelGroup(
                    GroupLayout.Alignment.BASELINE).addComponent(
                        self.textHost, GroupLayout.PREFERRED_SIZE,
                        GroupLayout.DEFAULT_SIZE,
                        GroupLayout.PREFERRED_SIZE).addComponent(
                            self.labelPath).addComponent(
                                self.textPath, GroupLayout.PREFERRED_SIZE,
                                GroupLayout.DEFAULT_SIZE,
                                GroupLayout.PREFERRED_SIZE).addComponent(
                                    self.labelHost)).addPreferredGap(
                                        LayoutStyle.ComponentPlacement.RELATED)
            .addComponent(self.tabIssue).addPreferredGap(
                LayoutStyle.ComponentPlacement.RELATED).addGroup(
                    jPanel1Layout.createParallelGroup().addComponent(
                        self.buttonNewIssue).addComponent(
                            self.buttonDeleteIssue).addComponent(
                                self.buttonImport).addComponent(
                                    self.buttonExport)).addContainerGap()))

        # create the main panel
        self.panel = JSplitPane(JSplitPane.VERTICAL_SPLIT)

        # set the top component
        self.panel.leftComponent = self.jScrollPane1
        self.panel.rightComponent = self.jPanel1
        self.panel.setDividerLocation(150)
Example #52
0
    def registerExtenderCallbacks(self, callbacks):

        # Set encoding to utf-8 to avoid some errors
        reload(sys)
        sys.setdefaultencoding('utf8')

        # Keep a reference to callback object and helper object
        self._callbacks = callbacks
        self._helpers = callbacks.getHelpers()

        # Set the extension name that shows in the burp extension menu
        callbacks.setExtensionName("InjectionScanner")

        # Create the log and a lock on which to synchronize when adding log entries
        self._log = ArrayList()
        self._logLock = Lock()
        self._httpLock = Lock()

        # The length of the basis used to fetch abnormal data, default to zero
        self._basisLen = 0

        # 1: {POST. GET}; 2: {urlencoded, json, xml}
        self._postGet = 'NaN'
        self._dataType = 'NaN'

        # Scan list
        self._simpleList = [
            '\'', '\"', '/', '/*', '#', ')', '(', ')\'', '(\'', 'and 1=1',
            'and 1=2', 'and 1>2', 'and 12', '+', 'and+12', '/**/and/**/1'
        ]
        self._xmlList = ['a', 'b', 'c', 'd', 'e']  # Not setted

        # Response mutex: True = is blocking; False = free to go
        # self._mutexR = False

        # Other classes instance
        self._dataTable = Guis_DefaultTM()
        self._logTable = Guis_AbstractTM(self)
        self._xh = XMLHandler()
        listeners = Guis_Listeners(self, self._logTable)
        '''
        Setting GUIs
        '''
        # Divide the whole pane two: one upper and one lower pane
        self._mainSplitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT)
        self._mainSplitpane.setResizeWeight(0.4)

        # Initizlize request table
        dataTable = JTable(self._dataTable)
        dataScrollPane = JScrollPane(dataTable)
        dataScrollPane.setPreferredSize(Dimension(0, 125))
        self._dataTable.addTableModelListener(listeners)

        # Initialize log table
        logTable = Guis_LogTable(self._logTable)
        logScrollPane = JScrollPane(logTable)
        logScrollPane.setPreferredSize(Dimension(0, 125))

        # Split the upper pane to two panes
        tableSplitpane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT)
        tableSplitpane.setResizeWeight(0.5)

        # Set the data table to the left and log to the right
        tableSplitpane.setLeftComponent(dataScrollPane)
        tableSplitpane.setRightComponent(logScrollPane)

        # Tabs with request/response viewers
        tabs = JTabbedPane()
        self._requestViewer = callbacks.createMessageEditor(self, False)
        self._responseViewer = callbacks.createMessageEditor(self, False)
        tabs.addTab("Request", self._requestViewer.getComponent())
        tabs.addTab("Response", self._responseViewer.getComponent())

        # Create buttons that do operation with the test
        self._basisLabel = JLabel('Basis: ' + str(self._basisLen))
        self._levelLabel = JLabel('Level:')
        self._setBasisButton = JButton('Set Basis')
        self._hitOnceButton = JButton('Hit Once')
        self._autoScanButton = JButton('Auto Scan')
        self._clearLogButton = JButton('Clear Log')
        self._cancelButton = JButton('Cancel')
        self._levelSelection = JComboBox()

        self._levelSelection.addItem('1')
        self._levelSelection.addItem('2')
        self._levelSelection.addItem('3')
        self._hitOnceButton.addActionListener(listeners)
        self._autoScanButton.addActionListener(listeners)
        self._clearLogButton.addActionListener(listeners)
        self._setBasisButton.addActionListener(listeners)
        self._cancelButton.addActionListener(listeners)
        self._basisLabel.setPreferredSize(Dimension(100, 20))

        # Create bottom pane for holding the buttons
        buttonPane = JPanel()
        buttonPane.setLayout(BorderLayout())
        centerPane = JPanel()
        leftPane = JPanel()
        rightPane = JPanel()
        leftPane.add(self._basisLabel)
        centerPane.add(self._setBasisButton)
        centerPane.add(self._hitOnceButton)
        centerPane.add(self._autoScanButton)
        centerPane.add(self._cancelButton)
        centerPane.add(self._clearLogButton)
        rightPane.add(self._levelLabel)
        rightPane.add(self._levelSelection)
        buttonPane.add(centerPane, BorderLayout.CENTER)
        buttonPane.add(leftPane, BorderLayout.WEST)
        buttonPane.add(rightPane, BorderLayout.EAST)

        # Create and set the bottom panel that holds viewers and buttons
        utilPane = JPanel()
        utilPane.setLayout(BorderLayout())
        utilPane.add(tabs, BorderLayout.CENTER)
        utilPane.add(buttonPane, BorderLayout.SOUTH)

        self._mainSplitpane.setLeftComponent(tableSplitpane)
        self._mainSplitpane.setRightComponent(utilPane)

        # Customize UI components
        callbacks.customizeUiComponent(self._mainSplitpane)
        callbacks.customizeUiComponent(dataTable)
        callbacks.customizeUiComponent(dataScrollPane)
        callbacks.customizeUiComponent(logTable)
        callbacks.customizeUiComponent(logScrollPane)
        callbacks.customizeUiComponent(tabs)
        callbacks.customizeUiComponent(buttonPane)
        callbacks.customizeUiComponent(utilPane)
        callbacks.customizeUiComponent(self._basisLabel)
        callbacks.customizeUiComponent(self._setBasisButton)
        callbacks.customizeUiComponent(self._hitOnceButton)
        callbacks.customizeUiComponent(self._autoScanButton)
        callbacks.customizeUiComponent(self._clearLogButton)
        callbacks.customizeUiComponent(self._levelSelection)
        callbacks.customizeUiComponent(self._cancelButton)

        # Add the custom tab to Burp's UI
        callbacks.addSuiteTab(self)

        # Register the context menu and message editor for new tabs
        callbacks.registerContextMenuFactory(self)

        # Register as a HTTP listener
        callbacks.registerHttpListener(self)

        return
Example #53
0
class BurpExtender(IBurpExtender, IContextMenuFactory, ITab, IHttpListener,
                   IMessageEditorController, AbstractTableModel):
    def registerExtenderCallbacks(self, callbacks):
        # keep a reference to our callbacks object
        self._callbacks = callbacks
        # obtain an extension helpers object
        self._helpers = callbacks.getHelpers()

        #setup the extension
        callbacks.setExtensionName('ExampleExtension')

        # main split pane
        self._splitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT)

        # table of log entries
        logTable = Table(self)
        scrollPane = JScrollPane(logTable)
        self._splitpane.setLeftComponent(scrollPane)
        # Setup the tab for the results
        tabs = JTabbedPane()
        linkResults_tab = self.set_linkResults_tab(functionality_name,
                                                   test_name)
        self._resultsViewer = callbacks.createMessageEditor(self, False)
        tabs.addTab("Results", linkResults_tab)
        self._splitpane.setRightComponent(tabs)

        stdout = PrintWriter(callbacks.getStdout(), True)
        stderr = PrintWriter(callbacks.getStderr(), True)

        #callbacks.registerScannerCheck(self)
        callbacks.registerContextMenuFactory(self)

        # customize our UI components
        callbacks.customizeUiComponent(self._splitpane)
        callbacks.customizeUiComponent(logTable)
        callbacks.customizeUiComponent(scrollPane)
        callbacks.customizeUiComponent(tabs)

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

        return

    def getTabCaption(self):
        return 'BurpExtension'

    def getUiComponent(self):
        return self._splitpane

    def createMenuItems(self, invocation):
        self.context = invocation
        menu_list = ArrayList()
        menu_list.add(
            JMenuItem("Send to BurpExtension", actionPerformed=self.scanItem))
        return menu_list

    def scanItem(self, event):
        # Regex used

        httpTraffic = self.context.getSelectedMessages()

        validTraffic = []
        self.paramlist = []
        hostUrls = []

        #Only test JS files.
        for traffic in httpTraffic:
            try:
                url = str(traffic.getUrl())
                if ".js" in url:
                    print 'Valid url: '
                    print url + '\n'
                    hostUrls.append(str(traffic.getUrl()))
                    validTraffic.append(traffic)

            except UnicodeEncodeError:
                continue

    def consolidateDuplicateIssues(self, isb, isa):
        if Arrays.equals(isb.getHttpMessages()[0].getResponse(),
                         isa.getHttpMessages()[0].getResponse()):
            return -1
        else:
            return 0

    #
    # extend AbstractTableModel
    #

    def getRowCount(self):
        try:
            return self._log.size()
        except:
            return 0

    def getColumnCount(self):
        return 1

    def getColumnName(self, columnIndex):
        if columnIndex == 0:
            return "URL"
        return ""

    def getValueAt(self, rowIndex, columnIndex):
        logEntry = self._log.get(rowIndex)
        if columnIndex == 0:
            return logEntry._url.toString()
        return ""

    def set_linkResults_tab(self, fn, vn):
        resource_text = ""

        for url in resource_urls:
            resource_text = resource_text + str(url) + "\n"

        resource_textarea = JTextArea()
        resource_textarea.setLineWrap(True)
        resource_textarea.setWrapStyleWord(True)
        resource_textarea.setText(resource_text)
        resources_panel = JScrollPane(resource_textarea)

        return resources_panel
Example #54
0
class BurpExtender(IBurpExtender, IContextMenuFactory, ITab, ComponentListener,
                   ActionListener, MouseAdapter):
    # contains the messages to show in the messages table
    _table_data = []

    # contains the messages to translate
    _messages = []

    # used to keep track when to refresh the table
    _reload_table = False

    _sql_file = None

    def registerExtenderCallbacks(self, callbacks):

        self._panel = JPanel()
        self._panel.setLayout(BorderLayout())
        #self._panel.setSize(400,400)

        # sourrounding try\except because Burp is not giving enough info
        try:

            # creating all the UI elements
            # create the split pane
            self._split_pane_horizontal = JSplitPane(
                JSplitPane.HORIZONTAL_SPLIT)
            self._split_panel_vertical = JSplitPane(JSplitPane.VERTICAL_SPLIT)

            # create panels
            self._panel_top = JPanel()
            self._panel_top.setLayout(BorderLayout())
            self._panel_bottom = JPanel()
            self._panel_bottom.setLayout(BorderLayout())
            self._panel_right = JPanel()
            self._panel_right.setLayout(BorderLayout())
            self._panel_request = JPanel()
            self._panel_request.setLayout(BorderLayout())
            self._panel_response = JPanel()
            self._panel_response.setLayout(BorderLayout())

            # create the tabbed pane used to show request\response
            self._tabbed_pane = JTabbedPane(JTabbedPane.TOP)

            # create the tabbed pane used to show aslan++\concretization file
            self._tabbed_pane_editor = JTabbedPane(JTabbedPane.TOP)

            # create the bottom command for selecting the SQL file and
            # generating the model
            self._button_generate = JButton(
                'Generate!', actionPerformed=self._generate_model)
            self._button_save = JButton('Save',
                                        actionPerformed=self._save_model)
            self._button_select_sql = JButton(
                'Select SQL', actionPerformed=self._select_sql_file)
            self._text_field_sql_file = JTextField(20)

            self._panel_bottom_commands = JPanel()
            layout = GroupLayout(self._panel_bottom_commands)
            layout.setAutoCreateGaps(True)
            layout.setAutoCreateContainerGaps(True)
            seq_layout = layout.createSequentialGroup()
            seq_layout.addComponent(self._text_field_sql_file)
            seq_layout.addComponent(self._button_select_sql)
            seq_layout.addComponent(self._button_generate)
            seq_layout.addComponent(self._button_save)
            layout.setHorizontalGroup(seq_layout)

            # create the message editors that will be used to show request and response
            self._message_editor_request = callbacks.createMessageEditor(
                None, True)
            self._message_editor_response = callbacks.createMessageEditor(
                None, True)

            # create the table that will be used to show the messages selected for
            # the translation

            self._columns_names = ('Host', 'Method', 'URL')
            dataModel = NonEditableModel(self._table_data, self._columns_names)
            self._table = JTable(dataModel)
            self._scrollPane = JScrollPane()
            self._scrollPane.getViewport().setView((self._table))

            popmenu = JPopupMenu()
            delete_item = JMenuItem("Delete")
            delete_item.addActionListener(self)
            popmenu.add(delete_item)
            self._table.setComponentPopupMenu(popmenu)
            self._table.addMouseListener(self)

            # add all the elements
            self._panel_request.add(
                self._message_editor_request.getComponent())
            self._panel_response.add(
                self._message_editor_response.getComponent())

            self._tabbed_pane.addTab("Request", self._panel_request)
            self._tabbed_pane.addTab("Response", self._panel_response)

            self._panel_top.add(self._scrollPane, BorderLayout.CENTER)

            self._panel_bottom.add(self._tabbed_pane, BorderLayout.CENTER)
            scroll = JScrollPane(self._panel_bottom)

            self._panel_right.add(self._tabbed_pane_editor,
                                  BorderLayout.CENTER)
            self._panel_right.add(self._panel_bottom_commands,
                                  BorderLayout.PAGE_END)

            self._split_panel_vertical.setTopComponent(self._panel_top)
            self._split_panel_vertical.setBottomComponent(scroll)
            self._split_pane_horizontal.setLeftComponent(
                self._split_panel_vertical)
            self._split_pane_horizontal.setRightComponent(self._panel_right)

            self._panel.addComponentListener(self)
            self._panel.add(self._split_pane_horizontal)

            self._callbacks = callbacks
            callbacks.setExtensionName("WAFEx")
            callbacks.addSuiteTab(self)
            callbacks.registerContextMenuFactory(self)
        except Exception as e:
            exc_type, exc_obj, exc_tb = sys.exc_info()
            fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
            print(exc_type, fname, exc_tb.tb_lineno)

    def getTabCaption(self):
        return "WAFEx"

    def getUiComponent(self):
        try:
            Platform.runLater(EditorTabUI(self))
            return self._panel
        except Exception as e:
            exc_type, exc_obj, exc_tb = sys.exc_info()
            fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
            print(exc_type, fname, exc_tb.tb_lineno)

    def componentShown(self, e):
        self._split_pane_horizontal.setDividerLocation(0.25)
        # populate the table with the selected requests\response
        try:
            if self._reload_table:
                print("reload")
                self._table_data = [
                ]  # empty _table_data (not too cool but quick)
                for c in self._messages:
                    msg = c[0]
                    http_request = converter._byte_array_to_string(
                        msg.getRequest())
                    request_parser = HttpParser()
                    request_parser.execute(http_request, len(http_request))

                    host = msg.getHttpService().getHost()
                    page = request_parser.get_url()
                    method = request_parser.get_method()

                    tmp = [host, method, page]
                    self._table_data += [tmp]
                self._table.getModel().setDataVector(self._table_data,
                                                     self._columns_names)
                self._reload_table = False
        except Exception as e:
            print(e)

    def componentHidden(self, e):
        return

    def componentMoved(self, e):
        return

    def componentResized(self, e):
        self._split_pane_horizontal.setDividerLocation(0.25)

    def createMenuItems(self, invocation):
        ret = []
        try:
            if (invocation.getInvocationContext() ==
                    invocation.CONTEXT_TARGET_SITE_MAP_TABLE):
                menu = JMenuItem("Send to WAFEx")
                messages = invocation.getSelectedMessages()

                def listener(e):
                    """ Generates a new WAFEx model. """
                    #self._generateWAFExModel(messages)
                    self._addToGeneration(messages)

                menu.addActionListener(listener)
                ret.append(menu)
        except Exception as e:
            print(e)
        return ret

    def mouseClicked(self, e):
        """ Positions the Aslan++ editor to the selected request position. """
        try:
            index = self._table.getSelectedRow()
            c = self._messages[index]
            print(len(c))
            message = c[0]
            tag = c[1]
            self._message_editor_request.setMessage(message.getRequest(), True)
            self._message_editor_response.setMessage(message.getResponse(),
                                                     False)
            if tag != None:
                document = self._jfxp_aslanpp._editor.getText()
                start, end = self._search_tag_position(tag, document)
                self._jfxp_aslanpp._editor.moveTo(start)
                self._jfxp_aslanpp._editor.selectRange(start, end)
                self._jfxp_aslanpp._editor.requestFollowCaret()
                self._jfxp_aslanpp._editor.requestFocus()
        except Exception as e:
            print(e)

    def actionPerformed(self, e):
        """ Performs the delete action. """
        try:
            index = self._table.getSelectedRow()
            del self._table_data[index]
            del self._messages[index]
            self._table.getModel().setDataVector(self._table_data,
                                                 self._columns_names)
        except Exception as e:
            print(e)

    def _search_tag_position(self, tag, text):
        """ Searches for a particular tag in a given text and return its position. """
        pattern = self._search_pattern.format(tag)
        for m in re.finditer(pattern, text):
            return m.start(), m.end()

    def _save_model(self, e):
        """ Saves the current Aslan++ model and concretization file. """
        try:
            chooseFile = JFileChooser()
            filter_ = FileNameExtensionFilter("txt files", ["txt"])
            chooseFile.addChoosableFileFilter(filter_)

            ret = chooseFile.showDialog(self._panel, "Choose file")

            if ret == JFileChooser.APPROVE_OPTION:
                self._model_name = chooseFile.getSelectedFile().getPath()
                with open("{}.aslan++".format(self._model_name), "w") as f:
                    skeleton = self._jfxp_aslanpp._editor.getText()
                    skeleton = skeleton.replace("@filename",
                                                basename(self._model_name))
                    f.write(skeleton)
                print("model created")

                with open("{}.txt".format(self._model_name), "w") as f:
                    f.write(self._jfxp_concretization._editor.getText())

        except Exception as e:
            print(e)

    def _select_sql_file(self, e):
        """ Shows a JFileChooser dialog to select the SQL file to use for creating
        the model. """
        try:
            chooseFile = JFileChooser()
            filter_ = FileNameExtensionFilter("txt files", ["txt"])
            chooseFile.addChoosableFileFilter(filter_)

            ret = chooseFile.showDialog(self._panel, "Choose file")

            if ret == JFileChooser.APPROVE_OPTION:
                self._sql_file = chooseFile.getSelectedFile().getPath()
            else:
                self._sql_file = None
            self._text_field_sql_file.setText("" + self._sql_file)
        except Exception as e:
            print(e)

    def _addToGeneration(self, messages):
        for msg in messages:
            self._messages += [[msg, None]]
        self._reload_table = True

    def _generate_model(self, e):
        if len(self._messages) <= 0:
            frame = JFrame("Error")
            JOptionPane.showMessageDialog(frame, "No messages!", "Error",
                                          JOptionPane.ERROR_MESSAGE)
            return
        if self._sql_file == None:
            frame = JFrame("Error")
            replay = JOptionPane.showConfirmDialog(
                frame, "No SQL file selected!\nDo you want to continue?",
                "Info", JOptionPane.YES_NO_OPTION)
            if replay == JOptionPane.NO_OPTION:
                return

        # create a new AslanppModel
        model = AslanppModel()
        # save _sql_file
        model._sql_file = self._sql_file

        for c in self._messages:
            # from byte to char Request and Response
            # for some reason b can be a negative value causing a crash
            # so I put a check to ensure b is in the right range
            msg = c[0]
            if msg.getRequest() == None or msg.getResponse() == None:
                # do not convert empty messages
                continue
            http_request = "".join(
                chr(b) for b in msg.getRequest() if b >= 0 and b <= 256)
            http_response = "".join(
                chr(b) for b in msg.getResponse() if b >= 0 and b <= 256)
            protocol = msg.getHttpService().getProtocol()
            # save the tag number generate by _parseHttpRequestResponse in the _messages array
            c[1] = converter._parseHttpRequestResponse(model, http_request,
                                                       http_response, protocol)

        # generate the ASLan++ code
        self._model, self._concrete = converter._generateWAFExModel(model)
        Platform.runLater(
            UpdateEditor(self._jfxp_aslanpp._editor,
                         self._jfxp_concretization._editor, self._model,
                         self._concrete))
Example #55
0
class BurpExtender(IBurpExtender, ITab, IHttpListener, IMessageEditorController, AbstractTableModel):
    
    #
    # implement IBurpExtender
    #
    
    def	registerExtenderCallbacks(self, callbacks):
    
        # 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("Otter")
        
        # create the log and a lock on which to synchronize when adding log entries
        self._log = ArrayList()
        self._lock = Lock()
       
        # main split pane for log entries and request/response viewing
        self._settingPanel = JPanel()
        self._logPane = JSplitPane(JSplitPane.VERTICAL_SPLIT)

        # setup settings pane ui
        self._settingPanel.setBounds(0,0,1000,1000)
        self._settingPanel.setLayout(None)

        self._isRegexp = JCheckBox("Use regexp for matching.")
        self._isRegexp.setBounds(10, 10, 220, 20)

        matchLabel = JLabel("String to Match:")
        matchLabel.setBounds(10, 40, 200, 20)
        self._matchString = JTextArea("User 1 Session Information")
        self._matchString.setWrapStyleWord(True)
        self._matchString.setLineWrap(True)
        matchString = JScrollPane(self._matchString)
        matchString.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED)
        matchString.setBounds(10, 60, 400, 200)

        replaceLabel = JLabel("String to Replace:")
        replaceLabel.setBounds(10, 270, 200, 20)
        self._replaceString = JTextArea("User 2 Session Information")
        self._replaceString.setWrapStyleWord(True)
        self._replaceString.setLineWrap(True)
        replaceString = JScrollPane(self._replaceString)
        replaceString.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED)
        replaceString.setBounds(10, 290, 400, 200)

        self._settingPanel.add(self._isRegexp)
        self._settingPanel.add(matchLabel)
        self._settingPanel.add(matchString)
        self._settingPanel.add(replaceLabel)
        self._settingPanel.add(replaceString)
        
        # table of log entries
        logTable = Table(self)
        logTable.getColumnModel().getColumn(0).setPreferredWidth(700)
        logTable.getColumnModel().getColumn(1).setPreferredWidth(150)
        logTable.getColumnModel().getColumn(2).setPreferredWidth(100)
        logTable.getColumnModel().getColumn(3).setPreferredWidth(130)
        logTable.getColumnModel().getColumn(4).setPreferredWidth(100)
        logTable.getColumnModel().getColumn(5).setPreferredWidth(130)
        scrollPane = JScrollPane(logTable)
        self._logPane.setLeftComponent(scrollPane)

        # tabs with request/response viewers
        logTabs = JTabbedPane()
        self._origRequestViewer = callbacks.createMessageEditor(self, False)
        self._origResponseViewer = callbacks.createMessageEditor(self, False)
        self._modRequestViewer = callbacks.createMessageEditor(self, False)
        self._modResponseViewer = callbacks.createMessageEditor(self, False)
        logTabs.addTab("Original Request", self._origRequestViewer.getComponent())
        logTabs.addTab("Original Response", self._origResponseViewer.getComponent())
        logTabs.addTab("Modified Request", self._modRequestViewer.getComponent())
        logTabs.addTab("Modified Response", self._modResponseViewer.getComponent())
        self._logPane.setRightComponent(logTabs)
        
        # top most tab interface that seperates log entries from settings
        maintabs = JTabbedPane()
        maintabs.addTab("Log Entries", self._logPane)
        maintabs.addTab("Settings", self._settingPanel)
        self._maintabs = maintabs
       
        # customize the UI components
        callbacks.customizeUiComponent(maintabs)
        
        # add the custom tab to Burp's UI
        callbacks.addSuiteTab(self)
        
        # register ourselves as an HTTP listener
        callbacks.registerHttpListener(self)
        
        return
        
    #
    # implement ITab
    #
    
    def getTabCaption(self):
        return "Otter"
    
    def getUiComponent(self):
        return self._maintabs
        
    #
    # implement IHttpListener
    #
    
    def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo):
   
        # Only process responses that came from the proxy. This will
        # ignore request/responses made by Otter itself.
        if not messageIsRequest and toolFlag == self._callbacks.TOOL_PROXY:
            # create a new log entry with the message details
            row = self._log.size()

            # analyze and store information about the original request/response
            responseBytes = messageInfo.getResponse()
            requestBytes = messageInfo.getRequest()
            request = self._helpers.analyzeRequest(messageInfo)
            response = self._helpers.analyzeResponse(responseBytes)
            
            # ignore out-of-scope requests.
            if not self._callbacks.isInScope(request.getUrl()):
                return

            wasModified = False
            ms = self._matchString.getText()
            rs = self._replaceString.getText()
            mss = ms.split(",")
            rss = rs.split(",")
            if len(rss) != len(mss):
                mss = [""]
                
            for i,x in enumerate(mss):
                if x == "":
                    continue
                if self._isRegexp.isSelected():
                    if search(x, requestBytes):
                        requestBytes = sub(x, rss[i], requestBytes)
                        wasModified = True
                else:
                    if fromBytes(requestBytes).find(x) >= 0:
                        requestBytes = toBytes(replace(fromBytes(requestBytes), x, rss[i]))
                        wasModified = True

            # make a modified request to test for authorization issues
            entry = None
            if wasModified:
                modReqResp = self._callbacks.makeHttpRequest(messageInfo.getHttpService(), requestBytes)
                modRequestBytes = modReqResp.getRequest()
                modResponseBytes = modReqResp.getResponse()
                modResponse = self._helpers.analyzeResponse(modResponseBytes)
                orig = self._callbacks.saveBuffersToTempFiles(messageInfo)
                mod = self._callbacks.saveBuffersToTempFiles(modReqResp)
                entry = LogEntry(orig, mod, request.getUrl(), response.getStatusCode(), len(responseBytes), modResponse.getStatusCode(), len(modResponseBytes), wasModified)
            else:
                orig = self._callbacks.saveBuffersToTempFiles(messageInfo)
                entry = LogEntry(orig, None, request.getUrl(), response.getStatusCode(), len(responseBytes), "None", 0, wasModified)

            self._lock.acquire()
            self._log.add(entry)
            self.fireTableRowsInserted(row, row)
            self._lock.release()
        return

    #
    # extend AbstractTableModel
    #
    
    def getRowCount(self):
        try:
            return self._log.size()
        except:
            return 0

    def getColumnCount(self):
        return 6

    def getColumnName(self, columnIndex):
        if columnIndex == 0:
            return "URL"
        if columnIndex == 1:
            return "Request Modified?"
        if columnIndex == 2:
            return "Orig. Status"
        if columnIndex == 3:
            return "Orig. Length"
        if columnIndex == 4:
            return "Mod. Status"
        if columnIndex == 5:
            return "Mod. Length"
        return ""

    def getValueAt(self, rowIndex, columnIndex):
        logEntry = self._log.get(rowIndex)
        if columnIndex == 0:
            return logEntry._url.toString()
        if columnIndex == 1:
            return str(logEntry._wasModified)
        if columnIndex == 2:
            return str(logEntry._origStatus)
        if columnIndex == 3:
            return str(logEntry._origLength)
        if columnIndex == 4:
            return str(logEntry._modStatus)
        if columnIndex == 5:
            return str(logEntry._modLength)
        return ""

    #
    # implement IMessageEditorController
    # this allows our request/response viewers to obtain details about the messages being displayed
    #
    
    def getHttpService(self):
        return self._currentlyDisplayedItem.getHttpService()

    def getRequest(self):
        return self._currentlyDisplayedItem.getRequest()

    def getResponse(self):
        return self._currentlyDisplayedItem.getResponse()
Example #56
0
class BurpExtender(IBurpExtender, ITab, IHttpListener,
                   IMessageEditorController, AbstractTableModel,
                   IContextMenuFactory):
    def registerExtenderCallbacks(self, callbacks):
        # smart xss feature (print conclusion and observation)
        # mark resulsts
        # add automatic check pages in the same domain

        self.tagPayloads = [
            "<b>test", "<b onmouseover=test()>test",
            "<img src=err onerror=test()>", "<script>test</script>"
            "", "<scr ipt>test</scr ipt>", "<SCRIPT>test;</SCRIPT>",
            "<scri<script>pt>test;</scr</script>ipt>",
            "<SCRI<script>PT>test;</SCR</script>IPT>",
            "<scri<scr<script>ipt>pt>test;</scr</sc</script>ript>ipt>",
            "<IMG \"\"\"><SCRIPT>test</SCRIPT>\">",
            "<IMG '''><SCRIPT>test</SCRIPT>'>", "<SCR%00IPT>test</SCR%00IPT>",
            "<IFRAME SRC='f' onerror=\"test\"></IFRAME>",
            "<IFRAME SRC='f' onerror='test'></IFRAME>",
            "<<SCRIPT>test//<</SCRIPT>", "<img src=\"1\" onerror=\"test\">",
            "<img src='1' onerror='test'",
            "<STYLE TYPE=\"text/javascript\">test;</STYLE>",
            "<<SCRIPT>test//<</SCRIPT>"
        ]
        self.attributePayloads = [
            "\"\"\"><SCRIPT>test", "'''><SCRIPT>test'",
            "\"><script>test</script>", "\"><script>test</script><\"",
            "'><script>test</script>", "'><script>test</script><'",
            "\";test;\"", "';test;'", ";test;", "\";test;//",
            "\"onmouseover=test ", "onerror=\"test\"", "onerror='test'",
            "onload=\"test\"", "onload='test'"
        ]
        self.xssKey = 'xssme'
        # 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("XSSor")

        self.affectedResponses = ArrayList()
        self._log = ArrayList()
        self._lock = Lock()

        # main split pane
        self._splitpane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT)

        # table of log entries
        logTable = Table(self)
        scrollPane = JScrollPane(logTable)
        self._splitpane.setLeftComponent(scrollPane)

        # tabs with request/response viewers
        tabs = JTabbedPane()
        self._requestViewer = callbacks.createMessageEditor(self, False)
        self._responseViewer = callbacks.createMessageEditor(self, False)
        tabs.addTab("Request", self._requestViewer.getComponent())
        tabs.addTab("Response", self._responseViewer.getComponent())

        clearAPListBtn = JButton("Clear List",
                                 actionPerformed=self.clearAPList)
        clearAPListBtn.setBounds(10, 85, 120, 30)
        apListLabel = JLabel('Affected Pages List:')
        apListLabel.setBounds(10, 10, 140, 30)
        self.affectedModel = DefaultListModel()
        self.affectedList = JList(self.affectedModel)
        self.affectedList.addListSelectionListener(listSelectedChange(self))
        scrollAList = JScrollPane(self.affectedList)
        scrollAList.setVerticalScrollBarPolicy(
            JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED)
        scrollAList.setBounds(150, 10, 550, 200)
        scrollAList.setBorder(LineBorder(Color.BLACK))

        APtabs = JTabbedPane()
        self._requestAPViewer = callbacks.createMessageEditor(self, False)
        self._responseAPViewer = callbacks.createMessageEditor(self, False)
        APtabs.addTab("Request", self._requestAPViewer.getComponent())
        APtabs.addTab("Affeced Page Response",
                      self._responseAPViewer.getComponent())
        APtabs.setBounds(0, 250, 700, 350)
        APtabs.setSelectedIndex(1)

        self.APpnl = JPanel()
        self.APpnl.setBounds(0, 0, 1000, 1000)
        self.APpnl.setLayout(None)
        self.APpnl.add(scrollAList)
        self.APpnl.add(clearAPListBtn)
        self.APpnl.add(APtabs)
        self.APpnl.add(apListLabel)
        tabs.addTab("Affected Pages", self.APpnl)
        self.intercept = 0

        ## init conf panel
        startLabel = JLabel("Plugin status:")
        startLabel.setBounds(10, 10, 140, 30)

        payloadLabel = JLabel("Basic Payload:")
        payloadLabel.setBounds(10, 50, 140, 30)

        self.basicPayload = "<script>alert(1)</script>"
        self.basicPayloadTxt = JTextArea(self.basicPayload, 5, 30)
        self.basicPayloadTxt.setBounds(120, 50, 305, 30)

        self.bruteForceMode = JCheckBox("Brute Force Mode")
        self.bruteForceMode.setBounds(120, 80, 300, 30)
        self.bruteForceMode.addItemListener(handleBFModeChange(self))

        self.tagPayloadsCheck = JCheckBox("Tag paylods")
        self.tagPayloadsCheck.setBounds(120, 100, 300, 30)
        self.tagPayloadsCheck.setSelected(True)
        self.tagPayloadsCheck.setEnabled(False)
        self.tagPayloadsCheck.addItemListener(handleBFModeList(self))

        self.attributePayloadsCheck = JCheckBox("Attribute payloads")
        self.attributePayloadsCheck.setBounds(260, 100, 300, 30)
        self.attributePayloadsCheck.setSelected(True)
        self.attributePayloadsCheck.setEnabled(False)
        self.attributePayloadsCheck.addItemListener(handleBFModeList(self))

        payloadListLabel = JLabel("Payloads list (for BF mode):")
        payloadListLabel.setBounds(10, 130, 140, 30)

        self.payloadsModel = DefaultListModel()
        self.payloadsList = JList(self.payloadsModel)
        scrollPayloadsList = JScrollPane(self.payloadsList)
        scrollPayloadsList.setVerticalScrollBarPolicy(
            JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED)
        scrollPayloadsList.setBounds(120, 170, 300, 200)
        scrollPayloadsList.setBorder(LineBorder(
            Color.BLACK))  # add buttons to remove payloads and add

        for payload in self.tagPayloads:
            self.payloadsModel.addElement(payload)

        for payload in self.attributePayloads:
            self.payloadsModel.addElement(payload)

        self.startButton = JButton("XSSor is off",
                                   actionPerformed=self.startOrStop)
        self.startButton.setBounds(120, 10, 120, 30)
        self.startButton.setBackground(Color(255, 100, 91, 255))

        consoleTab = JTabbedPane()
        self.consoleLog = JTextArea("", 5, 30)
        scrollLog = JScrollPane(self.consoleLog)
        scrollLog.setVerticalScrollBarPolicy(
            JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED)
        scrollLog.setBounds(120, 170, 550, 200)
        scrollLog.setBorder(LineBorder(Color.BLACK))
        scrollLog.getVerticalScrollBar().addAdjustmentListener(
            autoScrollListener(self))
        consoleTab.addTab("Console", scrollLog)
        consoleTab.setBounds(0, 400, 500, 200)

        self.pnl = JPanel()
        self.pnl.setBounds(0, 0, 1000, 1000)
        self.pnl.setLayout(None)
        self.pnl.add(self.startButton)
        self.pnl.add(startLabel)
        self.pnl.add(payloadLabel)
        self.pnl.add(self.basicPayloadTxt)
        self.pnl.add(self.bruteForceMode)
        self.pnl.add(payloadListLabel)
        self.pnl.add(scrollPayloadsList)
        self.pnl.add(self.attributePayloadsCheck)
        self.pnl.add(self.tagPayloadsCheck)
        self.pnl.add(consoleTab)

        tabs.addTab("Configuration", self.pnl)
        tabs.setSelectedIndex(3)
        self._splitpane.setRightComponent(tabs)

        # customize our UI components
        callbacks.customizeUiComponent(self._splitpane)
        callbacks.customizeUiComponent(logTable)
        callbacks.customizeUiComponent(scrollPane)
        callbacks.customizeUiComponent(tabs)

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

        # register ourselves as an HTTP listener
        callbacks.registerHttpListener(self)
        self._callbacks.registerContextMenuFactory(self)

        print "Thank you for installing XSSor v0.1 extension"
        print "Created by Barak Tawily"
        print "\nGithub:\nhttps://github.com/Quitten/XSSor"
        return

    #
    # implement ITab
    #

    def getTabCaption(self):
        return "XSSor"

    def getUiComponent(self):
        return self._splitpane

    #
    # implement IHttpListener
    #

    def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo):
        if self.intercept == 1:
            if toolFlag == 4:
                # only process requests
                if not messageIsRequest:
                    self.checkForKey(messageInfo)

        return

    def printLog(self, message):
        self.consoleLog.setText(self.consoleLog.getText() + '\r\n' + message)

    def checkXSS(self, messageInfo, urlStr, requestBody, currentPayload):
        self.printLog('trying exploit with the payload: ' + currentPayload)
        requestURL = URL(urlStr.replace(self.xssKey, currentPayload))
        requestBody = requestBody.replace(self.xssKey,
                                          urllib.pathname2url(currentPayload))
        httpService = self._helpers.buildHttpService(
            str(requestURL.getHost()), int(requestURL.getPort()),
            requestURL.getProtocol() == "https")
        response = self._callbacks.makeHttpRequest(httpService, requestBody)
        responseInfo = self._helpers.analyzeResponse(response.getResponse())
        analyzedResponse = self._helpers.bytesToString(response.getResponse(
        ))  # change body offeset + make ui for affeccted pages
        responseBody = analyzedResponse.encode('utf-8')
        vulnOrNot = 'no'

        if currentPayload in responseBody:
            self.printLog('payload: ' + currentPayload +
                          ' found to be vulnarble')
            vulnOrNot = 'yes'
            # mark the payload
        if not len(self.affectedResponses) == 0:
            for request in self.affectedResponses:  # bug in case of no response in messageinfo
                self.printLog('checking affeccted page' +
                              str(request.getUrl()))
                requestURL = request.getUrl()
                httpService = self._helpers.buildHttpService(
                    str(requestURL.getHost()), int(requestURL.getPort()),
                    requestURL.getProtocol() == "https")
                affectedPageResponse = self._callbacks.makeHttpRequest(
                    httpService, request.getRequest())
                analyzedResponse = self._helpers.bytesToString(
                    affectedPageResponse.getResponse())
                responseBody = analyzedResponse.encode('utf-8')

            if currentPayload in responseBody:
                vulnOrNot = 'yes, affected page'
                self.printLog('affeccted page has been found as vulnerable')

        self._lock.acquire()
        row = self._log.size()
        self._log.add(
            LogEntry(
                self._helpers.analyzeRequest(response).getUrl(),
                self._callbacks.saveBuffersToTempFiles(response),
                currentPayload, vulnOrNot))
        self.fireTableRowsInserted(row, row)
        self._lock.release()

    def checkForKey(self, messageInfo):

        currentPayload = self.tagPayloads[0]
        requestInfo = self._helpers.analyzeRequest(messageInfo)
        requestHeaders = list(requestInfo.getHeaders())

        requestURL = requestInfo.getUrl()
        urlStr = str(requestURL)
        self.printLog('checking for xss key in URL: ' + urlStr)
        requestBody = self._helpers.bytesToString(messageInfo.getRequest())
        requestBody = re.sub(
            'Referer:.*\n', '', requestBody, flags=re.MULTILINE,
            count=1)  # workaround avoid xsskey in the referer newHeaders
        if self.xssKey in urlStr or self.xssKey in requestBody:
            self.printLog('xss key has been found')
            if self.bruteForceMode.isSelected():
                for i in range(0, self.payloadsModel.getSize()):
                    payload = self.payloadsModel.getElementAt(i)
                    self.checkXSS(messageInfo, urlStr, requestBody, payload)
            else:
                self.checkXSS(messageInfo, urlStr, requestBody,
                              self.basicPayloadTxt.getText())

                #

    # extend AbstractTableModel
    #

    def getRowCount(self):
        try:
            return self._log.size()
        except:
            return 0

    def getColumnCount(self):
        return 3

    def getColumnName(self, columnIndex):
        if columnIndex == 0:
            return "URL"
        if columnIndex == 1:
            return "Payload"
        if columnIndex == 2:
            return "Vulnerable?"

        return ""

    def getValueAt(self, rowIndex, columnIndex):
        logEntry = self._log.get(rowIndex)
        if columnIndex == 0:
            # return self._callbacks.getToolName(logEntry._tool)
            return logEntry._url.toString()

        if columnIndex == 1:
            return logEntry._payload

        if columnIndex == 2:
            return logEntry._vulnOrNot

        return ""

    #
    # implement IMessageEditorController
    # this allows our request/response viewers to obtain details about the messages being displayed
    #

    def getHttpService(self):
        return self._currentlyDisplayedItem.getHttpService()

    def getRequest(self):
        return self._currentlyDisplayedItem.getRequest()

    def getResponse(self):
        return self._currentlyDisplayedItem.getResponse()

    def startOrStop(self, event):
        if self.startButton.getText() == "XSSor is off":
            self.startButton.setText("XSSor is on")
            self.startButton.setBackground(Color.GREEN)
            self.printLog('on, waiting for key word to be found (' +
                          self.xssKey + ')')
            self.intercept = 1
        else:
            self.startButton.setText("XSSor is off")
            self.startButton.setBackground(Color(255, 100, 91, 255))
            self.intercept = 0

    def clearAPList(self, event):
        self.affectedModel.clear()
        self.affectedResponses = ArrayList()

    #
    # implement IContextMenuFactory
    #
    def createMenuItems(self, invocation):
        responses = invocation.getSelectedMessages()
        if responses > 0:
            ret = LinkedList()
            affectedMenuItem = JMenuItem("XSSor: Add affected page")
            affectedMenuItem.addActionListener(
                handleMenuItems(self, responses[0], "affected"))
            ret.add(affectedMenuItem)
            return (ret)
        return null

    def addAfectedPage(self, messageInfo):
        self.affectedModel.addElement(
            str(self._helpers.analyzeRequest(messageInfo).getUrl()))
        self.affectedResponses.add(messageInfo)
Example #57
0
    def	registerExtenderCallbacks(self, callbacks):
    
        # 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("Otter")
        
        # create the log and a lock on which to synchronize when adding log entries
        self._log = ArrayList()
        self._lock = Lock()
       
        # main split pane for log entries and request/response viewing
        self._settingPanel = JPanel()
        self._logPane = JSplitPane(JSplitPane.VERTICAL_SPLIT)

        # setup settings pane ui
        self._settingPanel.setBounds(0,0,1000,1000)
        self._settingPanel.setLayout(None)

        self._isRegexp = JCheckBox("Use regexp for matching.")
        self._isRegexp.setBounds(10, 10, 220, 20)

        matchLabel = JLabel("String to Match:")
        matchLabel.setBounds(10, 40, 200, 20)
        self._matchString = JTextArea("User 1 Session Information")
        self._matchString.setWrapStyleWord(True)
        self._matchString.setLineWrap(True)
        matchString = JScrollPane(self._matchString)
        matchString.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED)
        matchString.setBounds(10, 60, 400, 200)

        replaceLabel = JLabel("String to Replace:")
        replaceLabel.setBounds(10, 270, 200, 20)
        self._replaceString = JTextArea("User 2 Session Information")
        self._replaceString.setWrapStyleWord(True)
        self._replaceString.setLineWrap(True)
        replaceString = JScrollPane(self._replaceString)
        replaceString.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED)
        replaceString.setBounds(10, 290, 400, 200)

        self._settingPanel.add(self._isRegexp)
        self._settingPanel.add(matchLabel)
        self._settingPanel.add(matchString)
        self._settingPanel.add(replaceLabel)
        self._settingPanel.add(replaceString)
        
        # table of log entries
        logTable = Table(self)
        logTable.getColumnModel().getColumn(0).setPreferredWidth(700)
        logTable.getColumnModel().getColumn(1).setPreferredWidth(150)
        logTable.getColumnModel().getColumn(2).setPreferredWidth(100)
        logTable.getColumnModel().getColumn(3).setPreferredWidth(130)
        logTable.getColumnModel().getColumn(4).setPreferredWidth(100)
        logTable.getColumnModel().getColumn(5).setPreferredWidth(130)
        scrollPane = JScrollPane(logTable)
        self._logPane.setLeftComponent(scrollPane)

        # tabs with request/response viewers
        logTabs = JTabbedPane()
        self._origRequestViewer = callbacks.createMessageEditor(self, False)
        self._origResponseViewer = callbacks.createMessageEditor(self, False)
        self._modRequestViewer = callbacks.createMessageEditor(self, False)
        self._modResponseViewer = callbacks.createMessageEditor(self, False)
        logTabs.addTab("Original Request", self._origRequestViewer.getComponent())
        logTabs.addTab("Original Response", self._origResponseViewer.getComponent())
        logTabs.addTab("Modified Request", self._modRequestViewer.getComponent())
        logTabs.addTab("Modified Response", self._modResponseViewer.getComponent())
        self._logPane.setRightComponent(logTabs)
        
        # top most tab interface that seperates log entries from settings
        maintabs = JTabbedPane()
        maintabs.addTab("Log Entries", self._logPane)
        maintabs.addTab("Settings", self._settingPanel)
        self._maintabs = maintabs
       
        # customize the UI components
        callbacks.customizeUiComponent(maintabs)
        
        # add the custom tab to Burp's UI
        callbacks.addSuiteTab(self)
        
        # register ourselves as an HTTP listener
        callbacks.registerHttpListener(self)
        
        return
Example #58
0
    def registerExtenderCallbacks(self, callbacks):
        # Initialize the global stdout stream
        global stdout

        # 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("Burpsuite Yara Scanner")

        # Create the log and a lock on which to synchronize when adding log entries
        self._log = ArrayList()
        self._lock = Lock()

        # main split pane
        splitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT)

        # table of log entries
        logTable = Table(self)
        scrollPane = JScrollPane(logTable)
        splitpane.setLeftComponent(scrollPane)

        # Options panel
        optionsPanel = JPanel()
        optionsPanel.setLayout(GridBagLayout())
        constraints = GridBagConstraints()

        yara_exe_label = JLabel("Yara Executable Location:")
        constraints.fill = GridBagConstraints.HORIZONTAL
        constraints.gridx = 0
        constraints.gridy = 0
        optionsPanel.add(yara_exe_label, constraints)

        self._yara_exe_txtField = JTextField(25)
        constraints.fill = GridBagConstraints.HORIZONTAL
        constraints.gridx = 1
        constraints.gridy = 0
        optionsPanel.add(self._yara_exe_txtField, constraints)

        yara_rules_label = JLabel("Yara Rules File:")
        constraints.fill = GridBagConstraints.HORIZONTAL
        constraints.gridx = 0
        constraints.gridy = 1
        optionsPanel.add(yara_rules_label, constraints)
		
        self._yara_rules_files = Vector()
        self._yara_rules_files.add("< None >")
        self._yara_rules_fileList = JList(self._yara_rules_files)
        constraints.fill = GridBagConstraints.HORIZONTAL
        constraints.gridx = 1
        constraints.gridy = 1
        optionsPanel.add(self._yara_rules_fileList, constraints)
        
        self._yara_rules_select_files_button = JButton("Select Files")
        self._yara_rules_select_files_button.addActionListener(self)
        constraints.fill = GridBagConstraints.HORIZONTAL
        constraints.gridx = 1
        constraints.gridy = 2
        optionsPanel.add(self._yara_rules_select_files_button, constraints)

        self._yara_clear_button = JButton("Clear Yara Results Table")
        self._yara_clear_button.addActionListener(self)
        constraints.fill = GridBagConstraints.HORIZONTAL
        constraints.gridx = 1
        constraints.gridy = 3
        optionsPanel.add(self._yara_clear_button, constraints)

        # Tabs with request/response viewers
        viewerTabs = JTabbedPane()
        self._requestViewer = callbacks.createMessageEditor(self, False)
        self._responseViewer = callbacks.createMessageEditor(self, False)
        viewerTabs.addTab("Request", self._requestViewer.getComponent())
        viewerTabs.addTab("Response", self._responseViewer.getComponent())
        splitpane.setRightComponent(viewerTabs)

        # Tabs for the Yara output and the Options
        self._mainTabs = JTabbedPane()
        self._mainTabs.addTab("Yara Output", splitpane)
        self._mainTabs.addTab("Options", optionsPanel)

        # customize our UI components
        callbacks.customizeUiComponent(splitpane)
        callbacks.customizeUiComponent(logTable)
        callbacks.customizeUiComponent(scrollPane)
        callbacks.customizeUiComponent(viewerTabs)
        callbacks.customizeUiComponent(self._mainTabs)

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

        # add ourselves as a context menu factory
        callbacks.registerContextMenuFactory(self)

        # Custom Menu Item
        self.menuItem = JMenuItem("Scan with Yara")
        self.menuItem.addActionListener(self)

        # obtain our output stream
        stdout = PrintWriter(callbacks.getStdout(), True)

        # Print a startup notification
        stdout.println("Burpsuite Yara scanner initialized.")
class BurpExtender(IBurpExtender, ITab, IHttpListener, IMessageEditorController, AbstractTableModel):

    # TODO better way?
    headers_seen = []

    #
    # implement IBurpExtender
    #
    
    def	registerExtenderCallbacks(self, callbacks):
    
        # 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("Response headers")
        
        # create the log and a lock on which to synchronize when adding log entries
        self._log = ArrayList()
        self._lock = Lock()
        
        # main split pane
        self._splitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT)
        
        # table of log entries
        logTable = Table(self)
        scrollPane = JScrollPane(logTable)
        self._splitpane.setLeftComponent(scrollPane)

        # tabs with request/response viewers
        tabs = JTabbedPane()
        self._requestViewer = callbacks.createMessageEditor(self, False)
        self._responseViewer = callbacks.createMessageEditor(self, False)
        tabs.addTab("Request", self._requestViewer.getComponent())
        tabs.addTab("Response", self._responseViewer.getComponent())
        self._splitpane.setRightComponent(tabs)
        
        # customize our UI components
        callbacks.customizeUiComponent(self._splitpane)
        callbacks.customizeUiComponent(logTable)
        callbacks.customizeUiComponent(scrollPane)
        callbacks.customizeUiComponent(tabs)
        
        # add the custom tab to Burp's UI
        callbacks.addSuiteTab(self)
        
        # register ourselves as an HTTP listener
        callbacks.registerHttpListener(self)
        
        return
        
    #
    # implement ITab
    #
    
    def getTabCaption(self):
        return "Response Headers"
    
    def getUiComponent(self):
        return self._splitpane
        
    #
    # implement IHttpListener
    #
    
    def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo):
        # TODO make this configurable in the UI
        boring_headers = ["ETag", "P3P", "Date", "Vary", "Content-Length", "Cteonnt-Length", "ntCoent-Length", "Keep-Alive", "Connection", "Content-Type", "Accept-Ranges", "Last-Modified", "Content-Language", "Cache-Control", "Expires", "Content-Location", "Location", "Set-Cookie", "Age", "X-Varnish"]
        # convert to lower case 
        boring_headers = [x.lower() for x in boring_headers]
        # only process requests
        if not messageIsRequest:
        
            # create a new log entry with the message details
            self._lock.acquire()
            row = self._log.size()

            # TODO possible to use analyseResponse? 
            response = messageInfo.getResponse().tostring()

            # TODO possible to use getHeaders()? 
            if "\r\n\r\n" in response:
                headers,body = response.split("\r\n\r\n", 1)

                # split out each header
                if "\n" in headers:
                    headers = headers.split("\n")
                    for header in headers:

                        # Skip HTTP verb and other lines without ':'
                        if ": " in header:
                            # split on 1st colon
                            header_name,header_val = header.split(": ", 1)

                             # insert an entry if the header is 'interesting'
                            if header_name.lower() not in boring_headers:

                                # and we haven't seen this name,value pair before
                                if header not in self.headers_seen:
                                    self.headers_seen.append(header)
                                    print header
                                    self._log.add(LogEntry(header, self._callbacks.saveBuffersToTempFiles(messageInfo), self._helpers.analyzeRequest(messageInfo).getUrl()))
                    self.fireTableRowsInserted(row, row)
                    self._lock.release()
        return

    #
    # extend AbstractTableModel
    #
    
    def getRowCount(self):
        try:
            return self._log.size()
        except:
            return 0

    def getColumnCount(self):
        return 2

    def getColumnName(self, columnIndex):
        if columnIndex == 0:
            return "Header"
        if columnIndex == 1:
            return "URL"
        return ""

    def getValueAt(self, rowIndex, columnIndex):
        logEntry = self._log.get(rowIndex)
        if columnIndex == 0:
            #return self._callbacks.getToolName(logEntry._tool)
            return logEntry._header
        if columnIndex == 1:
            return logEntry._url.toString()
        return ""

    #
    # implement IMessageEditorController
    # this allows our request/response viewers to obtain details about the messages being displayed
    #
    
    def getHttpService(self):
        return self._currentlyDisplayedItem.getHttpService()

    def getRequest(self):
        return self._currentlyDisplayedItem.getRequest()

    def getResponse(self):
        return self._currentlyDisplayedItem.getResponse()