Last Updated: 2022-11-03 01:29:48 UTC
by Rob VandenBrink (Version: 1)
No, this is not a story about the Canadian Thanksgiving long weekend, it's about web application testing. I recently had a web application to assess, and I used Burp Suite Pro as part of that project. Burp is one of my favourite tools to aim at a website, it does a lot of the up-front "test everything" grunt work for you so you can then focus on the details that are most important.
One of the findings was "OpenID Authorization Code Flow without PKCE Protection Detected", coupled with "OpenID Authorization code Flow without Nonce Parameter". This story isn't about these issues specifically, but how to deal with complex web app code flow issues in Burp.
We're all familiar with Breakpoints - in their simplest terms, when you write code and put in random lines that print out "Code got to here, variable $something = some value", that's a breakpoint. If you write complied code or assembly, breakpoints can mean something more complex. In Burp, by default "proxy intercept" is on, which means that for every request and response the app will intercept that data and present it to you for inspection or modification. You can see how in a complex web app you don't want that for EVERY page. What I needed was:
- Turn off proxy intercept so that I don't have to click "OK OK OK" a dozen times for each page load
- However, turn the proxy intercept back on when I get to a specific page, see a particular variable or some combination of "stop here, this is the spot" set of conditions.
- At that point, I'm at the proxy intercept screen and can either single-step from there, or change variables to see what happens as the code progresses along.
Does that sound complicated? Maybe so, but it's simpler once we look at it for real.
First, this is the raw "finding" that Burp displays. Note the "nonce=" parameter - that's what we're looking for in our breakpoint.
Next, in Burp navigate to the the Proxy / Options page, and edit "Intercept Client Requests" - this screenshot shows the default settings:
Note in the lower half of the screenshot above that you can also set breakpoints on the info that gets sent from the server to the client. The default client-side intercept settings shown here are: "intercept everything except for this default list of file extensions". On the server side, the intercept settings are "intercept everything that looks like text"
We'll disable those default settings and add our own - we want the intercept to turn on ONLY when the "nonce" parameter makes an appearance. Note how many options you can pick to combine together (with ANDs and ORs) to make up your condition:
In our case it's pretty simple - stop when you see the "nonce" parameter:
Now, with that set and intercept enabled, I went back to the login page and logged in, answered the MFA prompt and all the things. When the "nonce" parameter appears in the request or response - BOOM, things stop and I'm looking at the request.
If you are looking to save time in Burp, this is a great way to do exactly that!
What happened? It turns out that I could edit the nonce value to anything (including zero or deleting it altogether) and the login would still succeed. Even if I changed it several screens in, or in the server response the login would still succeed. It turns out that the provider didn't use the nonce.
The nonce is an important piece of the authentication puzzle - it's what associates the client session with the ID token and is used to prevent replay attacks. Of the 3 options for OpenID + OAuth, two of them require the nonce (Implicit and Hybrid) and the nonce value is not required but is still recommended for the third option (Auth Code). If you are using PKCE (for instance for handing the code flow back to a mobile app), if you don't specify a nonce value, it's supposed to use the value of "state" for the nonce to at least force a value. Long story short, the finding was a real thing - go go gadget burp! (wait, that still doesn't sound right ...)
Got a fun situation where you used breakpoints in a web test? By all means, share using our comment form!