Skip to content

Commit a6ad7c6

Browse files
feat: iscan issues from burpference findings (#9)
* feat: iscan issues from burpference findings * chore: update gitignore * fix: fix ci checks on shell script pattern range * fix: fix sc2102 and 2086 * chore: try ignore sc2102 * fix: typo ignore not exclude
1 parent e3ab933 commit a6ad7c6

6 files changed

Lines changed: 183 additions & 21 deletions

File tree

.github/workflows/rigging_pr_description.yml

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,10 @@ jobs:
2121
id: diff
2222
# shellcheck disable=SC2102
2323
run: |
24-
git fetch origin "${{ github.base_ref }}"
25-
MERGE_BASE=$(git merge-base HEAD "origin/${{ github.base_ref }}")
26-
# Use separate diff arguments instead of range notation
27-
DIFF=$(git diff "$MERGE_BASE" HEAD | base64 --wrap=0)
28-
echo "diff=${DIFF}" >> "$GITHUB_OUTPUT"
24+
git fetch origin "${GITHUB_BASE_REF}"
25+
MERGE_BASE="$(git merge-base HEAD "origin/${GITHUB_BASE_REF}")"
26+
DIFF="$(git diff "${MERGE_BASE}" HEAD | base64 --wrap=0)"
27+
echo "diff=${DIFF}" >> "${GITHUB_OUTPUT}"
2928
- uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b #v5.0.3
3029
with:
3130
python-version: "3.11"
@@ -46,6 +45,14 @@ jobs:
4645
GIT_DIFF: ${{ steps.diff.outputs.diff }}
4746
run: |
4847
python .github/scripts/rigging_pr_decorator.py
48+
# Extract PR body
49+
- name: Extract PR body
50+
id: pr
51+
run: |
52+
PR_BODY="$(gh pr view "${GITHUB_EVENT_PULL_REQUEST_NUMBER}" --json body --jq .body)"
53+
echo "body=${PR_BODY}" >> "${GITHUB_OUTPUT}"
54+
env:
55+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
4956
# Update the PR description
5057
- name: Update PR Description
5158
uses: nefrob/pr-description@4dcc9f3ad5ec06b2a197c5f8f93db5e69d2fdca7 #v1.2.0

.gitignore

Lines changed: 64 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,70 @@
1-
.DS_Store
1+
### Project Specific ###
2+
# burpference logs and local config
23
logs/
3-
.idea/workspace.xml
4+
.burpference/
5+
configs/*
6+
!configs/*.example.json
7+
prompt.txt
8+
9+
### Python ###
10+
# Byte-compiled / optimized / DLL files
11+
__pycache__/
12+
*.py[cod]
13+
*$py.class
14+
*.so
15+
16+
# Distribution / packaging
17+
dist/
18+
build/
19+
*.egg-info/
20+
*.egg
21+
22+
# Virtual environments
23+
venv/
24+
env/
25+
.env/
26+
.venv/
27+
28+
# Testing
29+
.pytest_cache/
30+
.coverage
31+
coverage.xml
32+
htmlcov/
33+
34+
# IDE specific files
35+
.idea/
436
.vscode/
5-
.env
6-
archive/autogpt/.gradle/*
7-
archive/autogpt/.gradle/buildOutputCleanup/cache.properties
8-
.lock
37+
*.swp
38+
*.swo
39+
*~
40+
.DS_Store
41+
42+
# Temporary files
43+
*.log
44+
*.tmp
45+
*.temp
946

10-
# Ignore Gradle project-specific cache directory
11-
.gradle
47+
# Debug files
48+
*.debug
1249

13-
# Ignore Gradle build output directory
14-
build
50+
# Local development
51+
local_settings.py
52+
*.local.json
53+
*.local.py
54+
55+
# Security related
56+
*.key
57+
*.pem
58+
*.cert
59+
*.password
60+
*.token
61+
.env
62+
.secret
1563

16-
# Ignore $py.class files (generated when running burp)
64+
# Java/Burp related
65+
*.class
66+
*.jar
67+
!lib/*.jar # Keep vendored jar files if needed
1768

18-
.*$py.*class
19-
burpference/api_adapters$py.class
20-
burpference/consts$py.class
69+
# Docs build
70+
docs/_build/

.pre-commit-config.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ repos:
1717
hooks:
1818
- id: actionlint
1919
name: Check Github Actions
20+
args: ["--ignore", "SC2102"]
2021

2122
# Python code security
2223
- repo: https://github.com/PyCQA/bandit

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ Some key features:
4343
- **Comprehensive Logging**: A logging system allows you to review intercepted responses, API requests sent, and replies received—all clearly displayed for analysis.
4444
- A clean table interface displaying all logs, intercepted responses, API calls, and status codes for comprehensive engagement tracking.
4545
- Stores inference logs in both the "_Inference Logger_" tab as a live preview and a timestamped file in the /logs directory.
46+
- **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.
47+
- Additionally, burpference "findings" are created as issues in the Burp Scanner navigation bar available across all tabs in the Burp UI.
4648
- **Flexible Configuration**: Customize system prompts, API keys, or remote hosts as needed. Use your own configuration files for seamless integration with your workflow.
4749
- Supports custom configurations, allowing you to load and switch between system prompts, API keys, and remote hosts
4850
- [Several examples](configs/README.md) are provided in the repository, and contributions for additional provider plugins are welcome.

burpference/burpference.py

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# -*- coding: utf-8 -*-
22
# type: ignore[import]
3-
from burp import IBurpExtender, ITab, IHttpListener
3+
from burp import IBurpExtender, ITab, IHttpListener, IScanIssue
44
from java.awt import BorderLayout, GridBagLayout, GridBagConstraints, Font
55
from javax.swing import (
66
JPanel, JTextArea, JScrollPane,
@@ -15,6 +15,7 @@
1515
from datetime import datetime
1616
from consts import *
1717
from api_adapters import get_api_adapter
18+
from issues import BurpferenceIssue
1819

1920

2021
def load_ascii_art(file_path):
@@ -144,7 +145,7 @@ def compare(self, s1, s2):
144145
n2 = int(s2)
145146
return n1 - n2
146147
except:
147-
return 0 # Return 0 if conversion fails
148+
return 0
148149

149150
# Add sorting capability
150151
sorter = TableRowSorter(self.historyTableModel)
@@ -598,6 +599,57 @@ def applyDarkTheme(self, component):
598599
for child in component.getComponents():
599600
self.applyDarkTheme(child)
600601

602+
def map_severity(self, ai_severity):
603+
"""Map burpference model severity levels to Burp's iscan exact severity strings"""
604+
severity_map = {
605+
"CRITICAL": "High",
606+
"HIGH": "High",
607+
"MEDIUM": "Medium",
608+
"LOW": "Low",
609+
"INFORMATIONAL": "Information"
610+
}
611+
return severity_map.get(ai_severity, "Information")
612+
613+
def extract_severity_from_response(self, response):
614+
"""Extract severity level from model response"""
615+
for level in ["CRITICAL", "HIGH", "MEDIUM", "LOW", "INFORMATIONAL"]:
616+
if "**%s**" % level in response:
617+
return level
618+
return "INFORMATIONAL"
619+
620+
def create_scan_issue(self, messageInfo, processed_response):
621+
try:
622+
severity = self.extract_severity_from_response(processed_response)
623+
burp_severity = self.map_severity(severity)
624+
625+
# Convert response to string and handle escaping
626+
if isinstance(processed_response, str):
627+
detail = processed_response
628+
else:
629+
detail = str(processed_response)
630+
631+
if detail.startswith('"') and detail.endswith('"'):
632+
detail = detail[1:-1] # Remove surrounding quotes
633+
634+
# Create properly formatted issue name
635+
issue_name = "burpference: %s Security Finding" % severity
636+
637+
issue = BurpferenceIssue(
638+
httpService=messageInfo.getHttpService(),
639+
url=self._helpers.analyzeRequest(messageInfo).getUrl(),
640+
httpMessages=[messageInfo],
641+
name=issue_name,
642+
detail=detail,
643+
severity=burp_severity,
644+
confidence="Certain"
645+
)
646+
647+
self._callbacks.addScanIssue(issue)
648+
self.log_message("Added %s issue to Burp Scanner" % severity)
649+
650+
except Exception as e:
651+
self.log_message("Error creating scan issue: %s" % str(e))
652+
601653
def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo):
602654
if not self.is_running:
603655
return
@@ -731,6 +783,9 @@ def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo):
731783

732784
# Only update the main UI if we got a successful response
733785
if status == "Success" and self.is_running:
786+
# Create Burp scanner issue
787+
self.create_scan_issue(messageInfo, processed_response)
788+
734789
# Add to history table with metadata
735790
self.historyTableModel.addRow([
736791
table_metadata.get("id", ""),

burpference/issues.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
from burp import IScanIssue
2+
3+
4+
class BurpferenceIssue(IScanIssue):
5+
def __init__(
6+
self, httpService, url, httpMessages, name, detail, severity, confidence
7+
):
8+
self._httpService = httpService
9+
self._url = url
10+
self._httpMessages = httpMessages
11+
self._name = name
12+
self._detail = detail
13+
self._severity = severity
14+
self._confidence = confidence
15+
16+
def getUrl(self):
17+
return self._url
18+
19+
def getIssueName(self):
20+
return self._name
21+
22+
def getIssueType(self):
23+
return 0 # Custom issue type
24+
25+
def getSeverity(self):
26+
return self._severity
27+
28+
def getConfidence(self):
29+
return self._confidence
30+
31+
def getIssueBackground(self):
32+
return "Issue identified by burpference model analysis"
33+
34+
def getRemediationBackground(self):
35+
return "Verify the models findings and remediate accordingly"
36+
37+
def getIssueDetail(self):
38+
return self._detail
39+
40+
def getRemediationDetail(self):
41+
return None
42+
43+
def getHttpMessages(self):
44+
return self._httpMessages
45+
46+
def getHttpService(self):
47+
return self._httpService

0 commit comments

Comments
 (0)