카테고리 없음

ㅍㅎ

1231. 2025. 4. 15. 14:06
from burp import IBurpExtender, ITab
from java.awt import BorderLayout
from javax.swing import JPanel, JTable, JScrollPane, JTextArea, JSplitPane, JButton, JComboBox
from javax.swing.table import DefaultTableModel
from java.util import Date
from java.text import SimpleDateFormat
from java.net import URL

class BurpExtender(IBurpExtender, ITab):

    def registerExtenderCallbacks(self, callbacks):
        self.callbacks = callbacks
        self.helpers = callbacks.getHelpers()
        self.callbacks.setExtensionName("Dir Index Checker with Request/Response List (Jython)")

        self._request_responses = []

        # UI 패널 구성
        self._panel = JPanel(BorderLayout())
        # 테이블에 URL, Status, Indexed, Time, Request, Response 컬럼을 추가
        self._table_model = DefaultTableModel(["URL", "Status", "Indexed", "Time", "Request", "Response"], 0)
        self._table = JTable(self._table_model)
        self._panel.add(JScrollPane(self._table), BorderLayout.CENTER)

        # 추가 상세 정보용 텍스트 영역 (클릭 시 상세하게 볼 수 있음)
        self._request_viewer = JTextArea()
        self._response_viewer = JTextArea()
        self._request_viewer.setEditable(False)
        self._response_viewer.setEditable(False)
        split = JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
                           JScrollPane(self._request_viewer),
                           JScrollPane(self._response_viewer))
        split.setDividerLocation(400)
        self._panel.add(split, BorderLayout.SOUTH)

        self._table.getSelectionModel().addListSelectionListener(lambda e: self.onRowSelect())

        # 도메인 선택 드롭다운 및 스캔 버튼
        self._host_selector = JComboBox()
        self._scan_button = JButton("Scan Selected Host", actionPerformed=self.scanSelectedHost)

        top_panel = JPanel()
        top_panel.add(self._host_selector)
        top_panel.add(self._scan_button)
        self._panel.add(top_panel, BorderLayout.NORTH)

        # 탭 등록
        callbacks.addSuiteTab(self)
        # 초기 호스트 목록 로딩
        self.updateHostList()

    def getTabCaption(self):
        return "Dir Index Checker"

    def getUiComponent(self):
        return self._panel

    def updateHostList(self):
        hosts = set()
        for item in self.callbacks.getSiteMap(None):
            try:
                url = self.helpers.analyzeRequest(item).getUrl()
                hosts.add(url.getHost())
            except Exception as e:
                print("Error updating host list: %s" % e)
                continue
        self._host_selector.removeAllItems()
        for host in sorted(hosts):
            self._host_selector.addItem(host)

    def scanSelectedHost(self, event):
        selected_host = self._host_selector.getSelectedItem()
        if selected_host is None:
            return

        # 초기화
        self._table_model.setRowCount(0)
        self._request_responses = []
        items = self.callbacks.getSiteMap(None)
        seen = set()

        for item in items:
            try:
                req_info = self.helpers.analyzeRequest(item)
                url = req_info.getUrl()

                if url.getHost() != selected_host:
                    continue

                service = item.getHttpService()

                # 원본 URL 스캔
                self.scan_url(url, service, seen)

                # 경로가 "/"로 끝나지 않으면, "/"를 추가한 URL도 스캔
                if not url.getPath().endswith("/"):
                    appended = url.toString() + "/"
                    new_url = URL(appended)
                    self.scan_url(new_url, service, seen)
            except Exception as e:
                print("Error scanning host: %s" % e)

    def scan_url(self, url, service, seen):
        url_str = url.toString()
        if url_str in seen:
            return
        seen.add(url_str)
        try:
            request = self.helpers.buildHttpRequest(url)
            new_response = self.callbacks.makeHttpRequest(service, request)
            resp_bytes = new_response.getResponse()
            if resp_bytes is None:
                return
            analyzed_response = self.helpers.analyzeResponse(resp_bytes)

            # 응답 본문 추출
            body_offset = analyzed_response.getBodyOffset()
            body = self.helpers.bytesToString(resp_bytes)[body_offset:].lower()

            # 디렉토리 리스팅 판별 (예: "index of"와 "parent directory" 포함 여부)
            if "index of" in body and "parent directory" in body:
                indexed = "YES"
            else:
                indexed = "NO"

            status = analyzed_response.getStatusCode()
            time_str = SimpleDateFormat("HH:mm:ss").format(Date())

            # 요청과 응답 내용을 문자열로 변환
            req_str = self.helpers.bytesToString(new_response.getRequest())
            res_str = self.helpers.bytesToString(new_response.getResponse())

            self._table_model.addRow([url_str, status, indexed, time_str, req_str, res_str])
            self._request_responses.append(new_response)
        except Exception as e:
            print("Error scanning URL %s: %s" % (url_str, e))

    def onRowSelect(self):
        row = self._table.getSelectedRow()
        if 0 <= row < len(self._request_responses):
            rr = self._request_responses[row]
            self._request_viewer.setText(self.helpers.bytesToString(rr.getRequest()))
            self._response_viewer.setText(self.helpers.bytesToString(rr.getResponse()))