diff --git a/doc/language.md b/doc/language.md index 9debdad..def1fb0 100644 --- a/doc/language.md +++ b/doc/language.md @@ -184,11 +184,14 @@ Note: The supported algorithms for signing are: Note that when decrypting a JWE, a JWS is expected in the payload. Other payloads are not supproted. -To decrypt a JWE to access the JWT in its payload use these two mandatory tags +To decrypt a JWE to access the JWT in its payload use these tags - `jwe decrypt` with the private key in PEM string format - `jwe encrypt` with the public key in PEM string format +Note: You can decrypt without specifying encrypt, this will prevent the JWE from being edited (as no encryption key is passed) +Note: You can't encrypt, without decrypt + Note: Supported algorithms are: - RSA_OAEP diff --git a/tool/src/main/java/migt/BurpExtender.java b/tool/src/main/java/migt/BurpExtender.java index 536212f..167e78c 100644 --- a/tool/src/main/java/migt/BurpExtender.java +++ b/tool/src/main/java/migt/BurpExtender.java @@ -97,6 +97,8 @@ public void processProxyMessage(boolean messageIsRequest, IInterceptedProxyMessa String port = proxy_message.getListenerInterface().split(":")[1]; IHttpRequestResponse messageInfo = proxy_message.getMessageInfo(); + HTTPReqRes message = new HTTPReqRes(messageInfo, helpers, messageIsRequest); + if (mainPane.ACTIVE_ENABLED) { if (!port.equals(mainPane.act_active_op.session_port)) { return; @@ -113,80 +115,24 @@ public void processProxyMessage(boolean messageIsRequest, IInterceptedProxyMessa mainPane.act_active_op.applicable = false; } - boolean matchMessage = false; - - try { - /* If the response message name is searched, the getByResponse will be true. - * so i have to search for the request, and then evaluate the response*/ - if (msg_type.getByResponse) { - if (!messageIsRequest) { - matchMessage = Tools.executeChecks(msg_type.checks, - new HTTPReqRes(messageInfo, helpers, true), - true, mainPane.act_active_op.api.vars); - } - } else if (msg_type.getByRequest) { - if (!messageIsRequest) { - matchMessage = Tools.executeChecks(msg_type.checks, - new HTTPReqRes(messageInfo, helpers, false), - false, mainPane.act_active_op.api.vars); - } - } else { - if (messageIsRequest == msg_type.isRequest) { - matchMessage = Tools.executeChecks(msg_type.checks, - new HTTPReqRes(messageInfo, helpers, msg_type.isRequest), - msg_type.isRequest, mainPane.act_active_op.api.vars); - } - } - } catch (ParsingException e) { - mainPane.act_active_op.applicable = false; - return; - } + boolean matchMessage = message.matches_msg_type(msg_type); if (matchMessage) { - boolean isRequest = false; - if (msg_type.getByRequest) { - isRequest = false; - } else if (msg_type.getByResponse) { - isRequest = true; - } else { - isRequest = msg_type.isRequest; - } - Operation.MatchedMessage m = new Operation.MatchedMessage( - new HTTPReqRes(messageInfo, helpers, isRequest), + message, HTTPReqRes.instances, - isRequest, - !isRequest, + msg_type.msg_to_process_is_request, + !msg_type.msg_to_process_is_request, false); mainPane.act_active_op.matchedMessages.add(m); // If the operation's action is an intercept if (Objects.requireNonNull(mainPane.act_active_op.getAction()) == Operation.Action.INTERCEPT) { try { - /* If the response message name is searched, the getByResponse will be true. - * so i have to search for the request, and then evaluate the response*/ - if (msg_type.getByResponse) { - if (!messageIsRequest) { - if (matchMessage) { - processMatchedMsg(msg_type, messageInfo); - } - } - } else if (msg_type.getByRequest) { - if (!messageIsRequest) { - if (matchMessage) { - processMatchedMsg(msg_type, messageInfo); - } - } - } else { - if (messageIsRequest == msg_type.isRequest) { - if (matchMessage) { - processMatchedMsg(msg_type, messageInfo); - if (mainPane.act_active_op.then != null & - mainPane.act_active_op.then == Operation.Then.DROP) { - proxy_message.setInterceptAction(IInterceptedProxyMessage.ACTION_DROP); - } - } - } + processMatchedMsg(msg_type, messageInfo); + if (mainPane.act_active_op.then != null & + mainPane.act_active_op.then == Operation.Then.DROP) { + proxy_message.setInterceptAction(IInterceptedProxyMessage.ACTION_DROP); } } catch (Exception e) { e.printStackTrace(); @@ -214,27 +160,25 @@ public void processProxyMessage(boolean messageIsRequest, IInterceptedProxyMessa private void processMatchedMsg(MessageType msg_type, IHttpRequestResponse messageInfo) { messageInfo.setHighlight("red"); - HTTPReqRes message = new HTTPReqRes(messageInfo, helpers, msg_type.isRequest); + HTTPReqRes message = new HTTPReqRes(messageInfo, helpers, msg_type.msg_to_process_is_request); mainPane.act_active_op.helpers = helpers; mainPane.act_active_op.api.message = message; - mainPane.act_active_op.api.is_request = msg_type.isRequest; // todo check if with getByResponse is ok + mainPane.act_active_op.api.is_request = msg_type.msg_to_process_is_request; mainPane.act_active_op.execute(); // if message has been edited inside operation update the value - if (mainPane.act_active_op.processed_message != null) { - //TODO: remove processed_message in future - if (msg_type.isRequest) { - messageInfo.setRequest(mainPane.act_active_op.processed_message); - } else { - messageInfo.setResponse(mainPane.act_active_op.processed_message); - } - } else { - if (msg_type.isRequest) { - messageInfo.setRequest(message.getMessage(message.isRequest, helpers)); - } else { - messageInfo.setResponse(message.getMessage(message.isRequest, helpers)); + try { + if (mainPane.act_active_op.processed_message != null) { + if (msg_type.isRequest) { + messageInfo.setRequest(mainPane.act_active_op.processed_message); + } else { + messageInfo.setResponse(mainPane.act_active_op.processed_message); + } } + } catch (UnsupportedOperationException e) { + // This is thrown when an already issued request is being substituted + System.err.println("Warning, edited message that has already been sent"); } resume(); } diff --git a/tool/src/main/java/migt/DecodeOperation.java b/tool/src/main/java/migt/DecodeOperation.java index fb1003d..883388a 100644 --- a/tool/src/main/java/migt/DecodeOperation.java +++ b/tool/src/main/java/migt/DecodeOperation.java @@ -92,8 +92,12 @@ public DecodeOperation(JSONObject decode_op_json) throws ParsingException { case "jwe decrypt": jwt.decrypt = true; jwt.public_key_pem_enc = decode_op_json.getString("jwe decrypt"); - jwt.private_key_pem_enc = decode_op_json.getString("jwe encrypt"); break; + case "jwe encrypt": + // if encrypt specified, also decrypt has to be specified + jwt.decrypt = true; + jwt.private_key_pem_enc = decode_op_json.getString("jwe encrypt"); + jwt.public_key_pem_enc = decode_op_json.getString("jwe decrypt"); } } } diff --git a/tool/src/main/java/migt/HTTPReqRes.java b/tool/src/main/java/migt/HTTPReqRes.java index 13c6080..7717ab6 100644 --- a/tool/src/main/java/migt/HTTPReqRes.java +++ b/tool/src/main/java/migt/HTTPReqRes.java @@ -83,24 +83,22 @@ public HTTPReqRes(IHttpRequestResponsePersisted message, IExtensionHelpers helpe * @param isRequest true if the message is a request, false otherwise */ public HTTPReqRes(IHttpRequestResponse message, IExtensionHelpers helpers, Boolean isRequest) { - this.isRequest = isRequest; - this.isResponse = !isRequest; - // TODO: in theory, if a IHttpRequestResponse object contains a response, it should contain also the request - - if (isRequest) { - this.setRequest(message.getRequest()); - this.setRequest_url(helpers.analyzeRequest(message).getUrl().toString()); - helpers.analyzeRequest(message.getRequest()).getBodyOffset(); - this.headers_req = helpers.analyzeRequest(message.getRequest()).getHeaders(); - this.request_url = helpers.analyzeRequest(message).getUrl().toString(); - this.body_offset_req = helpers.analyzeRequest(message.getRequest()).getBodyOffset(); - } else { + if (!isRequest) { + this.isResponse = true; this.setResponse(message.getResponse()); - helpers.analyzeResponse(message.getResponse()).getBodyOffset(); this.headers_resp = helpers.analyzeResponse(message.getResponse()).getHeaders(); - this.body_offset_resp = helpers.analyzeRequest(message.getRequest()).getBodyOffset(); + this.body_offset_resp = helpers.analyzeRequest(message.getResponse()).getBodyOffset(); } + // the request is always present in a IHTTPRequestResponse + this.isRequest = true; + this.setRequest(message.getRequest()); + this.setRequest_url(helpers.analyzeRequest(message).getUrl().toString()); + this.headers_req = helpers.analyzeRequest(message.getRequest()).getHeaders(); + this.request_url = helpers.analyzeRequest(message).getUrl().toString(); + this.body_offset_req = helpers.analyzeRequest(message.getRequest()).getBodyOffset(); + + // set host info IHttpService service = message.getHttpService(); this.setHost(service.getHost()); this.setPort(service.getPort()); @@ -472,6 +470,7 @@ public boolean matches_msg_type(MessageType msg_type) { * so messageIndex have to search for the request, and then evaluate the response */ if (msg_type.getByResponse) { + if (!isResponse) return false; // both request and response have to be present matchedMessage = Tools.executeChecks( msg_type.checks, this, @@ -479,6 +478,7 @@ public boolean matches_msg_type(MessageType msg_type) { new ArrayList<>() // TODO: fix ); } else if (msg_type.getByRequest) { + if (!isResponse) return false; // both request and response have to be present matchedMessage = Tools.executeChecks( msg_type.checks, this, @@ -486,6 +486,7 @@ public boolean matches_msg_type(MessageType msg_type) { new ArrayList<>() // TODO: fix ); } else { + if (!msg_type.isRequest && !isResponse) return false; // this message is not containing a response matchedMessage = Tools.executeChecks( msg_type.checks, this,