Skip to content

Commit

Permalink
Added full JSON Parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
JGillam committed Sep 22, 2019
1 parent 13dc2d2 commit d39733f
Show file tree
Hide file tree
Showing 12 changed files with 951 additions and 766 deletions.
1 change: 1 addition & 0 deletions .idea/artifacts/burp_paramalyzer.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1,262 changes: 607 additions & 655 deletions .idea/workspace.xml

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ repositories {
dependencies {
compile 'net.portswigger.burp.extender:burp-extender-api:1.7.13'
compile 'com.intellij:forms_rt:7.0.3'
compile group: 'org.json', name: 'json', version: '20190722'
}

sourceSets {
Expand Down
13 changes: 13 additions & 0 deletions src/com/professionallyevil/bc/CorrelatedParam.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ public class CorrelatedParam {
put(param, message, requestInfo, responseString, helpers);
}

CorrelatedParam(JSONParamInstance param) {
put(param);
}


public void put(IParameter param, IHttpRequestResponse message, IRequestInfo requestInfo, String responseString,
IExtensionHelpers helpers) {
Expand Down Expand Up @@ -72,6 +76,15 @@ public void put(RestParamInstance param, IHttpRequestResponse message, IRequestI
checkReflection(param, responseString, helpers);
}

public void put(JSONParamInstance param) {
paramInstances.add(param);
String value = param.getValue();
if(!uniqueValues.contains(value)) {
uniqueValues.add(value);
uniqueParamInstances.add(param);
}
}

private void addURL(IRequestInfo requestInfo) {
String externalForm = requestInfo.getUrl().toExternalForm();
int paramStart = externalForm.indexOf('?');
Expand Down
28 changes: 28 additions & 0 deletions src/com/professionallyevil/bc/CorrelatorEngine.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public class CorrelatorEngine extends SwingWorker<String, Object> {
Map<String, CorrelatedParam> cookieParameters = new HashMap<>();
Map<String, CorrelatedParam> jsonParameters = new HashMap<>();
Map<String, CorrelatedParam> restParameters = new HashMap<>();
Map<String, CorrelatedParam> jsonPartParameters = new HashMap<>();
Set<IHttpRequestResponse> inScopeMessagesWithResponses = new HashSet<>();
Map<String, CookieStatistics> cookieStatistics = new TreeMap<>();

Expand Down Expand Up @@ -162,29 +163,56 @@ private void parameterFormatAnalysis() {
publish(0);
for(CorrelatedParam cp: urlParameters.values()){
cp.analyzeAll(callbacks);
processJSON(cp);
i+=1;
publish(100*i/total);
}
for(CorrelatedParam cp: bodyParameters.values()){
cp.analyzeAll(callbacks);
processJSON(cp);
i+=1;
publish(100*i/total);
}
for(CorrelatedParam cp: cookieParameters.values()){
cp.analyzeAll(callbacks);
processJSON(cp);
i+=1;
publish(100*i/total);
}
for(CorrelatedParam cp: jsonParameters.values()){
cp.analyzeAll(callbacks);
processJSON(cp);
i+=1;
publish(100*i/total);
}
for(CorrelatedParam cp: restParameters.values()){
cp.analyzeAll(callbacks);
processJSON(cp);
i+=1;
publish(100*i/total);
}

for(CorrelatedParam cp: jsonPartParameters.values()) {
publish("Analyzing JSON params...");
cp.analyzeAll(callbacks);
}

jsonParameters.putAll(jsonPartParameters);
}

private void processJSON(CorrelatedParam cp) {
for(ParamInstance param: cp.uniqueParamInstances) {
if(param.getFormat() == ParamInstance.Format.JSON) {
List<JSONParamInstance> jsonParams = JSONParamParser.parseObjectString(param.decodedValue, param);
for(JSONParamInstance jsonParam: jsonParams) {
if (jsonPartParameters.containsKey(jsonParam.getName())) {
jsonPartParameters.get(jsonParam.getName()).put(jsonParam);
} else {
jsonPartParameters.put(jsonParam.getName(), new CorrelatedParam(jsonParam));
}
}
}
}
}

private void secondPass(IExtensionHelpers helpers) {
Expand Down
2 changes: 1 addition & 1 deletion src/com/professionallyevil/bc/DeepAnalysisTab.form
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
<properties/>
<border type="etched" title="Matches"/>
<children>
<component id="f467a" class="javax.swing.JList" binding="listMatches" custom-create="true">
<component id="f467a" class="javax.swing.JList" binding="listMatches">
<constraints/>
<properties>
<selectionMode value="0"/>
Expand Down
17 changes: 1 addition & 16 deletions src/com/professionallyevil/bc/DeepAnalysisTab.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public class DeepAnalysisTab implements WorkerStatusListener {
DeepAnalysisTab(ParamInstance pi, Paramalyzer parent, IBurpExtenderCallbacks callbacks) {
this.parent = parent;
this.callbacks = callbacks;
titleLabel.setText("Deep Analysis: [" + pi.getTypeName() + "] " + pi.getName() + " = " + pi.getDecodedValue() + " (Inferred Format: "+pi.getFormat()+")");
titleLabel.setText("Deep Analysis: [" + pi.getTypeName() + "] " + pi.getName() + " = " + pi.getDecodedValue() + "\n (Inferred Format: " + pi.getFormat() + ")");
closeButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Expand All @@ -63,26 +63,11 @@ public void actionPerformed(ActionEvent e) {

listMatches.setModel(listModel);

// listMatches.setCellRenderer(new DefaultListCellRenderer() {
// @Override
// public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
// if (value instanceof ParamInstance) {
// String title = "--" + ((ParamInstance) value).summarize();
// return super.getListCellRendererComponent(list, title, index, isSelected, cellHasFocus);
// } else {
// return super.getListCellRendererComponent(list, "+" + value, index, isSelected, cellHasFocus);
// }
// }
//
//
// });

textDetails.setText("Processing...");
analyzer = new DeepAnalyzer(pi, ((ParametersTableModel) parent.parametersTable.getModel()).getEntries(), callbacks, this);
listMatches.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
// ParamInstance pi = (ParamInstance) listMatches.getSelectedValue();
ParamInstance pi = (ParamInstance) listModel.getParamInstanceAt(listMatches.getSelectedIndex());
textDetails.setText(analyzer.getResultsMap().get(pi));
}
Expand Down
76 changes: 76 additions & 0 deletions src/com/professionallyevil/bc/JSONParamInstance.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* Copyright (c) 2019 Jason Gillam
*
* 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.professionallyevil.bc;

import burp.IHttpRequestResponse;

public class JSONParamInstance extends ParamInstance {

private String paramName;
private String paramValue;
private ParamInstance parent;
static final byte TYPE = 64;

public JSONParamInstance(String name, String value, ParamInstance parent) {
super(null, parent.getMessage());
this.paramName = name;
String[] parts = value.split("\n\r");
this.paramValue = String.join(" ", parts);
this.parent = parent;
}

@Override
public byte getType() {
return TYPE;
}

@Override
public String getName() {
return paramName;
}

@Override
public String getValue() {
return paramValue;
}

@Override
public int getNameStart() {
return parent.getNameStart();
}

@Override
public int getNameEnd() {
return parent.getNameEnd();
}

@Override
public int getValueStart() {
return parent.getValueStart();
}

@Override
public int getValueEnd() {
return parent.getValueEnd();
}

@Override
public IHttpRequestResponse getMessage() {
return parent.getMessage();
}

}
108 changes: 108 additions & 0 deletions src/com/professionallyevil/bc/JSONParamParser.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/*
* Copyright (c) 2019 Jason Gillam
*
* 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.professionallyevil.bc;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

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*))*\\}$");


private String regex;
private Pattern pattern;

JSONValue(String regex) {
this.regex = regex;
this.pattern = Pattern.compile(regex);
}

String getRegex(){
return regex;
}

Pattern getPattern() {
return pattern;
}
}

private static void parseValue(List<JSONParamInstance> paramList, ParamInstance parent, String key, Object value) {
if (value instanceof JSONObject) {
parseObject((JSONObject)value, paramList, parent);
paramList.add(new JSONParamInstance(key, value.toString(), parent));
} else if (value instanceof JSONArray) {
parseArray((JSONArray)value, key, paramList, parent);
paramList.add(new JSONParamInstance(key, value.toString(), parent));
} else if (value instanceof String) {
paramList.add(new JSONParamInstance(key, (String)value, parent));
} else if (value instanceof Integer) {
try {
paramList.add(new JSONParamInstance(key, Integer.toString((Integer)value), parent));
} catch (Exception e) {
e.printStackTrace();
}
} else if (value instanceof Boolean) {
paramList.add(new JSONParamInstance(key, Boolean.toString((Boolean)value), parent));
}
}

private static void parseObject(JSONObject jsonObject, List<JSONParamInstance> paramList, ParamInstance parent) {
for(String key: jsonObject.keySet()) {
Object value = jsonObject.get(key);
parseValue(paramList, parent, key, value);
}
}

private static void parseArray(JSONArray array, String key, List<JSONParamInstance> paramList, ParamInstance parent) {
for(Object value: array) {
parseValue(paramList, parent, key, value);
}
}

static List<JSONParamInstance> parseObjectString(String jsonString, ParamInstance parent){
List<JSONParamInstance> paramList = new ArrayList<>();

try {
JSONObject jo = new JSONObject(jsonString);
parseObject(jo, paramList, parent);
} catch (JSONException e) {
// skip
}

return paramList;

}

// public static void main(String[] args) {
// parseObjectString("{\"foo\":\"bar\"}");
// parseObjectString("{\"foo\":-42}");
// parseObjectString("{\"foo\":[\"foo bar\", -42]}");
// parseObjectString("{\"foo\": true}");
// parseObjectString("{\"foo\": null}");
// parseObjectString("{\"foo\": {\"bar\": \"foo2\"}}");
// parseObjectString("{\"foo\":\"bar\" ,\"foo2\":\"bar2\",\"foo3\":\"bar3\",\"foo4\":\"bar4\"}");
// parseObjectString("not a json object");
// }

}
Loading

0 comments on commit d39733f

Please sign in to comment.