Skip to content

Commit 5d2f440

Browse files
committed
Improve integrity of requests. Test.
Fixes #6.
1 parent 09fe514 commit 5d2f440

21 files changed

+402
-108
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.gradle
2+
build
3+
settings.xml
4+

build.gradle

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,31 @@ repositories {
44
mavenCentral()
55
}
66

7-
dependencies {
8-
compile 'net.portswigger.burp.extender:burp-extender-api:1.7.22'
9-
compile 'com.google.code.gson:gson:2.8.6'
10-
}
7+
apply plugin: 'jacoco'
118

12-
sourceSets {
13-
main {
14-
java {
15-
srcDir 'src'
16-
}
17-
resources {
18-
srcDir 'resources'
19-
}
9+
jacocoTestReport {
10+
reports {
11+
xml.enabled = true
12+
html.enabled = true
2013
}
2114
}
2215

16+
check.dependsOn jacocoTestReport
17+
18+
dependencies {
19+
implementation 'net.portswigger.burp.extender:burp-extender-api:1.7.22'
20+
implementation 'com.google.code.gson:gson:2.8.6'
21+
testImplementation 'junit:junit:4.12'
22+
testImplementation 'org.mockito:mockito-core:2.8.47'
23+
}
24+
2325
task fatJar(type: Jar) {
24-
baseName = project.name + '-all'
25-
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
26+
archiveBaseName = project.name + '-all'
27+
from { configurations.compileClasspath.collect { it.isDirectory() ? it : zipTree(it) } }
2628
with jar
2729
}
30+
31+
tasks.withType(JavaCompile) {
32+
options.encoding = 'UTF-8'
33+
options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
34+
}
-298 KB
Binary file not shown.
-298 KB
Binary file not shown.

src/burp/Extractor.java

Lines changed: 0 additions & 93 deletions
This file was deleted.
File renamed without changes.
File renamed without changes.

src/main/java/burp/Extractor.java

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
package burp;
2+
3+
import java.io.PrintWriter;
4+
import java.net.URL;
5+
6+
public class Extractor implements IHttpListener {
7+
private ExtractorMainTab extractorMainTab;
8+
private IExtensionHelpers helpers;
9+
private Logger logger;
10+
11+
public Extractor(ExtractorMainTab extractorMainTab, IBurpExtenderCallbacks callbacks) {
12+
this.extractorMainTab = extractorMainTab;
13+
this.helpers = callbacks.getHelpers();
14+
15+
this.logger = new Logger(new PrintWriter(callbacks.getStdout(), true));
16+
// Logger.setLogLevel(Logger.INFO);
17+
}
18+
19+
@Override
20+
public void processHttpMessage(int toolFlag, boolean messageIsRequest, IHttpRequestResponse messageInfo) {
21+
if (messageIsRequest) {
22+
logger.debug("Processing request...");
23+
byte[] requestBytes = messageInfo.getRequest();
24+
String request = this.helpers.bytesToString(requestBytes);
25+
26+
// Loop over each tab to perform whatever replacement is necessary
27+
String extractedData;
28+
boolean edited = false;
29+
for (ExtractorTab extractorTab : this.extractorMainTab.getExtractorTabs()) {
30+
31+
// Determine if this message is in scope, and the user wants requests edited at this time
32+
URL url = this.helpers.analyzeRequest(messageInfo.getHttpService(), requestBytes).getUrl();
33+
if (extractorTab.requestIsInScope(url,
34+
messageInfo.getHttpService().getHost(),
35+
toolFlag) &&
36+
extractorTab.shouldModifyRequests()) {
37+
logger.debug("Request is in scope and Extractor tab is active.");
38+
39+
// Check if we have the necessary components to do replacement
40+
String[] requestSelectionRegex = extractorTab.getRequestSelectionRegex();
41+
extractedData = extractorTab.getDataToInsert();
42+
if (!extractedData.equals("")
43+
&& !requestSelectionRegex[0].equals("")
44+
&& !requestSelectionRegex[1].equals("")) {
45+
logger.debug("Attempting replacement...");
46+
int[] selectionBounds = Utils.getSelectionBounds(request, requestSelectionRegex[0], requestSelectionRegex[1]);
47+
if (selectionBounds != null) {
48+
logger.info("Replacing request after regex \"" + requestSelectionRegex[0] + "\" with \"" + extractedData + "\"");
49+
int[] clHeaderBounds = Utils.getSelectionBounds(request, "(?i)\\r\\nContent-Length: ", "\\r\\n");
50+
int[] headersEndBounds = Utils.getSelectionBounds(request, "\\r\\n\\r\\n", "");
51+
// The following rewrite of the Content-Length
52+
// header aims at maintaining the integrity between
53+
// the header's claim and the rewritten content's
54+
// length. The Content-Length rewrite can still be
55+
// insufficient. For example, the rewrite will not
56+
// fix the MIME parts of a request body that carry
57+
// own content length headers. The Content-Length
58+
// rewrite will not fix the claimed length of a
59+
// chunk in a a chunked Transfer-Encoding.
60+
String dangerousContentLengthRewrite = null;
61+
if ((clHeaderBounds != null) && (headersEndBounds != null) &&
62+
(clHeaderBounds[0] < headersEndBounds[0]) && (headersEndBounds[0] < selectionBounds[0])) {
63+
int origContentLength = Integer.parseInt(request.substring(clHeaderBounds[0],
64+
clHeaderBounds[1]));
65+
int replacedLength = selectionBounds[1] - selectionBounds[0];
66+
int replacedContentLength = origContentLength - replacedLength + extractedData.length();
67+
if (origContentLength != replacedContentLength) {
68+
logger.info("Updating Content-Length: " + origContentLength + " with " + replacedContentLength);
69+
dangerousContentLengthRewrite = request.substring(0, clHeaderBounds[0]) +
70+
Integer.toString(replacedContentLength) +
71+
request.substring(clHeaderBounds[1], selectionBounds[0]);
72+
}
73+
}
74+
String contentBeforeRewrite;
75+
if (dangerousContentLengthRewrite == null) {
76+
contentBeforeRewrite = request.substring(0, selectionBounds[0]);
77+
} else {
78+
contentBeforeRewrite = dangerousContentLengthRewrite;
79+
}
80+
request = contentBeforeRewrite
81+
+ extractedData
82+
+ request.substring(selectionBounds[1], request.length());
83+
edited = true;
84+
logger.debug("Finished replacement");
85+
}
86+
}
87+
}
88+
}
89+
if (edited) {
90+
messageInfo.setRequest(this.helpers.stringToBytes(request));
91+
}
92+
} else if (!messageIsRequest) {
93+
94+
logger.debug("Processing response...");
95+
byte[] responseBytes = messageInfo.getResponse();
96+
String response = this.helpers.bytesToString(responseBytes);
97+
98+
// Loop over each tab, and grab whatever data item is necessary
99+
for (ExtractorTab extractorTab : this.extractorMainTab.getExtractorTabs()) {
100+
101+
// Check if message is in scope
102+
IHttpService service = messageInfo.getHttpService();
103+
URL url;
104+
try {
105+
url = new URL(service.getProtocol(), service.getHost(), service.getPort(), "");
106+
} catch(java.net.MalformedURLException e) {
107+
throw new RuntimeException(e);
108+
}
109+
if (extractorTab.responseIsInScope(url,
110+
service.getHost(),
111+
toolFlag)) {
112+
logger.debug("Response is in scope.");
113+
114+
String[] responseSelectionRegex = extractorTab.getResponseSelectionRegex();
115+
116+
// Grab text from response
117+
if (responseSelectionRegex[0] != "" && responseSelectionRegex[1] != "") {
118+
int[] selectionBounds = Utils.getSelectionBounds(response, responseSelectionRegex[0], responseSelectionRegex[1]);
119+
if (selectionBounds != null) {
120+
logger.info("Found a match in the response after regex \"" + responseSelectionRegex[0] + "\": \"" +
121+
response.substring(selectionBounds[0], selectionBounds[1]) + "\"");
122+
extractorTab.setDataToInsert(response.substring(selectionBounds[0], selectionBounds[1]));
123+
}
124+
} else {
125+
logger.debug("Before and after regex not defined");
126+
}
127+
}
128+
}
129+
}
130+
}
131+
}
File renamed without changes.

src/burp/ExtractorMainTab.java renamed to src/main/java/burp/ExtractorMainTab.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import java.util.HashMap;
1010

1111
public class ExtractorMainTab implements ITab {
12-
private HashMap extractorTabMap;
12+
private HashMap<Integer, ExtractorTab> extractorTabMap;
1313
private ExtractorSelectorTab selectorTab;
1414
private int tabNum = 0;
1515
static int tabsRemoved = 0;

0 commit comments

Comments
 (0)