Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 12 additions & 5 deletions .github/workflows/rigging_pr_description.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,10 @@ jobs:
id: diff
# shellcheck disable=SC2102
run: |
git fetch origin "${{ github.base_ref }}"
MERGE_BASE=$(git merge-base HEAD "origin/${{ github.base_ref }}")
# Use separate diff arguments instead of range notation
DIFF=$(git diff "$MERGE_BASE" HEAD | base64 --wrap=0)
echo "diff=${DIFF}" >> "$GITHUB_OUTPUT"
git fetch origin "${GITHUB_BASE_REF}"
MERGE_BASE="$(git merge-base HEAD "origin/${GITHUB_BASE_REF}")"
DIFF="$(git diff "${MERGE_BASE}" HEAD | base64 --wrap=0)"
echo "diff=${DIFF}" >> "${GITHUB_OUTPUT}"
- uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b #v5.0.3
with:
python-version: "3.11"
Expand All @@ -46,6 +45,14 @@ jobs:
GIT_DIFF: ${{ steps.diff.outputs.diff }}
run: |
python .github/scripts/rigging_pr_decorator.py
# Extract PR body
- name: Extract PR body
id: pr
run: |
PR_BODY="$(gh pr view "${GITHUB_EVENT_PULL_REQUEST_NUMBER}" --json body --jq .body)"
echo "body=${PR_BODY}" >> "${GITHUB_OUTPUT}"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Update the PR description
- name: Update PR Description
uses: nefrob/pr-description@4dcc9f3ad5ec06b2a197c5f8f93db5e69d2fdca7 #v1.2.0
Expand Down
78 changes: 64 additions & 14 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,20 +1,70 @@
.DS_Store
### Project Specific ###
# burpference logs and local config
logs/
.idea/workspace.xml
.burpference/
configs/*
!configs/*.example.json
prompt.txt

### Python ###
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
*.so

# Distribution / packaging
dist/
build/
*.egg-info/
*.egg

# Virtual environments
venv/
env/
.env/
.venv/

# Testing
.pytest_cache/
.coverage
coverage.xml
htmlcov/

# IDE specific files
.idea/
.vscode/
.env
archive/autogpt/.gradle/*
archive/autogpt/.gradle/buildOutputCleanup/cache.properties
.lock
*.swp
*.swo
*~
.DS_Store

# Temporary files
*.log
*.tmp
*.temp

# Ignore Gradle project-specific cache directory
.gradle
# Debug files
*.debug

# Ignore Gradle build output directory
build
# Local development
local_settings.py
*.local.json
*.local.py

# Security related
*.key
*.pem
*.cert
*.password
*.token
.env
.secret

# Ignore $py.class files (generated when running burp)
# Java/Burp related
*.class
*.jar
!lib/*.jar # Keep vendored jar files if needed

.*$py.*class
burpference/api_adapters$py.class
burpference/consts$py.class
# Docs build
docs/_build/
1 change: 1 addition & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ repos:
hooks:
- id: actionlint
name: Check Github Actions
args: ["--ignore", "SC2102"]

# Python code security
- repo: https://github.com/PyCQA/bandit
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ Some key features:
- **Comprehensive Logging**: A logging system allows you to review intercepted responses, API requests sent, and replies received—all clearly displayed for analysis.
- A clean table interface displaying all logs, intercepted responses, API calls, and status codes for comprehensive engagement tracking.
- Stores inference logs in both the "_Inference Logger_" tab as a live preview and a timestamped file in the /logs directory.
- **Native Burp Reporting**: burpference' system prompt invokes the model to make an assessment based on severity level of the finding which is color-coded (a heatmap related to the severity level) in the extenstion tab.
- Additionally, burpference "findings" are created as issues in the Burp Scanner navigation bar available across all tabs in the Burp UI.
- **Flexible Configuration**: Customize system prompts, API keys, or remote hosts as needed. Use your own configuration files for seamless integration with your workflow.
- Supports custom configurations, allowing you to load and switch between system prompts, API keys, and remote hosts
- [Several examples](configs/README.md) are provided in the repository, and contributions for additional provider plugins are welcome.
Expand Down
59 changes: 57 additions & 2 deletions burpference/burpference.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
# type: ignore[import]
from burp import IBurpExtender, ITab, IHttpListener
from burp import IBurpExtender, ITab, IHttpListener, IScanIssue
from java.awt import BorderLayout, GridBagLayout, GridBagConstraints, Font
from javax.swing import (
JPanel, JTextArea, JScrollPane,
Expand All @@ -15,6 +15,7 @@
from datetime import datetime
from consts import *
from api_adapters import get_api_adapter
from issues import BurpferenceIssue


def load_ascii_art(file_path):
Expand Down Expand Up @@ -144,7 +145,7 @@ def compare(self, s1, s2):
n2 = int(s2)
return n1 - n2
except:
return 0 # Return 0 if conversion fails
return 0

# Add sorting capability
sorter = TableRowSorter(self.historyTableModel)
Expand Down Expand Up @@ -598,6 +599,57 @@ def applyDarkTheme(self, component):
for child in component.getComponents():
self.applyDarkTheme(child)

def map_severity(self, ai_severity):
"""Map burpference model severity levels to Burp's iscan exact severity strings"""
severity_map = {
"CRITICAL": "High",
"HIGH": "High",
"MEDIUM": "Medium",
"LOW": "Low",
"INFORMATIONAL": "Information"
}
return severity_map.get(ai_severity, "Information")

def extract_severity_from_response(self, response):
"""Extract severity level from model response"""
for level in ["CRITICAL", "HIGH", "MEDIUM", "LOW", "INFORMATIONAL"]:
if "**%s**" % level in response:
return level
return "INFORMATIONAL"

def create_scan_issue(self, messageInfo, processed_response):
try:
severity = self.extract_severity_from_response(processed_response)
burp_severity = self.map_severity(severity)

# Convert response to string and handle escaping
if isinstance(processed_response, str):
detail = processed_response
else:
detail = str(processed_response)

if detail.startswith('"') and detail.endswith('"'):
detail = detail[1:-1] # Remove surrounding quotes

# Create properly formatted issue name
issue_name = "burpference: %s Security Finding" % severity

issue = BurpferenceIssue(
httpService=messageInfo.getHttpService(),
url=self._helpers.analyzeRequest(messageInfo).getUrl(),
httpMessages=[messageInfo],
name=issue_name,
detail=detail,
severity=burp_severity,
confidence="Certain"
)

self._callbacks.addScanIssue(issue)
self.log_message("Added %s issue to Burp Scanner" % severity)

except Exception as e:
self.log_message("Error creating scan issue: %s" % str(e))

def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo):
if not self.is_running:
return
Expand Down Expand Up @@ -731,6 +783,9 @@ def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo):

# Only update the main UI if we got a successful response
if status == "Success" and self.is_running:
# Create Burp scanner issue
self.create_scan_issue(messageInfo, processed_response)

# Add to history table with metadata
self.historyTableModel.addRow([
table_metadata.get("id", ""),
Expand Down
47 changes: 47 additions & 0 deletions burpference/issues.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
from burp import IScanIssue


class BurpferenceIssue(IScanIssue):
def __init__(
self, httpService, url, httpMessages, name, detail, severity, confidence
):
self._httpService = httpService
self._url = url
self._httpMessages = httpMessages
self._name = name
self._detail = detail
self._severity = severity
self._confidence = confidence

def getUrl(self):
return self._url

def getIssueName(self):
return self._name

def getIssueType(self):
return 0 # Custom issue type

def getSeverity(self):
return self._severity

def getConfidence(self):
return self._confidence

def getIssueBackground(self):
return "Issue identified by burpference model analysis"

def getRemediationBackground(self):
return "Verify the models findings and remediate accordingly"

def getIssueDetail(self):
return self._detail

def getRemediationDetail(self):
return None

def getHttpMessages(self):
return self._httpMessages

def getHttpService(self):
return self._httpService
Loading