diff --git a/addOns/automacrobuilder/CHANGELOG.md b/addOns/automacrobuilder/CHANGELOG.md index 0d01b6a..2696959 100644 --- a/addOns/automacrobuilder/CHANGELOG.md +++ b/addOns/automacrobuilder/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to this add-on will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). +## [v1.1.19] - 2024-03-28 +### Changed +- bugfix: Changed to correctly encode and decode the HttpRequest body based on Content-Encoding. + ## [v1.1.18] - 2024-03-12 ### Changed - bugfix: Changed ActiveScan behavior when scan is started again. diff --git a/addOns/automacrobuilder/automacrobuilder.gradle.kts b/addOns/automacrobuilder/automacrobuilder.gradle.kts index 3e0bc0b..6e5e077 100644 --- a/addOns/automacrobuilder/automacrobuilder.gradle.kts +++ b/addOns/automacrobuilder/automacrobuilder.gradle.kts @@ -1,6 +1,6 @@ import org.zaproxy.gradle.addon.AddOnStatus -version = "1.1.18" +version = "1.1.19" description = "AutoMacroBuilder for ZAP" tasks.withType { diff --git a/addOns/automacrobuilder/src/main/java/org/zaproxy/zap/extension/automacrobuilder/mdepend/ClientDependMessageContainer.java b/addOns/automacrobuilder/src/main/java/org/zaproxy/zap/extension/automacrobuilder/mdepend/ClientDependMessageContainer.java index 4140d19..8a9694a 100644 --- a/addOns/automacrobuilder/src/main/java/org/zaproxy/zap/extension/automacrobuilder/mdepend/ClientDependMessageContainer.java +++ b/addOns/automacrobuilder/src/main/java/org/zaproxy/zap/extension/automacrobuilder/mdepend/ClientDependMessageContainer.java @@ -109,7 +109,8 @@ public byte[] getRequestByte() { .getRequestHeader() .toString(); // getPrimeHeader() + mLineDelimiter + mMsgHeader + // mLineDelimiter; - byte[] bodybin = this.href.getHttpMessage().getRequestBody().getBytes(); + // get body bytes with applying properly decoding which is based on Content-Encoding + byte[] bodybin = this.href.getHttpMessage().getRequestBody().getContent(); ParmGenBinUtil pbinutil = new ParmGenBinUtil(reqheader.getBytes()); pbinutil.concat(bodybin); return pbinutil.getBytes(); @@ -129,7 +130,8 @@ public byte[] getResponseByte() { .getResponseHeader() .toString(); // getPrimeHeader() + mLineDelimiter + mMsgHeader + // mLineDelimiter; - byte[] bodybin = this.href.getHttpMessage().getResponseBody().getBytes(); + // get body bytes with applying properly decoding which is base on Content-Encoding + byte[] bodybin = this.href.getHttpMessage().getResponseBody().getContent(); ParmGenBinUtil pbinutil = new ParmGenBinUtil(resheader.getBytes()); pbinutil.concat(bodybin); return pbinutil.getBytes(); diff --git a/addOns/automacrobuilder/src/main/java/org/zaproxy/zap/extension/automacrobuilder/mdepend/ClientRequest.java b/addOns/automacrobuilder/src/main/java/org/zaproxy/zap/extension/automacrobuilder/mdepend/ClientRequest.java index 55de172..03a4b60 100644 --- a/addOns/automacrobuilder/src/main/java/org/zaproxy/zap/extension/automacrobuilder/mdepend/ClientRequest.java +++ b/addOns/automacrobuilder/src/main/java/org/zaproxy/zap/extension/automacrobuilder/mdepend/ClientRequest.java @@ -63,7 +63,9 @@ public PRequestResponse clientRequest(ParmGenMacroTrace pmt, PRequest request) { HttpRequestBody requestbody = htmess.getRequestBody(); ParmGenBinUtil requestbin = new ParmGenBinUtil(requestheader.toString().getBytes()); - requestbin.concat(requestbody.getBytes()); + //requestbin.concat(requestbody.getBytes()); + // must use getContent method which can get properly decoded value. + requestbin.concat(requestbody.getContent()); HttpResponseHeader responseheader = htmess.getResponseHeader(); HttpResponseBody responsebody = htmess.getResponseBody(); String responseHeaderString = @@ -77,7 +79,9 @@ public PRequestResponse clientRequest(ParmGenMacroTrace pmt, PRequest request) { responseEncode = Encode.getEnum(responseHttpContentType.getCharSetName()); } ParmGenBinUtil responsebin = new ParmGenBinUtil(responseHeaderString.getBytes()); - responsebin.concat(responsebody.getBytes()); + //responsebin.concat(responsebody.getBytes()); + // must use getContent method which get body bytes with applying properly decoding which is based on Content-Encoding + responsebin.concat(responsebody.getContent()); if (responsebin.length() < 1) { responsebin.clear(); responsebin.concat( @@ -189,7 +193,9 @@ public void updateCurrentResponseWithFinalResponse( if (responsebody == null || responsebody.length < 1) { responsebody = "".getBytes(); // not null zero length bytes. } - currentmessage.setResponseBody(responsebody); + //currentmessage.setResponseBody(responsebody); + // set body bytes with applying properly encoding which is based on Content-Encoding + currentmessage.getResponseBody().setContent(responsebody); } catch (HttpMalformedHeaderException e) { LOGGER4J.error("", e); } diff --git a/addOns/automacrobuilder/src/main/java/org/zaproxy/zap/extension/automacrobuilder/zap/ZapUtil.java b/addOns/automacrobuilder/src/main/java/org/zaproxy/zap/extension/automacrobuilder/zap/ZapUtil.java index 6e4576e..19bc564 100644 --- a/addOns/automacrobuilder/src/main/java/org/zaproxy/zap/extension/automacrobuilder/zap/ZapUtil.java +++ b/addOns/automacrobuilder/src/main/java/org/zaproxy/zap/extension/automacrobuilder/zap/ZapUtil.java @@ -5,10 +5,7 @@ import org.parosproxy.paros.control.Control; import org.parosproxy.paros.extension.Extension; -import org.parosproxy.paros.network.HttpMalformedHeaderException; -import org.parosproxy.paros.network.HttpMessage; -import org.parosproxy.paros.network.HttpRequestHeader; -import org.parosproxy.paros.network.HttpResponseHeader; +import org.parosproxy.paros.network.*; import org.zaproxy.zap.control.AddOn; import org.zaproxy.zap.extension.automacrobuilder.*; import org.zaproxy.zap.extension.automacrobuilder.view.StyledDocumentWithChunk; @@ -86,10 +83,13 @@ public static HttpMessage getHttpMessage(PRequest preq) { try { HttpRequestHeader httpReqHeader = new HttpRequestHeader(reqhstr, isSSL); HttpRequestBody mReqBody = new HttpRequestBody(); - mReqBody.setBody(preq.getBodyBytes()); // set PRequest Encoding Charset to request Body Charset mReqBody.setCharset(preq.getPageEnc().getIANACharsetName()); + // setup Content-Encoding handlers(gzip,deflate). + HttpMessage.setContentEncodings(httpReqHeader, mReqBody); htmess = new HttpMessage(httpReqHeader, mReqBody); + // update request body and apply properly encodings(based on Content-Encoding) to it. + updateRequestContent(htmess, preq.getBodyBytes()); } catch (HttpMalformedHeaderException e) { LOGGER4J.error("reqhstr:" + reqhstr, e); } @@ -153,7 +153,9 @@ public static PRequestResponse getPRequestResponse(HttpMessage htmess, Encode se requestBodyEncode = sequenceEncode; } ParmGenBinUtil requestbin = new ParmGenBinUtil(requestheader.toString().getBytes()); - requestbin.concat(requestbody.getBytes()); + //requestbin.concat(requestbody.getBytes()); + // must use getContent method. it can apply properly decoding which is based on Content-Encoding + requestbin.concat(requestbody.getContent()); HttpResponseHeader responseheader = htmess.getResponseHeader(); HttpResponseBody responsebody = htmess.getResponseBody(); Encode responseBodyEncode = Encode.getEnum(responsebody.getCharset()); @@ -161,7 +163,9 @@ public static PRequestResponse getPRequestResponse(HttpMessage htmess, Encode se responseBodyEncode = sequenceEncode; } ParmGenBinUtil responsebin = new ParmGenBinUtil(responseheader.toString().getBytes()); - responsebin.concat(responsebody.getBytes()); + //responsebin.concat(responsebody.getBytes()); + // must use getContent method which can get properly decoded value which is based on Content-Encoding + responsebin.concat(responsebody.getContent()); if (responsebin.length() < 1) { responsebin.clear(); Encode enc_iso8859_1 = Encode.ISO_8859_1; @@ -200,7 +204,9 @@ public static PRequest getPRequest(HttpMessage htmess, Encode lastResponseEncode + lastResponseEncode.getIANACharsetName() + "]"); ParmGenBinUtil requestbin = new ParmGenBinUtil(requestheader.toString().getBytes()); - requestbin.concat(requestbody.getBytes()); + //requestbin.concat(requestbody.getBytes()); + // must use getContent method which apply properly decoding based on Content-Encoding + requestbin.concat(requestbody.getContent()); String host = requestheader.getHostName(); int port = requestheader.getHostPort(); boolean isSSL = requestheader.isSecure(); @@ -365,4 +371,28 @@ public static void SwingInvokeLaterIfNeeded(Runnable runnable) { runnable.run(); } } + + /** + * update request body with bodyBytes and update Content-Length with bodyBytes.length + * + * @param message + * @param bodyBytes + */ + public static void updateRequestContent(HttpMessage message, byte[] bodyBytes) { + // set request body bytes and apply properly encodings(based on Content-Encoding). + message.getRequestBody().setContent(bodyBytes); + // update Content-Length with bodyBytes.length + int bodyLength = message.getRequestBody().length(); + String method = message.getRequestHeader().getMethod(); + if (bodyLength == 0 + && (HttpRequestHeader.GET.equalsIgnoreCase(method) + || HttpRequestHeader.CONNECT.equalsIgnoreCase(method) + || HttpRequestHeader.DELETE.equalsIgnoreCase(method) + || HttpRequestHeader.HEAD.equalsIgnoreCase(method) + || HttpRequestHeader.TRACE.equalsIgnoreCase(method))) { + message.getRequestHeader().setHeader(HttpHeader.CONTENT_LENGTH, null); + return; + } + message.getRequestHeader().setContentLength(bodyLength); + } }