Skip to content

Commit

Permalink
Proper handling of non-basic-Latin Unicode characters in body and URI
Browse files Browse the repository at this point in the history
  • Loading branch information
AndreyRainchik committed Nov 26, 2019
1 parent b918c6b commit eac2a53
Showing 1 changed file with 80 additions and 7 deletions.
87 changes: 80 additions & 7 deletions src/main/java/burp/Utility.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,10 @@
import java.net.URI;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.Collator;
import java.util.regex.Pattern;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Utility {

Expand Down Expand Up @@ -93,22 +92,49 @@ public static byte[] signRequest(IHttpRequestResponse messageInfo,
for (String signedHeader : signedHeaderList){
canonicalHeaders.append(signedHeader.toLowerCase()).append(':').append(headerMap.get(signedHeader)).append('\n');
}

//pw.println(canonicalHeaders.toString());
byte[] request = messageInfo.getRequest();
String body = "";
String notUnicode = "[^\\u0000-\\u007F]+";
String payloadHash;

if (!requestInfo.getMethod().equals("GET")){

int bodyOffset = requestInfo.getBodyOffset();
body = new String(request, bodyOffset, request.length - bodyOffset, "UTF-8").trim();
body = hexToString(bytesToHex(Arrays.copyOfRange(request, bodyOffset, request.length)));
if(!body.matches(notUnicode)) {
char[] chars = body.toCharArray();
String sanitize = "";
for (int i = 0; i < chars.length; ++i) {
String test = Character.toString(chars[i]);
if (Pattern.matches(notUnicode, test)) {
sanitize = sanitize.concat(URLEncoder.encode(test, StandardCharsets.UTF_8.toString()));
} else {
sanitize = sanitize.concat(test);
}
}
body = sanitize;
}
payloadHash = Hashing.sha256().hashString(body, StandardCharsets.UTF_8).toString().toLowerCase();

} else {
payloadHash = Hashing.sha256().hashString("", StandardCharsets.UTF_8).toString().toLowerCase();
}

String canonicalUri = requestInfo.getUrl().getPath();
if(!canonicalUri.matches(notUnicode)) {
char[] chars = canonicalUri.toCharArray();
String sanitize = "";
for (int i = 0; i < chars.length; ++i) {
String test = Character.toString(chars[i]);
if (Pattern.matches(notUnicode, test)) {
sanitize = sanitize.concat(URLEncoder.encode(test, StandardCharsets.UTF_8.toString()));
} else {
sanitize = sanitize.concat(test);
}
}
canonicalUri = sanitize;
}
//pw.println(canonicalUri);
URI uri = new URI(canonicalUri);
uri = uri.normalize();
Expand Down Expand Up @@ -136,6 +162,19 @@ public static byte[] signRequest(IHttpRequestResponse messageInfo,
if (Strings.isNullOrEmpty(canonicalQueryString)){
canonicalQueryString = "";
}
if(!canonicalQueryString.matches(notUnicode)) {
char[] chars = canonicalQueryString.toCharArray();
String sanitize = "";
for (int i = 0; i < chars.length; ++i) {
String test = Character.toString(chars[i]);
if (Pattern.matches(notUnicode, test)) {
sanitize = sanitize.concat(URLEncoder.encode(test, StandardCharsets.UTF_8.toString()));
} else {
sanitize = sanitize.concat(test);
}
}
canonicalQueryString = sanitize;
}

String[] sorted = canonicalQueryString.split("&");
Arrays.sort(sorted);
Expand Down Expand Up @@ -169,7 +208,7 @@ public static byte[] signRequest(IHttpRequestResponse messageInfo,
}
}
canonicalQueryString = String.join("", cleanup);

//pw.println(canonicalQueryString);
//canonicalQueryString = canonicalQueryString.replace(":","%3A").replace("/","%2F").replace(" ", "%20");

String canonicalRequest = requestInfo.getMethod() + '\n' + encodedCanonicalUri + '\n' + canonicalQueryString + '\n' +
Expand All @@ -178,15 +217,28 @@ public static byte[] signRequest(IHttpRequestResponse messageInfo,
String algorithm = "AWS4-HMAC-SHA256";

String stringToSign = algorithm + '\n' + amzdate + '\n' + credScope + '\n' + Hashing.sha256().hashString(canonicalRequest, StandardCharsets.UTF_8).toString().toLowerCase();
pw.println(canonicalRequest);
pw.println(stringToSign);
//pw.println(canonicalRequest);
//pw.println(stringToSign);
byte[] signingKey = getSignatureKey(secretKey, dateStampString, region, service);

String signature = DatatypeConverter.printHexBinary(HmacSHA256(stringToSign, signingKey));

newHeaders.add("Authorization: " + algorithm + ' ' + "Credential=" + accessKey + '/' + credScope + ", " + "SignedHeaders=" +
signedHeaders + ", " + "Signature=" + signature.toLowerCase());
newHeaders.add("X-Amz-Date: " + amzdate);
if(!newHeaders.get(0).matches(notUnicode)) {
char[] chars = newHeaders.get(0).toCharArray();
String sanitize = "";
for (int i = 0; i < chars.length; ++i) {
String test = Character.toString(chars[i]);
if (Pattern.matches(notUnicode, test)) {
sanitize = sanitize.concat(URLEncoder.encode(test, StandardCharsets.UTF_8.toString()));
} else {
sanitize = sanitize.concat(test);
}
}
newHeaders.set(0, sanitize);
}

return helpers.buildHttpMessage(newHeaders, body.getBytes());
}
Expand Down Expand Up @@ -220,4 +272,25 @@ private static String getSignedHeaders(String authHeader){
return signedHeaders;

}
private static String bytesToHex(byte[] bytes) {
char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
char[] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = HEX_ARRAY[v >>> 4];
hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
}
return new String(hexChars);
}
private static String hexToString(String hex){
StringBuilder sb = new StringBuilder();
StringBuilder temp = new StringBuilder();
for( int i=0; i<hex.length()-1; i+=2 ){
String output = hex.substring(i, (i + 2));
int decimal = Integer.parseInt(output, 16);
sb.append((char)decimal);
temp.append(decimal);
}
return sb.toString();
}
}

0 comments on commit eac2a53

Please sign in to comment.