Skip to content

Commit

Permalink
Merge pull request #39 from augustd/combine-offsets
Browse files Browse the repository at this point in the history
Provide for better combining of offsets when scanner matches overlap
  • Loading branch information
augustd authored Apr 12, 2021
2 parents 2349414 + 6c3e1cb commit 812a2a1
Show file tree
Hide file tree
Showing 6 changed files with 195 additions and 22 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.codemagi</groupId>
<artifactId>burp-suite-utils</artifactId>
<version>1.2.4</version>
<version>1.2.5</version>
<packaging>jar</packaging>
<name>Burp Suite Utils</name>
<description>The Burp Suite Utils project provides developers with APIs for building Burp Suite Extensions.</description>
Expand Down
80 changes: 80 additions & 0 deletions src/main/java/com/codemagi/burp/Offsets.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Copyright 2021 augustd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.codemagi.burp;

/**
*
* @author August Detlefsen [augustd at codemagi dot com]
*/
public class Offsets {
private Integer start;
private Integer end;

public Offsets(Integer start, Integer end) {
this.start = start;
this.end = end;
}

public Integer getStart() {
return start;
}

public void setStart(Integer start) {
this.start = start;
}

public Integer getEnd() {
return end;
}

public void setEnd(Integer end) {
this.end = end;
}

/**
* Return true if this set of Offsets overlaps the other set passed in.
*
* @param other Another Offsets instance to compare against
* @return true if this set of Offsets overlaps the other set passed in.
*/
public boolean overlaps(Offsets other) {
if (other == null) return false;

return (this.start <= other.getEnd() && other.getStart() <= this.end);
}

/**
* Combine two sets of Offsets into one overlapping set.
*
* @param other Another Offsets instance to combine with
* @return An Offsets instance which combines the start/stop points of both instances
*/
public Offsets combine(Offsets other) {
if (other == null) return this;

return new Offsets(Math.min(start, other.getStart()), Math.max(end, other.getEnd()));
}

/**
* Retrieve the start/stop points as an int[] array.
*
* @return An array of int suitable for passing into a Burp IScanIssue
*/
public int[] toArray() {
int[] output = {start, end};
return output;
}
}
18 changes: 16 additions & 2 deletions src/main/java/com/codemagi/burp/PassiveScan.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;

