diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index 0bf8c72..5ab4b15 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -12,16 +12,10 @@
-
-
-
-
-
-
-
-
+
+
@@ -85,35 +79,11 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
@@ -124,125 +94,78 @@
+
+
-
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
+
+
-
-
-
-
-
-
+
+
-
+
-
-
+
+
-
-
+
+
+
+
+
+
@@ -276,6 +199,7 @@
rest
join
This may be a json
+ base64
C:\Projects\burp-paramalyzer\src\com\professionallyevil\bc
@@ -328,13 +252,13 @@
-
-
+
-
-
+
+
+
@@ -344,8 +268,8 @@
-
-
+
+
@@ -389,6 +313,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
@@ -694,8 +630,8 @@
-
+
@@ -1059,12 +995,12 @@
-
+
-
+
@@ -1078,7 +1014,7 @@
-
+
@@ -1503,34 +1439,10 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
@@ -1538,35 +1450,20 @@
-
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
+
@@ -1577,24 +1474,51 @@
+
+
-
+
-
-
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1722,8 +1646,8 @@
diff --git a/src/com/professionallyevil/bc/CorrelatedParam.java b/src/com/professionallyevil/bc/CorrelatedParam.java
index 03596f4..16de9e4 100644
--- a/src/com/professionallyevil/bc/CorrelatedParam.java
+++ b/src/com/professionallyevil/bc/CorrelatedParam.java
@@ -143,7 +143,14 @@ public String getAnalysisText(ParamInstance pi, IBurpExtenderCallbacks callbacks
if(analysisText.containsKey(pi)) {
return analysisText.get(pi);
} else {
- String text = ParamAnalyzer.analyze(pi, callbacks);
+ String text = "";
+ if (pi instanceof JSONParamInstance) {
+ String logPrefix = "This parameter was derived from a JSON object: "+ ((JSONParamInstance)pi).getParent().getName()+"\n";
+ text = ParamAnalyzer.analyze(pi, callbacks, logPrefix);
+ } else {
+ text = ParamAnalyzer.analyze(pi, callbacks);
+ }
+
analysisText.put(pi, text);
return text;
}
diff --git a/src/com/professionallyevil/bc/CorrelatorEngine.java b/src/com/professionallyevil/bc/CorrelatorEngine.java
index 7fa3da3..fc0ca16 100644
--- a/src/com/professionallyevil/bc/CorrelatorEngine.java
+++ b/src/com/professionallyevil/bc/CorrelatorEngine.java
@@ -202,7 +202,7 @@ private void parameterFormatAnalysis() {
private void processJSON(CorrelatedParam cp) {
for(ParamInstance param: cp.uniqueParamInstances) {
- if(param.getFormat() == ParamInstance.Format.JSON) {
+ if(param.getFormat() == ParamInstance.Format.JSON || param.getFormat() == ParamInstance.Format.JWT) {
List jsonParams = JSONParamParser.parseObjectString(param.decodedValue, param);
for(JSONParamInstance jsonParam: jsonParams) {
if (jsonPartParameters.containsKey(jsonParam.getName())) {
diff --git a/src/com/professionallyevil/bc/JSONParamInstance.java b/src/com/professionallyevil/bc/JSONParamInstance.java
index dafdfec..ed122b2 100644
--- a/src/com/professionallyevil/bc/JSONParamInstance.java
+++ b/src/com/professionallyevil/bc/JSONParamInstance.java
@@ -38,6 +38,10 @@ public byte getType() {
return TYPE;
}
+ public ParamInstance getParent() {
+ return parent;
+ }
+
@Override
public String getName() {
return paramName;
diff --git a/src/com/professionallyevil/bc/JSONParamParser.java b/src/com/professionallyevil/bc/JSONParamParser.java
index fd1afec..c1bf3e2 100644
--- a/src/com/professionallyevil/bc/JSONParamParser.java
+++ b/src/com/professionallyevil/bc/JSONParamParser.java
@@ -27,7 +27,7 @@
class JSONParamParser {
enum JSONValue {
- OBJECT("^\\{(\\s*\"([^\\\"^\\\\^\\p{Cntrl}]+)\"\\s*:(\\s*((-?\\d+)|(\"[^\\\"^\\\\^\\p{Cntrl}]*\")|true|false|null|\\[.*\\]|\\{.*\\})\\s*))(,\\s*\"([^\\\"^\\\\^\\p{Cntrl}]*)\"\\s*:(\\s*((\\-?d+)|(\"[^\\\"^\\\\^\\p{Cntrl}]*\")|true|false|null|\\[.*\\]|\\{.*\\})\\s*))*\\}$");
+ OBJECT("^\\{(\\s*\"([^\\\"^\\\\^\\p{Cntrl}]+)\"\\s*:(\\s*((-?\\d+)|(\"[^\\\"^\\\\^\\p{Cntrl}]*\")|true|false|null|\\[.*\\]|\\{.*\\})\\s*))(,\\s*\"([^\\\"^\\\\^\\p{Cntrl}]*)\"\\s*:(\\s*((-?\\d+)|(\"[^\\\"^\\\\^\\p{Cntrl}]*\")|true|false|null|\\[.*\\]|\\{.*\\})\\s*))*\\}$");
private String regex;
diff --git a/src/com/professionallyevil/bc/ParamAnalyzer.java b/src/com/professionallyevil/bc/ParamAnalyzer.java
index da70cb0..e552127 100644
--- a/src/com/professionallyevil/bc/ParamAnalyzer.java
+++ b/src/com/professionallyevil/bc/ParamAnalyzer.java
@@ -47,7 +47,8 @@ enum ValuePattern {
JSON_VALUE_QUICK("^(\\s*((\\d+)|(\"[\\w ]*\")|true|false|null|\\[.*\\]|\\{.*\\})\\s*)$", "PRINTABLE_CHARS"),
JSON_OBJECT(JSONParamParser.JSONValue.OBJECT.getRegex(), "PRINTABLE_CHARS", "JSON_VALUE_QUICK"),
PHP_SERIALIZED_QUICK("^([si]:\\d+:\\w+?;)(N;)|[oa]:\\d+:.*\\{.*}$"),
- PHP_SERIALIZED("^((s:\\d+:\".*\";)|(i:\\d+;)|(N;)|(a:\\d+:\\{((s:\\d+:\".*?\";)|(i:\\d+;)|(N;)|(o:\\d+:\"[a-z0-9_]+\":\\d+:\\{((s:\\d+:\".*?\";)|(i:\\d+;)|(N;))*}))*})|(o:\\d+:\"[a-z0-9_]+\":\\d+:\\{((s:\\d+:\".*?\";)|(i:\\d+;)|(N;))*}))$");
+ PHP_SERIALIZED("^((s:\\d+:\".*\";)|(i:\\d+;)|(N;)|(a:\\d+:\\{((s:\\d+:\".*?\";)|(i:\\d+;)|(N;)|(o:\\d+:\"[a-z0-9_]+\":\\d+:\\{((s:\\d+:\".*?\";)|(i:\\d+;)|(N;))*}))*})|(o:\\d+:\"[a-z0-9_]+\":\\d+:\\{((s:\\d+:\".*?\";)|(i:\\d+;)|(N;))*}))$"),
+ JWT("^[A-Za-z0-9-_=]+\\.[A-Za-z0-9-_=]+\\.?[A-Za-z0-9-_.+/=]*$", "PRINTABLE_CHARS");
private Pattern pattern;
@@ -85,6 +86,10 @@ public static boolean isBase62Encoded(String testValue) {
}
static String analyze(ParamInstance pi, IBurpExtenderCallbacks callbacks) {
+ return analyze(pi, callbacks, "");
+ }
+
+ static String analyze(ParamInstance pi, IBurpExtenderCallbacks callbacks, String logPrefix) {
try {
String value = pi.getValue();
if (value.isEmpty() || "[EMPTY]".equals(value)) {
@@ -96,7 +101,7 @@ static String analyze(ParamInstance pi, IBurpExtenderCallbacks callbacks) {
return "Appears to be a BigIP value: " + value + "\nDecodes to: " + decodeBigIP(pi, value);
}
- StringBuilder smartDecodeLog = new StringBuilder();
+ StringBuilder smartDecodeLog = new StringBuilder(logPrefix);
String currentValue = value;
String lastValue = "";
while (!lastValue.equals(currentValue)) {
@@ -165,7 +170,17 @@ private static String smartDecode(ParamInstance pi, String input, IBurpExtenderC
log.append("\n");
log.append(identify(pi, input));
return input;
- }else if(ValuePattern.BASE64_ENCODED.matches(input)) {
+ } else if(ValuePattern.JWT.matches(input)) {
+ String[] parts = input.split("[\\.]");
+ byte[] algorithmBytes = callbacks.getHelpers().base64Decode(parts[0]);
+ String algorithm = callbacks.getHelpers().bytesToString(algorithmBytes);
+ byte[] decodedBytes = callbacks.getHelpers().base64Decode(parts[1]);
+ String decodedString = callbacks.getHelpers().bytesToString(decodedBytes);
+ pi.setFormat(ParamInstance.Format.JWT);
+ log.append("\nLooks to be a JWT: \n The algorithm section is: \n").append(algorithm);
+ log.append("\n The body section is: \n").append(decodedString);
+ return decodedString;
+ } else if(ValuePattern.BASE64_ENCODED.matches(input)) {
byte[] decodedBytes = callbacks.getHelpers().base64Decode(input);
String decodedString = callbacks.getHelpers().bytesToString(decodedBytes);
if(ValuePattern.PRINTABLE_CHARS.matches(decodedString)) {
@@ -187,6 +202,7 @@ private static String smartDecode(ParamInstance pi, String input, IBurpExtenderC
}
}
+
private static String identify(ParamInstance pi, String input) {
StringBuilder log = new StringBuilder();
if (isCreditCard(input)) {
@@ -254,7 +270,9 @@ private static String identify(ParamInstance pi, String input) {
pi.setFormat(ParamInstance.Format.HTMLFRAG);
} else if (ValuePattern.JSON_OBJECT.matches(input)) {
log.append("\nThis may be a JSON-formatted String.");
- pi.setFormat(ParamInstance.Format.JSON);
+ if (pi.getFormat() != ParamInstance.Format.JWT) {
+ pi.setFormat(ParamInstance.Format.JSON);
+ }
} else {
pi.setFormat(ParamInstance.Format.PRINTABLE);
}
@@ -421,6 +439,11 @@ public static void main(String[] args) {
test("JSON 2", "{\"foo\": {\"foo1\": [1,2,3]}}", ValuePattern.JSON_OBJECT);
test("JSON 3", "{\"foo\": \"bar\", \"foo2\": [42, 99], \"foo3\": {\"secret1\": \"4242-4242-4242-4242\", \"secret2\": false}}", ValuePattern.JSON_OBJECT);
test("JSON 4", "{\"secret1\": \"4242-4242-4242-4242\", \"secret2\": false}", ValuePattern.JSON_OBJECT);
+ test("JWT 1", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6Ikphc29uIEdpbGxhbSIsInNlY3JldCI6NDJ9.Yo-96trF4CAU_v-mrJLYuqigEGC3QBDul7C41RM2RL4", ValuePattern.JWT);
+ test("JSON 5", "{\"sub\":\"1234567890\",\"name\":\"Jason Gillam\",\"secret\":42}", ValuePattern.JSON_OBJECT);
+
+
+
}
}
diff --git a/src/com/professionallyevil/bc/ParamInstance.java b/src/com/professionallyevil/bc/ParamInstance.java
index 173972f..7e98b2d 100644
--- a/src/com/professionallyevil/bc/ParamInstance.java
+++ b/src/com/professionallyevil/bc/ParamInstance.java
@@ -44,7 +44,8 @@ enum Format {
HTMLFRAG("XML/HTML"),
EMPTY("Empty"),
JSON("JSON Object"),
- PHP("PHP Serialized");
+ PHP("PHP Serialized"),
+ JWT("JWT");
private String title;