PortSwigger / BChecks

BChecks collection for Burp Suite Professional and Burp Suite Enterprise Edition
https://portswigger.net/burp/documentation/scanner/bchecks
GNU Lesser General Public License v3.0
588 stars 104 forks source link

IllegalArgumentException- input byte array has wrong 4-byte ending unit #145

Closed arturoidelgado1998 closed 4 months ago

arturoidelgado1998 commented 7 months ago

I working on creating a B check for saml responses and one of the main errors im getting is IllegalArgumentException- input byte array has wrong 4-byte ending unit. Ive tried multiple steps to try and fix it but nothing is working. Ive tried replacing some characters so base64 decode comes out cleaner but I think maybe having a url decode function would be great and definitely solve my problem. Im thinking my problem is coming from the base 64 decode portion.

Do you know of any work around that might work?

Michelle-PortSwigger commented 7 months ago

Can you tell us a bit more about the BCheck you've created and how the URL encode would help in this scenario? If you're happy to share a copy of the BCheck with us to help us understand what you are creating, that would be great. If you'd prefer to email to us, you can contact us using support@portswigger.net

arturoidelgado1998 commented 7 months ago

Sure here is the bcheck. There are no errors and Ive added the metadata before hand. The body is:

givenresponse then if {base.request.body} matches "SAMLResponse" then if {base64_decode(regex_replace({base.request.body},"%2b", "+"))} differs from "InResponseTo" then report issue: severity: info confidence: certain detail: "Test" remediation: "Test" end if end if

This is an example of what I'm trying to do. What I want to do is check the InResponseTo in the SamlResponse. I don't think I can set a variable equal to the saml response so I use base64_decode on the entire body of the request. When in application I wouldnt use differs but matches instead.

Michelle-PortSwigger commented 7 months ago

Thanks for sending that over.

I should have asked for this at the same time (sorry), but do you have any example data that you can share?

arturoidelgado1998 commented 7 months ago

so the body usually has a saml response and a relaystate. the relaystate is optional but most Saml implementation have it.

An examlpe body request would be like this:

SAMLResponse=[encoded SAML response]&RelayState=[optional relay state]

in this case an example SAMLResponse would be

SAMLResponse=CjxzYW1scDpSZXNwb25zZSB4bWxuczpzYW1scD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOnByb3RvY29sIiBJblJlc3BvbnNlVG89ImlkLTEyMzQ1Njc4OTAiPgo8L3NhbWxwOlJlc3BvbnNlPgo%3D &RelayState=returnUrl%3Dhttps%3A%2F%2Fwww.example.com%2Fdashboard

Now I think what may be the problem is not being able to decode properly since I would have to replace multiple url encoded characters with their respective decoded characters, currently im using regex replace. So Im trying to find a work around or maybe an enhancement to provide url decoding if possible.

Thank you! if you can find a work around that would be great! Thank you for being quick to answer!

Michelle-PortSwigger commented 7 months ago

The base64 decode is strict, so if the whole string it's trying to decode isn't base64 then it's going not going to decode nicely, which seems to be the case here. The bit we're really wanting to base64 decode is just the SAMLResponse value, so we'd need to use regex to pull this out of the body. I hope this makes sense. If not, or if you need some examples to help you get started, let me know :)

arturoidelgado1998 commented 7 months ago

Can I please have some examples to get started. Thank you again for your help!

Michelle-PortSwigger commented 7 months ago

Hi

I'm going to try and explain the thinking behind the various steps rather than just provide a single example, so I hope this all makes sense. If it doesn't, just ask more questions :)

If I've understood your scenario correctly, you have a payload such as this:

SAMLResponse=CjxzYW1scDpSZXNwb25zZSB4bWxuczpzYW1scD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOnByb3RvY29sIiBJblJlc3BvbnNlVG89ImlkLTEyMzQ1Njc4OTAiPgo8L3NhbWxwOlJlc3BvbnNlPgo%3D
&RelayState=returnUrl%3Dhttps%3A%2F%2Fwww.example.com%2Fdashboard

and you want to base64 decode the SAMLReponse value: CjxzYW1scDpSZXNwb25zZSB4bWxuczpzYW1scD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOnByb3RvY29sIiBJblJlc3BvbnNlVG89ImlkLTEyMzQ1Njc4OTAiPgo8L3NhbWxwOlJlc3BvbnNlPgo

to check whether or not it contains InResponseTo. If it does not contain InResponseTo you want an Issue to be generated.

Our first challenge is to strip out the SAMLResponse value.

As a first step we can use a regex_replace to strip off the end of the payload, for example: {regex_replace({base.request.body},"%3D&.+$", "")}

The next step is to take that and strip off the beginning of the payload, 'SAMLResponse=' so we're just left with the value: {regex_replace({regex_replace({base.request.body},"%3D&.+$", "")},"SAMLResponse=","")})}

Now we can base64 decode it: {base64_decode({regex_replace({regex_replace({base.request.body},"%3D&.+$", "")},"SAMLResponse=","")})})

As we're no longer using the full response, we can't use 'differs from' in the BCheck.

We can also improve the checks we make on the response to be sure it definitely contains data we can base64 decode and doesn't just contain a payload that starts with SAMLResponse=foo.

The resulting BCheck would look like this:

metadata:
    language: v2-beta
    name: "regex_replace example SAMLResponse"
    description: "Testing SAMLResponse case"
    author: "Test Author"

given response then
    if {base.request.body} matches "^SAMLResponse=[a-zA-Z0-9+=].+" then
        if not ("InResponseTo" in {base64_decode({regex_replace({regex_replace({base.request.body},"%3D&.+$", "")},"SAMLResponse=","")})}) then
            report issue:
            severity: info
            confidence: certain
            detail: "Description of issue here"
            remediation: "Remediation details here"
        end if
    end if

Let me know if this helps :)