Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JS: Changes to fix and improve scanning #4

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
72 changes: 34 additions & 38 deletions src/main/java/burp/BurpExtender.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.*;

Expand Down Expand Up @@ -42,20 +43,10 @@ public void registerExtenderCallbacks(IBurpExtenderCallbacks iBurpExtenderCallba
helpers = iBurpExtenderCallbacks.getHelpers();
}

private List<IScanIssue> runScannerForRequest(IHttpRequestResponse iHttpRequestResponse) {
private void runScannerForRequest(IHttpRequestResponse iHttpRequestResponse) {
print("runScannerForRequest");
ExecutorService service = Executors.newFixedThreadPool(1);
Future<List<IScanIssue>> task = service.submit(new ScannerThread(iHttpRequestResponse));
List<IScanIssue> result = null;

try {
result = task.get();
} catch(final InterruptedException ex) {
ex.printStackTrace();
} catch(final ExecutionException ex) {
ex.printStackTrace();
}

return result;
service.execute(new ScannerThread(iHttpRequestResponse));
}

/**
Expand Down Expand Up @@ -94,11 +85,7 @@ class MenuItemListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
for (IHttpRequestResponse message : arr) {
List<IScanIssue> result = runScannerForRequest(message);

if (result != null) {
callbacks.addScanIssue(result.get(0));
}
runScannerForRequest(message);
}
}
}
Expand All @@ -113,7 +100,8 @@ public List<IScanIssue> doPassiveScan(IHttpRequestResponse iHttpRequestResponse)

@Override
public List<IScanIssue> doActiveScan(IHttpRequestResponse iHttpRequestResponse, IScannerInsertionPoint iScannerInsertionPoint) {
return runScannerForRequest(iHttpRequestResponse);
runScannerForRequest(iHttpRequestResponse);
return new ArrayList<>();
}

@Override
Expand All @@ -123,42 +111,50 @@ public int consolidateDuplicateIssues(IScanIssue existingIssue, IScanIssue newIs
}
}

class ScannerThread implements Callable<List<IScanIssue>> {
class ScannerThread implements Runnable {

private List<IScanIssue> result = null;
private IHttpRequestResponse reqRes;

ScannerThread(IHttpRequestResponse reqRes) {
this.reqRes = reqRes;
}

public List<IScanIssue> call() {
// Test One: Does appending to the URL return a similar response.
if (RequestSender.initialTest(reqRes)) {
Set<String> fileTypesCached = new HashSet<>();
@Override
public void run() {
try {
print("run");

// Test two: Check if caching is done by file type
for (String ext : RequestSender.INITIAL_TEST_EXTENSIONS) {
if (RequestSender.getFileTypeCached(reqRes, ext)) {
fileTypesCached.add(ext);
}
}
// Test One: Does appending to the URL return a similar response.
if (RequestSender.initialTest(reqRes)) {
Set<String> fileTypesCached = new HashSet<>();

if (fileTypesCached.size() != 0) {
for (String ext : RequestSender.OTHER_TEST_EXTENSIONS) {
// Test two: Check if caching is done by file type
for (String ext : RequestSender.INITIAL_TEST_EXTENSIONS) {
if (RequestSender.getFileTypeCached(reqRes, ext)) {
fileTypesCached.add(ext);
}
}

WebCacheIssue issue = new WebCacheIssue(reqRes);
issue.setVulnerableExtensions(fileTypesCached);
if (fileTypesCached.size() > 0) {
for (String ext : RequestSender.OTHER_TEST_EXTENSIONS) {
if (RequestSender.getFileTypeCached(reqRes, ext)) {
fileTypesCached.add(ext);
}
}

WebCacheIssue issue = new WebCacheIssue(reqRes);
issue.setVulnerableExtensions(fileTypesCached);
callbacks.addScanIssue(issue);
}
}

return Arrays.asList(issue);
} catch (Throwable t) {
try {
callbacks.getStderr().write(t.toString().getBytes());
} catch (IOException ioe) {
print(t.toString());
}
}

return result;
}
}
}
48 changes: 24 additions & 24 deletions src/main/java/burp/RequestSender.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ class RequestSender {
private final static String WORD = "test";

protected final static String[] INITIAL_TEST_EXTENSIONS = {"css", "jpg", "js"};
protected final static String[] OTHER_TEST_EXTENSIONS = {"html", "htm", "gif", "png", "cgi", "pl", "java", "class",
"php", "php3", "shtm", "shtml", "cfm", "cfml", "doc", "log", "txt", "csv", "ppt", "m4a", "mid", "mp3", "flv",
"m4v", "mov", "tif", "svg", "pdf", "xls", "sql", "bat", "exe", "jsp", "asp", "aspx", "jpeg"};
protected final static String[] OTHER_TEST_EXTENSIONS = {"html", "gif", "png", "svg", "php", "txt", "pdf", "jsp", "asp"};
// , "php3", "shtm", "shtml", "cfm", "cfml", "doc", "log", "csv", "ppt", "m4a", "mid", "mp3", "flv",
// "m4v", "mov", "tif", "xls", "sql", "bat", "exe",, "aspx", "jpeg", "htm", "cgi", "pl", "java", "class"};

private static byte[] orgResponse;

Expand All @@ -29,47 +29,48 @@ class RequestSender {
* @return
*/
protected static boolean initialTest(IHttpRequestResponse message) {
// Send the original request again
// Send the original request again, to get the response
byte[] orgRequest = buildHttpRequest(message, null, null, true);
orgResponse = retrieveResponseBody(message.getHttpService(), orgRequest, true);
orgResponse = retrieveResponseBody(message.getHttpService(), orgRequest);

// Send an unauthenticated - to root out fp's. Unauthenticated should not be the same as original
byte[] unAuthedRequest = buildHttpRequest(message, null, null, false);
byte[] unAuthedResponse = retrieveResponseBody(message.getHttpService(), unAuthedRequest, false);
byte[] unAuthedResponse = retrieveResponseBody(message.getHttpService(), unAuthedRequest);

// Test that the original request and an unauthenticated request do not get the same response.
// Same here is similar, according to the thresholds set
boolean authed = testSimilar(new String(orgResponse), new String(unAuthedResponse));
if (authed) {
BurpExtender.print("Request not vulnerable");
boolean unauthed = testSimilar(new String(orgResponse), new String(unAuthedResponse));
if (unauthed) {
BurpExtender.print("Request not vulnerable, no auth: ");
return false;
}

// Send with /test appended, check that everything after is ignored
byte[] testRequest = buildHttpRequest(message, WORD, null, true);
byte[] testResponse = retrieveResponseBody(message.getHttpService(), testRequest, true);
byte[] testResponse = retrieveResponseBody(message.getHttpService(), testRequest);

boolean append = testSimilar(new String(orgResponse), new String(testResponse));
if (!append) {
BurpExtender.print("Request not vulnerable.");
BurpExtender.print("Request not vulnerable, appending to end not similar.");
}
return append;
}

protected static boolean getFileTypeCached(IHttpRequestResponse message, String extension) {
protected static boolean getFileTypeCached(IHttpRequestResponse message, String ext) {
// Send with extension, potentially create cached version of resource
byte[] extRequest = buildHttpRequest(message, WORD, extension, true);
byte[] extResponse = retrieveResponseBody(message.getHttpService(), extRequest, false);
byte[] extRequest = buildHttpRequest(message, WORD, ext, true);
byte[] extResponse = retrieveResponseBody(message.getHttpService(), extRequest);

// Send an unauthenticated, test if vulnerable
byte[] vulRequest = buildHttpRequest(message, WORD, extension, false);
byte[] vulResponse = retrieveResponseBody(message.getHttpService(), vulRequest, false);
byte[] vulRequest = buildHttpRequest(message, WORD, ext, false);
byte[] vulResponse = retrieveResponseBody(message.getHttpService(), vulRequest);

boolean eq = testSimilar(new String(extResponse), new String(vulResponse)); //= new String(extResponse).equals(new String(vulResponse));
boolean eq = testSimilar(new String(extResponse), new String(vulResponse));
if (!eq) {
BurpExtender.print("Request is not vulnerable.");
BurpExtender.print(ext + " cached adding extension to list");
} else {
BurpExtender.print("Request is not vulnerable, no caching.");
}

return eq;
}

Expand Down Expand Up @@ -132,14 +133,14 @@ private static byte[] buildHttpRequest(final IHttpRequestResponse reqRes, final
return result;
}

private static byte[] retrieveResponseBody(IHttpService service, byte[] request, boolean checkResponseCode) {
private static byte[] retrieveResponseBody(IHttpService service, byte[] request) {
byte[] result = null;

IHttpRequestResponse test = BurpExtender.getCallbacks().makeHttpRequest(service, request);
byte[] res = test.getResponse();
IResponseInfo responseInfo = BurpExtender.getHelpers().analyzeResponse(res);

if (checkResponseCode && responseInfo.getStatusCode() == 200) {
if (responseInfo.getBodyOffset() > 0) {
int len = res.length - responseInfo.getBodyOffset();
result = new byte[len];
System.arraycopy(res, responseInfo.getBodyOffset(), result, 0, len);
Expand Down Expand Up @@ -196,8 +197,7 @@ private static String createNewUrl(String url, String additional, String extensi
}

/**
* Testing if the responses of two requests are similar. This is the not the same as the same, rather there is a
* threshold set in the static parameters of the class.
* Testing if the responses of two requests are similar. This is the not the same as equals, but below a static threshold
* @param firstString
* @param secondString
* @return Test if similar
Expand All @@ -208,7 +208,7 @@ private static boolean testSimilar(String firstString, String secondString) {
int levenDist = StringUtils.getLevenshteinDistance(firstString, secondString);

// BurpExtender.print("============================================");
// BurpExtender.print("Fuzzy Distance:" + fuzzyDist);
// BurpExtender.print(" Fuzzy Distance:" + fuzzyDist);
// BurpExtender.print(" Jaro Winkler Distance:" + jaroDist);
// BurpExtender.print(" Levenshtein Distance:" + levenDist);
// BurpExtender.print("============================================");
Expand Down