From b918c6bd1563901fa468808424f18e0f84392184 Mon Sep 17 00:00:00 2001 From: Andrey Rainchik Date: Fri, 6 Sep 2019 13:12:32 -0500 Subject: [PATCH 1/2] Fixing bug where an extra equals sign was added. --- src/main/java/burp/Utility.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/burp/Utility.java b/src/main/java/burp/Utility.java index 3c99a50..a26f1d9 100644 --- a/src/main/java/burp/Utility.java +++ b/src/main/java/burp/Utility.java @@ -155,7 +155,7 @@ public static byte[] signRequest(IHttpRequestResponse messageInfo, } if (param.length > 1) { sorted[i] = String.join("=", param); - } else if (param.length == 1){ + } else if (param.length == 1 && !param[0].isEmpty()){ sorted[i] = param[0] + "="; } } @@ -178,8 +178,8 @@ 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)); From eac2a53ca4f4c1e45672ab61438f0e90c887150b Mon Sep 17 00:00:00 2001 From: Andrey Rainchik Date: Tue, 26 Nov 2019 12:20:08 -0600 Subject: [PATCH 2/2] Proper handling of non-basic-Latin Unicode characters in body and URI --- src/main/java/burp/Utility.java | 87 ++++++++++++++++++++++++++++++--- 1 file changed, 80 insertions(+), 7 deletions(-) diff --git a/src/main/java/burp/Utility.java b/src/main/java/burp/Utility.java index a26f1d9..4639d4c 100644 --- a/src/main/java/burp/Utility.java +++ b/src/main/java/burp/Utility.java @@ -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 { @@ -93,15 +92,29 @@ 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 { @@ -109,6 +122,19 @@ public static byte[] signRequest(IHttpRequestResponse messageInfo, } 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(); @@ -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); @@ -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' + @@ -178,8 +217,8 @@ 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)); @@ -187,6 +226,19 @@ public static byte[] signRequest(IHttpRequestResponse messageInfo, 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()); } @@ -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