Skip to content

Commit

Permalink
Fixed bugs (url decoding + changing order of jwt headers)
Browse files Browse the repository at this point in the history
- Url decoding of a variable didn't consider the character "+" that is converted to space when url decoded
- Changing the order of the jwt headers now doesn't replace the original jwt
  • Loading branch information
mattebit committed Sep 21, 2023
1 parent ecc3c84 commit a44f4f4
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 4 deletions.
2 changes: 1 addition & 1 deletion doc/language.md
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,7 @@ The Checks tag inside an operation has a list of Check elements, which can be de
> Note that `check` accepts only the `is present` tag.
> Note that by default, all the values read from a message (only message, not json) are URL-decoded before the checks are executed. You can disable this behaviour by using `url decode` = false
> Note that by default, all the values read from a message that contains url-encoded values (only message, not json) are URL-decoded before the checks are executed. You can disable this behaviour by using `url decode` = false
In passive tests the checks's result are intended as the entire test result, so all the checks has to pass to have a successfull test.

Expand Down
11 changes: 9 additions & 2 deletions tool/src/main/java/migt/Check.java
Original file line number Diff line number Diff line change
Expand Up @@ -253,8 +253,15 @@ private boolean execute_http(HTTPReqRes message,
}

// URL-decode matched content
//if (url_decode)
// msg_str = URLDecoder.decode(msg_str, StandardCharsets.UTF_8);
// when a string contains a "+" character then, it is replaced with a space.
if (url_decode) {
Pattern p = Pattern.compile("%[0-9a-fA-F]{2}");
Matcher m = p.matcher(op_val);
if (m.find()) {
// if the content contains url-encoded characters then, url-decode the content
op_val = URLDecoder.decode(op_val, StandardCharsets.UTF_8);
}
}

// if a regex is present, execute it
if (!regex.equals("")) {
Expand Down
10 changes: 9 additions & 1 deletion tool/src/main/java/migt/JWT.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import java.text.ParseException;
import java.util.Base64;

import static migt.Tools.check_json_strings_equals;


/**
* Class to manage JWT tokens
Expand All @@ -17,6 +19,7 @@
*/
public class JWT {
public String header;
public String header_original;
public String payload;
public String signature;
public String raw;
Expand Down Expand Up @@ -99,6 +102,7 @@ public void parse(String raw_jwt) throws ParsingException {

try {
header = parsed_jwt.getHeader().toString();
header_original = parsed_jwt.getParsedParts()[0].toString();
payload = parsed_jwt.getPayload().toString();
signature = parsed_jwt instanceof JWSObject ?
((JWSObject) parsed_jwt).getSignature().toString() : null;
Expand Down Expand Up @@ -163,7 +167,11 @@ public String build() throws ParsingException {
if (this.header.equals("") || this.payload.equals(""))
throw new ParsingException("error in building jwt, empty values");

res += Base64.getEncoder().encodeToString(header.getBytes());
if (check_json_strings_equals(header, new String(Base64.getDecoder().decode(header_original)))) {
res += header_original;
} else {
res += Base64.getEncoder().encodeToString(header.getBytes());
}
res += "." + Base64.getEncoder().encodeToString(payload.getBytes());

if (sign) {
Expand Down
17 changes: 17 additions & 0 deletions tool/src/main/java/migt/Tools.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package migt;

import burp.IExtensionHelpers;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.PathNotFoundException;
import org.json.JSONArray;
import org.json.JSONObject;


import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
Expand Down Expand Up @@ -866,4 +869,18 @@ public static String editJson(EditOperation.Jwt_action action,
}
return Configuration.defaultConfiguration().jsonProvider().toJson(document); //basically converts to string
}

/**
* Checks that the json resulting by parsing the two strings is equals. Equals in this case means that the same keys
* and values are present, but the order is ignored
* @param s1 the string 1
* @param s2 the string 2
* @return true or false depending if the json parsing of the two strings is the same or not
*/
public static boolean check_json_strings_equals(String s1, String s2) {
JsonElement o1 = JsonParser.parseString(s1);
JsonElement o2 = JsonParser.parseString(s2);

return o1.equals(o2);
}
}
30 changes: 30 additions & 0 deletions tool/src/test/java/JWT_Test.java
Original file line number Diff line number Diff line change
Expand Up @@ -410,4 +410,34 @@ void test_decodeRawJwt() {
out);
}
*/

@Test
@DisplayName("Testing jwt decode and encode")
void test_jwt_parse_change_order() {
JWT j = new JWT();
boolean errors = false;
try {
j.parse(raw_jwt);

j.header = "{\"alg\":\"RS256\", \"typ\":\"JWT\"}"; // invert header keys

String out = j.build();
assertEquals(raw_jwt, out);
String[] splitted = out.split("\\.");

assertEquals(3, splitted.length);

assertEquals(raw_header, splitted[0]);
assertEquals(raw_payload, splitted[1]);
assertEquals(raw_signature, splitted[2]);

//assertEquals(raw_header, j.header);
//assertEquals(raw_payload, j.payload);
//assertEquals(raw_signature, j.signature);
} catch (ParsingException e) {
errors = true;
}
assertFalse(errors);
}

}
11 changes: 11 additions & 0 deletions tool/src/test/java/Utils_Test.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import migt.*;
import org.json.JSONObject;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

Expand Down Expand Up @@ -193,4 +194,14 @@ void executeSessioOps_test() throws ParsingException {
assertEquals(1, 0);
}
}

@Test
void test_check_json_strings_equals() {
boolean res = Tools.check_json_strings_equals(
"{a : {a : 2}, b : 2}",
"{b : 2, a : {a : 2}}"
);

assertEquals(true, res);
}
}

0 comments on commit a44f4f4

Please sign in to comment.