Expand Down Expand Up @@ -157,15 +158,28 @@ protected List<IScanIssue> processIssues(List<ScannerMatch> matches, IHttpReques
if (!matches.isEmpty()) {
Collections.sort(matches); //matches must be in order
//get the offsets of scanner matches
List<int[]> startStop = new ArrayList<>(1);
LinkedList<Offsets> offsets = new LinkedList<>();
for (ScannerMatch match : matches) {
callbacks.printOutput("Processing match: " + match);
callbacks.printOutput(" start: " + match.getStart() + " end: " + match.getEnd() + " full match: " + match.getFullMatch() + " group: " + match.getMatchGroup());
//add a marker for code highlighting
startStop.add(new int[]{match.getStart(), match.getEnd()});
//startStop.add(new int[]{match.getStart(), match.getEnd()});
Offsets matchOffsets = match.getOffsets();
if (!matchOffsets.overlaps(offsets.peekLast())) {
offsets.add(match.getOffsets());
} else {
//if the new offsets overlap, combine them into one and add them to the list
Offsets combinedOffsets = matchOffsets.combine(offsets.pop());
offsets.add(combinedOffsets);
}
}
List<int[]> startStop = new ArrayList<>(1);
for (Offsets os : offsets) {
startStop.add(os.toArray());
}
issues.add(getScanIssue(baseRequestResponse, matches, startStop));
callbacks.printOutput("issues: " + issues.size());
callbacks.printOutput("offsets: " + offsets.size());
}

return issues;
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/codemagi/burp/ScanIssue.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public ScanIssue(
this.severity = severity;
this.confidence = confidence;
}

public ScanIssue(IScanIssue existing) {
this.httpService = existing.getHttpService();
this.url = existing.getUrl();
Expand Down
35 changes: 17 additions & 18 deletions src/main/java/com/codemagi/burp/ScannerMatch.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,33 +8,29 @@
*/
public class ScannerMatch implements Comparable<ScannerMatch> {

private Integer start;
private int end;
private String fullMatch;
private String matchGroup;
private String type;
private ScanIssueSeverity severity;
private ScanIssueConfidence confidence;
private MatchRule rule;
private Offsets offsets;

public ScannerMatch(int start, int end, String match, String type) {
this.start = start;
this.end = end;
offsets = new Offsets(start, end);
this.matchGroup = match;
this.type = type;
}

public ScannerMatch(Integer start, int end, String match, String type, ScanIssueSeverity severity) {
this.start = start;
this.end = end;
offsets = new Offsets(start, end);
this.matchGroup = match;
this.type = type;
this.severity = severity;
}

public ScannerMatch(Integer start, int end, String match, MatchRule rule) {
this.start = start;
this.end = end;
offsets = new Offsets(start, end);
this.matchGroup = match;
this.rule = rule;
this.type = rule.getType();
Expand All @@ -43,8 +39,7 @@ public ScannerMatch(Integer start, int end, String match, MatchRule rule) {
}

public ScannerMatch(Integer start, int end, String fullMatch, String matchGroup, MatchRule rule) {
this.start = start;
this.end = end;
offsets = new Offsets(start, end);
this.fullMatch = fullMatch;
this.matchGroup = matchGroup;
this.rule = rule;
Expand All @@ -53,12 +48,12 @@ public ScannerMatch(Integer start, int end, String fullMatch, String matchGroup,
this.confidence = rule.getConfidence();
}

public int getStart() {
return start;
public Integer getStart() {
return offsets.getStart();
}

public int getEnd() {
return end;
public Integer getEnd() {
return offsets.getEnd();
}

public String getFullMatch() {
Expand All @@ -73,9 +68,9 @@ public MatchRule getRule() {
return rule;
}

public Pattern getPattern() {
return rule.getPattern();
}
public Pattern getPattern() {
return rule.getPattern();
}

public String getType() {
return type;
Expand All @@ -91,7 +86,11 @@ public ScanIssueConfidence getConfidence() {

@Override
public int compareTo(ScannerMatch m) {
return start.compareTo(m.getStart());
return this.getStart().compareTo(m.getStart());
}

public Offsets getOffsets() {
return offsets;
}

}
80 changes: 80 additions & 0 deletions src/test/java/com/codemagi/burp/OffsetsTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Copyright 2021 august.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.codemagi.burp;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;

/**
*
* @author august
*/
public class OffsetsTest {

Offsets a = new Offsets(10, 15);
Offsets b = new Offsets(20, 25);
Offsets c = new Offsets(12, 17);
Offsets d = new Offsets(8, 13);
Offsets e = new Offsets(5, 20);

public OffsetsTest() {
}

@BeforeClass
public static void setUpClass() {
}

@AfterClass
public static void tearDownClass() {
}

@Before
public void setUp() {
}

@After
public void tearDown() {
}

@Test
public void testOverlap() {
assertFalse(a.overlaps(b));
assertFalse(b.overlaps(a));

assertTrue(a.overlaps(c));
assertTrue(c.overlaps(a));

assertTrue(a.overlaps(d));
assertTrue(d.overlaps(a));

assertTrue(a.overlaps(e));
assertTrue(e.overlaps(a));

assertTrue(b.overlaps(e));
assertTrue(e.overlaps(b));
}

@Test
public void testCombine() {
Offsets product = a.combine(c);
assertEquals(new Integer(10), product.getStart());
assertEquals(new Integer(17), product.getEnd());
}
}

0 comments on commit 812a2a1

Please sign in to comment.