카테고리 없음

ㅎㅇㅇ

1231. 2025. 4. 15. 15:49
# -*- coding: utf-8 -*-
from burp import IBurpExtender, IHttpListener, ITab
from javax.swing import (JPanel, JButton, JTextField, JLabel, JComboBox,
                         JTable, JScrollPane, JTextArea, JSplitPane,
                         BoxLayout, JTree)
from javax.swing.table import DefaultTableModel, DefaultTableCellRenderer
from javax.swing.tree import DefaultMutableTreeNode, DefaultTreeModel
from javax.swing.border import TitledBorder
from java.awt import BorderLayout, Dimension
import re

class BurpExtender(IBurpExtender, IHttpListener, ITab):
    def registerExtenderCallbacks(self, callbacks):
        self.callbacks = callbacks
        self.helpers = callbacks.getHelpers()
        callbacks.setExtensionName("7illight")
        callbacks.registerHttpListener(self)

        self.cached_keywords = []
        self.discovered_map = {}
        self.dir_index_check_results = {}

        self.init_gui()
        callbacks.addSuiteTab(self)

    def getTabCaption(self):
        return "7illight"

    def getUiComponent(self):
        return self.main_panel

    def init_gui(self):
        self.main_panel = JPanel(BorderLayout())

        # Discovered JS URLs
        self.js_root_node = DefaultMutableTreeNode("Discovered JS URLs")
        self.js_tree_model = DefaultTreeModel(self.js_root_node)
        self.js_tree = JTree(self.js_tree_model)
        js_scroll = JScrollPane(self.js_tree)
        js_scroll.setBorder(TitledBorder("Auto JS Mapper"))

        # Directory Index Check Results
        self.dir_table_model = DefaultTableModel(["URL", "Status", "Result"], 0)
        self.dir_table = JTable(self.dir_table_model)
        dir_scroll = JScrollPane(self.dir_table)
        dir_scroll.setBorder(TitledBorder("Directory Index Checker"))

        # Keyword Highlighter
        keyword_panel = JPanel()
        keyword_panel.setLayout(BoxLayout(keyword_panel, BoxLayout.X_AXIS))
        self.scope_selector = JComboBox(["Both", "Request", "Response"])
        self.color_selector = JComboBox(["red", "orange", "yellow", "green", "cyan", "blue", "pink", "magenta", "gray"])
        self.keyword_field = JTextField(15)
        add_button = JButton("Add", actionPerformed=self.add_keyword)
        keyword_panel.add(self.scope_selector)
        keyword_panel.add(self.color_selector)
        keyword_panel.add(self.keyword_field)
        keyword_panel.add(add_button)

        self.keyword_table_model = DefaultTableModel(["Scope", "Color", "Keyword"], 0)
        self.keyword_table = JTable(self.keyword_table_model)
        keyword_scroll = JScrollPane(self.keyword_table)
        keyword_scroll.setBorder(TitledBorder("Keyword Highlights"))

        # Main Split Pane
        left_split = JSplitPane(JSplitPane.VERTICAL_SPLIT, js_scroll, dir_scroll)
        left_split.setResizeWeight(0.5)
        right_split = JSplitPane(JSplitPane.VERTICAL_SPLIT, keyword_panel, keyword_scroll)
        right_split.setResizeWeight(0.1)

        self.main_split = JSplitPane(JSplitPane.HORIZONTAL_SPLIT, left_split, right_split)
        self.main_split.setResizeWeight(0.5)

        self.main_panel.add(self.main_split, BorderLayout.CENTER)

    def add_keyword(self, event):
        scope = self.scope_selector.getSelectedItem()
        color = self.color_selector.getSelectedItem()
        keyword = self.keyword_field.getText().strip()
        if keyword:
            self.cached_keywords.append((scope, color, keyword))
            self.keyword_table_model.addRow([scope, color, keyword])

    def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo):
        if toolFlag not in [self.callbacks.TOOL_PROXY, self.callbacks.TOOL_REPEATER]:
            return

        if messageIsRequest:
            request_info = self.helpers.analyzeRequest(messageInfo)
            url = request_info.getUrl().toString()

            if url.endswith("/") and url not in self.dir_index_check_results:
                self.check_directory_indexing(url, messageInfo)

        else:
            response = messageInfo.getResponse()
            if response is None:
                return

            response_info = self.helpers.analyzeResponse(response)
            body = response[response_info.getBodyOffset():].tostring().decode('utf-8', 'ignore')

            request_info = self.helpers.analyzeRequest(messageInfo.getHttpService(), messageInfo.getRequest())
            base_url = request_info.getUrl()

            headers = response_info.getHeaders()
            for header in headers:
                if "content-type:" in header.lower() and "javascript" in header.lower():
                    self.extract_js_urls(body, base_url)

            self.highlight_message(messageInfo, response_info, body)

    def extract_js_urls(self, body, base_url):
        found_urls = set(re.findall(r'["\'](/[^\'"\s]+)["\']', body))
        for path in found_urls:
            full_url = base_url.getProtocol() + "://" + base_url.getHost() + path
            if full_url not in self.discovered_map:
                self.discovered_map[full_url] = True
                self.js_tree_model.insertNodeInto(DefaultMutableTreeNode(full_url), self.js_root_node, self.js_root_node.getChildCount())
                self.js_tree_model.reload()

    def check_directory_indexing(self, url, messageInfo):
        request_bytes = self.helpers.buildHttpRequest(self.helpers.stringToBytes(url))
        response = self.callbacks.makeHttpRequest(messageInfo.getHttpService(), request_bytes).getResponse()
        response_info = self.helpers.analyzeResponse(response)
        body = response[response_info.getBodyOffset():].tostring().decode('utf-8', 'ignore').lower()

        result = "VULNERABLE" if ("index of" in body or "directory listing for" in body) else "Safe"

        self.dir_index_check_results[url] = result
        self.dir_table_model.addRow([url, response_info.getStatusCode(), result])

    def highlight_message(self, messageInfo, response_info, body):
        body_lower = body.lower()
        request_lower = self.helpers.bytesToString(messageInfo.getRequest()).lower()
        for scope, color, keyword in self.cached_keywords:
            if (scope == "Response" and keyword in body_lower) or \
               (scope == "Request" and keyword in request_lower) or \
               (scope == "Both" and (keyword in body_lower or keyword in request_lower)):
                messageInfo.setHighlight(color)
                break