Upload
august-detlefsen
View
1.813
Download
5
Embed Size (px)
Citation preview
Customizing Burp Suite
Getting the Most out of Burp Extensions
August Detlefsen
• Senior Application Security Consultant• Author
[email protected]@codemagihttp://www.codemagi.com/blog
Monika Morrow
• Senior Application Security Consultant@ AppSec Consulting
[email protected] @fortytwowho
Agenda/Overview
• Extensions• Using the BApp Store• Building Your First Extension• Adding GUI to extensions• Building Scanners• Utilities
Burp Suite
• What is Burp? • What are extensions?– What can I do with them? (use cases)
What Can I Do With Extensions?
• Passive Scanning• Active Scanning• Alter/append requests• Define Insertion Points for Scanner/Intruder• Create new payload types• Automate Authentication• Much, Much More
BApp Store
• What is it? • How do I use it? • A look at some useful extensions– Logger++– WSDL Wizard
BApp Store
Burp Extension Tab
BApp Store
Logger++
List of Active/Inactive Burp Extensions
Logger++ Options
Logger++ View Logs
Logger++ Item Details
Jython Extensions
Burp Extensions Settings
Burp Extensions Settings
One Click Install Jython Extensions
WSDL Wizard Installed
Installed Burp Extensions
WSDL Wizard Usage
WSDL Wizard Results
Limited Examples
• Proprietary code• One-Offs• No process for updating BApp Store
extensions
Loading a Custom Extension
• Java, Python, and Ruby extensions are loaded and managed through a single interface within the Extension tab
Loading a Custom Extension
Loading a Custom Extension
Loading a Custom Extension
Loading a Custom Extension
Loading a Custom Extension
Building Custom Extensions
• Burp Suite Pro v 1.6.x• Current NetBeans IDE (8.0.2)• JDK 8
Starting with a Template
• Find a starter project• Some example projects at
https://portswigger.net/burp/extender/ • Today we’ll start with my NetbeansGUI project
found at https://github.com/monikamorrow/ Burp-Suite-Extension-Examples– Which depends on
https://github.com/augustd/burp-suite-utils
Starting with a Template
• Clone Burp-Suite-Extension-Examples and burp-suite-utils into your working directory
• Open the Burp-Suite-Extension-Examples NetBeans project and expand folders and resolve issues along the way
• Compile the project to resolve remaining issues
Open the NetBeans Project
Problems already! No problem.
Resolve Project Problems
Find the Cloned Project
….and Repeat. Resolved.
Now what!?
Invalid Java Version?
Select Java Version
Resolved!
More Problems?
Compile to Fix!Building jar: C:\Users\mmorrow\Documents\GitHub\Burp-Suite-Extension-Examples\Example4NetBeansGUI\BurpExtender\dist\BurpExtender-combined.jarjar:BUILD SUCCESSFUL (total time: 1 second)
Edit build.xml
<target name="-post-jar"><jar jarfile=
"dist/BurpExtender-combined.jar"><zipfileset src="${dist.jar}" /><zipgroupfileset dir="dist/lib" includes="*.jar”excludes="META-INF/*"/></jar>
</target>
Test!
Let's Write Some Code
• Start new class BurpExtender• Import BurpGUIExtender• Implement BurpGUIExtender's abstract
functions– init()– processSelectedMessage()
BurpExtenderpackage burp;import com.monikamorrow.burp.BurpGUIExtender;
public class BurpExtender extends BurpGUIExtender { ... }
BurpExtenderpublic class BurpExtender extends BurpGUIExtender {
public void init() { mPluginName = "MYPROJECT"; mUsageStatement = "Usage statement for " + mPluginName; }
}
BurpExtenderpublic class BurpExtender extends BurpGUIExtender
protected IHttpRequestResponse processSelectedMessage( IHttpRequestResponse messageInfo, boolean isRequest) { ... return messageInfo; }}
BurpExtender{if(isRequest) { mStdOut.println( "processSelectedMessage triggered for request"); messageInfo.setComment("Request processed");} else { mStdOut.println( "processSelectedMessage triggered for response"); messageInfo.setComment( messageInfo.getComment() + "/Response processed");} return messageInfo;}
What's Available?
• Mix and match– BurpGUIExtender– BurpSuiteTab• ToolsScopeComponent• UrlScopeComponent
– BaseExtender– PassiveScan– ….and more
GUI Components
• Configuration of options• Enable only what you want• Autosave
How to Add?
mTab = new BurpSuiteTab (mPluginName, mCallbacks);mTab.add(toolsScope);mTab.add(urlScope);mTab.add(myJPanel);mCallbacks.customizeUiComponent(mTab);mCallbacks.addSuiteTab(mTab);
How to Get Settings?urlScope.processAllRequests();
toolsScope.isToolSelected(toolFlag);
Passive Scanning• Search responses for problematic values• Built-in passive scans– Credit card numbers– Known passwords– Missing headers
Building a Passive Scanner
Passive Scanning – Room for Improvement• Error Messages• Software Version Numbers
Building a Passive Scanner
Implement the IScannerCheck interfacepublic class PassiveScan implements IScannerCheck {
@Override public List<IScanIssue> doPassiveScan(
IHttpRequestResponse baseRequestResponse) { … }
@Override public List<IScanIssue> doActiveScan(
IHttpRequestResponse baseRequestResponse, IScannerInsertionPoint insertionPoint) { … }
@Override public int consolidateDuplicateIssues(
IScanIssue existingIssue, IScanIssue newIssue) { … }
Building a Passive Scanner
Register the extension as a custom scanner@Overrideprotected void initialize() { callbacks.registerScannerCheck(this);}
Building a Passive Scanner
IScannerCheck.doPassiveScan()for (MatchRule rule : rules) {
Matcher matcher = rule.getPattern().matcher(response);
while (matcher.find()) {matches.add(
new ScannerMatch(matcher.start(), matcher.end(), group,
rule));
Building a Passive Scanner
IScannerCheck.doPassiveScan()if (!matches.isEmpty()) {
Collections.sort(matches);
List<int[]> startStop = new ArrayList<int[]>(1);
for (ScannerMatch match : matches) {startStop.add(new int[]{match.getStart(), match.getEnd()
});
Building a Passive Scanner
IScannerCheck.doPassiveScan()return new ScanIssue(
baseRequestResponse.getHttpService(),
helpers.analyzeRequest(baseRequestResponse).getUrl(),
new IHttpRequestResponse[] {callbacks.applyMarkers(
baseRequestResponse, null, startStop)}, issueName, issueDetail, ScanIssueSeverity.MEDIUM, ScanIssueConfidence.FIRM
Building a Passive Scanner
IScannerCheck.consolidateDuplicateIssues()@Overridepublic int consolidateDuplicateIssues(
IScanIssue existingIssue, IScanIssue newIssue) {
if (existingIssue.getIssueDetail().equals(newIssue.getIssueDetail())) {
return -1; //It is a duplicate
} else { return 0; //This is a new issue}
Building a Passive Scanner
Extending from PassiveScan@Overrideprotected void initPassiveScan() {
//set the extension NameextensionName = "Error Message Checks";
//create match rulesaddMatchRule(
new MatchRule(PHP_ON_LINE, 0, "PHP"));addMatchRule(
new MatchRule(PHP_HTML_ON_LINE, 0, "PHP"));…
Building a Passive Scanner
Extending from PassiveScan@Overrideprotected ScanIssue getScanIssue(
IHttpRequestResponse baseRequestResponse, List<ScannerMatch> matches, List<int[]> startStop) {
return new ScanIssue(baseRequestResponse, helpers,callbacks, startStop, getIssueName(), getIssueDetail(matches), ScanIssueSeverity.MEDIUM.getName(), ScanIssueConfidence.FIRM.getName());
Building a Passive Scanner
Active Scanning• Issue requests containing attacks • Look for indication of success in response• Built-In Active Scans– XSS– SQL Injection– Path Traversal– etc
Building an Active Scanner
IScannerCheck.doActiveScan()@Overridepublic List<IScanIssue> doActiveScan(
IHttpRequestResponse baseRequestResponse, IScannerInsertionPoint insertionPoint) {
for (MatchRule rule : rules) { // compile a request containing our // injection test in the insertion point byte[] testBytes = rule.getTest(); byte[] checkRequest =
insertionPoint.buildRequest(testBytes);
Building an Active Scanner
IScannerCheck.doActiveScan()// issue the requestIHttpRequestResponse checkRequestResponse =
callbacks.makeHttpRequest( httpService, checkRequest);
//get the responseString response = helpers.bytesToString(
checkRequestResponse.getResponse());
Building an Active Scanner
IScannerCheck.doActiveScan()// get the offsets of the payload // within the request, for in-UI highlightingList<int[]> requestHighlights =
new ArrayList<int[]>(1);requestHighlights.add(
insertionPoint.getPayloadOffsets(testBytes));
Building an Active Scanner
Extending from ActiveScan@Overrideprotected void initActiveScan() { //set the extension Name extensionName = "Server Side Javascript Injection checks"; //create match rules addMatchRule(
new MatchRule("response.end('success')", SUCCESS, 0, "response.end")); addMatchRule(
new MatchRule("1995';return(true);var%20foo='bar", TRUE, 0, "string"));
Building an Active Scanner
Insertion Points • Locations of parameters in request • Contain data the server will act upon
Building an Active Scanner
Defining Insertion Points
Defining Insertion Points
Defining Insertion Points• Implement IScannerInsertionPointProvider– getInsertionPoints()
• Register as an insertion point provider:
callbacks.registerScannerInsertionPointProvider(this)
;
Defining Insertion Points
BurpExtender.getInsertionPoints()@Overridepublic List<IScannerInsertionPoint> getInsertionPoints(
IHttpRequestResponse baseRR) { byte[] request = baseRR.getRequest(); String requestAsString =
new String(request);
GWTParser parser = new GWTParser(); parser.parse(requestAsString);
Defining Insertion Points
BurpExtender.getInsertionPoints()for (int[] offset : insertionPointOffsets) {IScannerInsertionPoint point = helpers.makeScannerInsertionPoint(
"GWT", request, offset[0] - bodyStart, offset[1] - bodyStart);
insertionPoints.add(point);
}return insertionPoints;
Defining Insertion Points
Defining Insertion Points
Viewing Insertion Points• Add menu option to send request to Intruder
• Implement IContextMenuFactory– createMenuItems()
• Register as a menu factorycallbacks.registerContextMenuFactory(this);
Defining Insertion Points
BurpExtender.createMenuItems()@Overridepublic List<JMenuItem> createMenuItems(
IContextMenuInvocation invocation) { //get selected requests from //the invocation IHttpRequestResponse[] ihrrs =
invocation.getSelectedMessages();
Defining Insertion Points
BurpExtender.createMenuItems()//create clickable menu itemJMenuItem item = new JMenuItem(
"Send GWT request(s) to Intruder");item.addActionListener(new MenuItemListener(ihrrs));
//return a Collection of menu itemsList<JMenuItem> menuItems =
new ArrayList<JMenuItem>();menuItems.add(item); return menuItems;
Defining Insertion Points
MenuItemListenerclass MenuItemListener implements ActionListener { private IHttpRequestResponse[] ihrrs; public MenuItemListener(
IHttpRequestResponse[] ihrrs) {this.ihrrs = ihrrs;
} public void actionPerformed(ActionEvent ae) {
sendGWTToIntruder(ihrrs); }}
Defining Insertion Points
BurpExtender.sendGWTToIntruder()public void sendGWTToIntruder(IHttpRequestResponse[] ihrrs) { for (IHttpRequestResponse baseRR : ihrrs) {
IHttpService service = baseRR.getHttpService();
// parse the request (not shown)
if (isGWTRequest) {// Send GWT request to Intrudercallbacks.sendToIntruder(
service.getHost(), service.getPort(),
service.getProtocol().equals("https"), request, insertionPointOffsets);
Defining Insertion Points
BurpExtender.sendGWTToIntruder()
baseRR.setComment("GWT: " +
parser.getServiceMethod() + " " + baseRR.getComment()
);
Defining Insertion Points
Defining Insertion Points
Defining Insertion Points
Modifying Requests• Add custom headers• Add signatures• CSRF tokens
Modifying Requests
Modifying Requests• Implement IHttpListener
processHttpMessage()
• Register as an HTTP Listenercallbacks.registerHttpListener(this);
Modifying Requests
@Overridepublic void processHttpMessage(
int toolFlag, boolean messageIsRequest, IHttpRequestResponse messageInfo) {
if (messageIsRequest && callbacks.TOOL_SCANNER == toolFlag) {
BurpExtender.processHttpMessage()Modifying a Request
//see if the request contains a CSRF_TOKENbyte[] scannerRequest =
messageInfo.getRequest();String requestString =
helpers.bytesToString(scannerRequest);
Matcher matcher =TOKEN_PATTERN.matcher(requestString);
if (matcher.find()) { getFreshToken();
BurpExtender.processHttpMessage()Modifying a Request
byte[] request = helpers.buildHttpRequest(FORM_URL);
// issue the request and get the responsebyte[] response = callbacks.makeHttpRequest(
DOMAIN_NAME, 443, true, request);
getFreshToken()Modifying a Request
String responseString = helpers.bytesToString(response);
Matcher matcher = TOKEN_INPUT_PATTERN.matcher(responseString)
;
if (matcher.find()) return matcher.group(1);
getFreshToken()Modifying a Request
String token = getFreshToken(); if (token != null) { requestString = matcher.replaceAll(
"name=\"CSRF_TOKEN\" value=\" + token);} messageInfo.setRequest(
requestString.getBytes());
BurpExtender.processHttpMessage()Modifying a Request
Debugging• callbacks.printOutput(String)• callbacks.printError(String)
Utilities
Utilities
Debugging – Stack Traces• Exception.printStackTrace()• Get the error OutputStream
• Print a stack trace to the stream
Utilities
Utilities
Bringing it all Together
• BApp Store Challenges• Base Classes• Passive Scanning• GUI Building
Using Base Classes• com.codemagi.burp.BaseExtender– com.codemagi.burp.PassiveScan• com.monikamorrow.burp.BurpSuiteTab
Bringing it all Together
Bringing it all TogetherGUI Building
Passive Scanning@Overrideprotected void initPassiveScan() { //set the extension Name extensionName = "Software Version Checks"; //create a component rulesTable = new RuleTableComponent(this, callbacks); //add component to Burp GUI mTab = new BurpSuiteTab(extensionName, callbacks); mTab.addComponent(rulesTable);}
Bringing it all Together
Bringing it all TogetherSolving BApp Store Challenges
Get the Code• Burp Suite Utils:– https://github.com/augustd/burp-suite-utils
• Burp Suite Extension Examples: – https://github.com/monikamorrow/Burp-Suite-Extension-Exam
ples
• Software Version Checks– https://github.com/augustd/burp-suite-software-version-checks
• GWT Scan– https://github.com/augustd/burp-suite-gwt-scan
Get the Extensions
• Software Version Checks• GWT Scan
Also See: • Error Message Checks• Session Timeout Test
Available in the Bapp Store
Thank You!
August Detlefsen
[email protected]@codemagi
Monika Morrow
mmorrow@ appsecconsulting.com@fortytwowho