Skip to content

Commit

Permalink
v1.12 - Adding logging to the console. Dependency confusion now has a…
Browse files Browse the repository at this point in the history
… new approach to detect internally disclosed NPM package names.
  • Loading branch information
minamo7sen committed Sep 26, 2021
1 parent 7f9d02e commit bd9ad2a
Show file tree
Hide file tree
Showing 8 changed files with 346 additions and 158 deletions.
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Burp JS-Miner Changelog
Notable changes in JS-Miner releases. Other code improvements that usually happen with every release are not mentioned.

## [1.12] - 2021-09-26
- Added logging to the extension console.
- Only enabled for invoked tasks through the context menu items. (Not enabled for Burp's passive scan)
- Added a new approach to identify internally disclosed NPM package names.
- For this approach, "css" files are also scanned as they are a potential location for this type of disclosure.

## [1.11] - 2021-09-19
- Improving the Subdomains scanner.

## [1.1] - 2021-09-08
- Added Dependency Confusion (passive scan)
- Added Inline Base64 Source Mapper (passive scan)

## [1.0] - 2021-08-22
- Initial release
9 changes: 6 additions & 3 deletions src/main/java/burp/BurpExtender.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ public class BurpExtender implements IBurpExtender, IContextMenuFactory, IExtens
static PrintWriter mStdOut;
static PrintWriter mStdErr;
public static final String EXTENSION_NAME = "JS Miner";
private static final String EXTENSION_VERSION = "1.11";
private static final String EXTENSION_VERSION = "1.12";
private static int taskCount = 0; // counter for invoked tasks through the menu items context (Not for Burp's passive scan)

// Exposing callbacks for use in other classes
public static IBurpExtenderCallbacks getCallbacks() {
Expand Down Expand Up @@ -134,7 +135,8 @@ static void handleTargets(IHttpRequestResponse[] siteMapReqResArray, boolean sou
// If host is in the list, add to our unique targets & scan it
if (!uniqueTargets.contains(host)) {
uniqueTargets.add(host);
new JSMinerScan(httpReqRes, sourceMapScan, findInterestingStuffScan);
taskCount++;
new JSMinerScan(httpReqRes, taskCount, sourceMapScan, findInterestingStuffScan);
}
}

Expand All @@ -143,7 +145,8 @@ static void handleTargets(IHttpRequestResponse[] siteMapReqResArray, boolean sou

@Override
public List<IScanIssue> doPassiveScan(IHttpRequestResponse baseRequestResponse) {
new Thread(() -> new JSMinerScan(baseRequestResponse, false, true)).start();
// taskId: -1 -> no logging for passive scans
new Thread(() -> new JSMinerScan(baseRequestResponse, -1, false, true)).start();
return null;
}

Expand Down
103 changes: 103 additions & 0 deletions src/main/java/burp/Constants.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package burp;

import java.util.regex.Pattern;

public class Constants {

private Constants() {}

// Logging constants
public static final String LOG_FORMAT = "%-15s%-15s%-40s%-40s%n";
public static final String LOG_TIME_STAMP_STRING = "Task timestamp: ";
public static final String LOG_TASK_ID_PREFIX = " Task ID: ";
public static final String SCANNER_NAME_SOURCE_MAPPER = "Source Mapper Active Scan";
public static final String SCANNER_NAME_INTERESTING_STUFF = "Find Interesting Stuff Scan";
public static final String SCANNER_NAME_CLOUD_URLS = "Cloud URLs Scanner";
public static final String SCANNER_NAME_DEPENDENCY_CONFUSION = "Dependency Confusion Scanner";
public static final String SCANNER_NAME_INLINE_SOURCE_MAPS = "Inline JS Source Maps Scanner";
public static final String SCANNER_NAME_SECRETS = "Secrets Scanner";
public static final String SCANNER_NAME_SUBDOMAINS = "Subdomains Scanner";
public static final String SCAN_STATUS_ADDED = "QUEUED";
public static final String SCAN_STATUS_RUNNING = "STARTED";
public static final String SCAN_STATUS_COMPLETED = "COMPLETED";
public static final String SCAN_STATUS_FAILED = "FAILED";

// Regexes
public static final String WHITE_SPACES = "(\\s*)";
public static final String REGEX_QUOTES = "['\"`]";

public static final Pattern CLOUD_URLS_REGEX = Pattern.compile("([\\w]+[.]){1,10}" + // get up to 10 subdomain levels
"(s3.amazonaws.com|rds.amazonaws.com|cache.amazonaws.com|" + // AWS
"blob.core.windows.net|onedrive.live.com|1drv.com|" + // Azure
"storage.googleapis.com|storage.cloud.google.com|storage-download.googleapis.com|content-storage-upload.googleapis.com|content-storage-download.googleapis.com|" + // Google
"cloudfront.net|" +
"digitaloceanspaces.com|" +
"oraclecloud.com|" +
"aliyuncs.com|" + // Ali baba
"firebaseio.com|" + // Firebase
"rackcdn.com|" +
"objects.cdn.dream.io|objects-us-west-1.dream.io)",
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);

// Inspired by: https://github.com/nsonaniya2010/SubDomainizer/blob/master/SubDomainizer.py
public static final Pattern SECRETS_REGEX = Pattern.compile(("['\"`]?(\\w*)" + // Starts with a quote then a word / white spaces
WHITE_SPACES +
"(secret|token|password|passwd|authorization|bearer|aws_access_key_id|aws_secret_access_key|irc_pass|SLACK_BOT_TOKEN|id_dsa" +
"secret[_-]?(key|token|secret)|" +
"api[_-]?(key|token|secret)|" +
"access[_-]?(key|token|secret)|" +
"auth[_-]?(key|token|secret)|" +
"session[_-]?(key|token|secret)|" +
"consumer[_-]?(key|token|secret)|" +
"public[_-]?(key|token|secret)|" +
"client[_-]?(id|token|key)|" +
"ssh[_-]?key|" +
"encrypt[_-]?(secret|key)|" +
"decrypt[_-]?(secret|key)|" +
"github[_-]?(key|token|secret)|" +
"slack[_-]?token)" +
"(\\w*)" + // in case there are any characters / white spaces
WHITE_SPACES +
"['\"`]?" + // closing quote for variable name
WHITE_SPACES +// white spaces
"[:=]+[:=>]?" +// assignments operation
WHITE_SPACES +
REGEX_QUOTES + // opening quote for secret
WHITE_SPACES +
"([\\w\\-/~!@#$%^&*+]+)" + // Assuming secrets will be alphanumeric with some special characters
WHITE_SPACES +
REGEX_QUOTES // closing quote for secrets
),
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);

public static final Pattern b64SourceMapRegex = Pattern.compile("sourceMappingURL=data(.*)json(.*)base64,((?:[a-z0-9+/]{4})*(?:[a-z0-9+/]{2}==|[a-z0-9+/]{3}=)?)(\\\\n)?",
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);

public static final Pattern EXTRACT_DEPENDENCIES_REGEX = Pattern.compile((
"dependencies" + // we don't care about prefix. Once we find this, just check what comes next
"([a-z-_0-9])*" + // some suffix may be (e.g.: dependenciesDev1_2-3)
REGEX_QUOTES + // closing quote
":" + // mandatory colon
"\\{" + // mandatory opening curly brackets
"(.*?)" + // our dependencies list -> matcher.group(2)
"}" // mandatory closing curly brackets
),
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);

public static final Pattern extractFromNodeModules = Pattern.compile(("/node_modules/(.*?)/"));

// Scan issues related constants
public static final String SCAN_ISSUE_HEADER = "This issue was generated by \"" + BurpExtender.EXTENSION_NAME + "\" Burp extension.<br><br>";
public static final String CONFIDENCE_CERTAIN = "Certain";
public static final String CONFIDENCE_TENTATIVE = "Tentative";
public static final String CONFIDENCE_FIRM = "Firm";
public static final String SEVERITY_INFORMATION = "Information";
public static final String SEVERITY_MEDIUM = "Medium";
public static final String SEVERITY_HIGH = "High";
public static final String HTML_LIST_OPEN = "<ul>";
public static final String HTML_LIST_BULLET_OPEN = "<li> ";
public static final String HTML_LIST_BULLET_CLOSED = "</li>";
public static final String HTML_LIST_CLOSED = "</ul>";


}
Loading

0 comments on commit bd9ad2a

Please sign in to comment.