Authentication Token Obtain and Replace (ATOR) Burp Plugin: Fast and Reliable plugin to handle Complex Login Sequences — Part 2
This post will be a continuation of the previous post. Highly recommend you read the previous post.
Scenarios
We will cover the below scenarios for the plugin:
- Multi-step login — when there is more than one request for login (think email address on first page and password on second) — google login is a good example.
- Multi-token replacement — more than one token has to be replaced from say response 1 to request 2. (Tokens like accountId, accountToken, authToken, authSecret)
- Commonly used Regex Patterns — we also mention a few commonly used regex patterns
Sample Application Background
We picked a website listed on bugcrowd because this website had both multi-step login and multiple tokens to be replaced. This was a perfect example to demonstrate the ability of the plugin.
Request/Response and Parameters
The screenshot above shows about the requests for the login process:
- [# 1820] — create_session -> posts the email address (login screen 1)
- [# 1822] — present_credentials -> posts the password (login screen 2)
- [# 1823] — get_session_cookies -> post authenticated page which gets session cookies
Request 1: create_session
Request: email address is passed
Response: If email address is valid then an authToken [highlighted in pink] is retrieved. Let us call this token1
Request 2: present_credentials
Request: along with the password, the token1 parameter from Response 1 has to be passed in both: [highlighted in pink]
- Header: authorization
- Post body: authToken
Response: If the password and the tokens are valid the response will have two tokens:
- authToken: let us call this export_token1 [highlighted in blue]
- accountId: let us call this account_token [highlighted in green]
Request 3: get_session_cookies
Request: Two parameters from previous response has to be passed in JSON body:
- authToken: this will be the same as export_token1 [highlighted in blue]
- accountId: this will be the same as account_token [highlighted in green]
Response: If all parameters are valid: status code is 200 OK else status code is 401 Unauthorized
To summarize the above steps, the following replacements need to happen for a successful login:
- Request 2 present_credentials: AuthToken from response 1 must be replicated in both the header and body parameter [pink box]
- Request 3 get_session_cookies: authToken from response 2 must be replicated in the body [blue box]
- Request 3 get_session_cookies: accountId from response 2 must be replicated in the body [green box]
This step is critical during setup because it is very easy to miss a tiny tiny detail.
ATOR Setup
Now that we have understood the setup and the replacements to be done,
Let us follow the 4 step process:
- Identify the login sequence (from proxy or repeater) and send to ATOR
- Identify the Error Pattern (details in section below)
- Obtain the data from the response using regex (see sample regex values)
- Replace this data on the request (use same regex as step 3 along with the variable name)
Step 1: Identify the login sequence
Send both Request 1 (create_session)& Request 2 (present_credentials)to ATOR from Proxy or Repeater.
1st replacement:
Request 2 present_credentials: AuthToken from response 1 must be replicated in both the header and body parameter [pink box]
2nd replacement:
Request 3 get_session_cookies: authToken from response 2 must be replicated in the body [blue box]
Export this value so that it can be plugged into get_session_cookies whenever this request is made. We have only exported this value, the replacement will happen in step 4.
3rd replacement:
Request 3 get_session_cookies: accountId from response 2 must be replicated in the body [green box]
Export this value so that it can be plugged into get_session_cookies whenever this request is made. We have only exported this value, the replacement will happen in step 4.
Step 2: Identify error pattern
A 401 is returned whenever the session has expired.
Setup the error condition in ATOR
Step 3: Specify Regex pattern for replacement of token
Step 4: Replace this data on the request
We have combined steps 3 and 4 for ease of screenshots. Remember we had exported two values (export_token1 and account_token1) in step 1. Time to use regex and plug-in those values in the right place. Both of these tokens are export-values that will be stored in memory. The plugin will replace the tokens whenever an error condition occurs. More about this is explained in the In-Memory Replacement section.
Regex used:
In the section below we will explain more about regex and provide a few examples.
Pattern: authToken”.”([\d\-\.\=\_\w])*
ReplacementArea: authToken”.”export_token1Pattern: accountId”.”([\d\-\.\=\_\w])*
ReplacementArea: accountId”.”account_token1
We have now setup the replacement rules for both the tokens. So all the 3 replacements are now taken care of.
Working of the Plugin
Let us trigger a request of get_session_cookies with invalid tokens (Request 141 — authToken and accountId) i.e. we have forced a logout. With the plugin now setup, let us look at the flow of requests in the Flow Extender.
Request 141 with invalid cookies triggered requests 142 and 143 in the background and tokens were exported. The request get_session_cookies is replayed (144) with the exported tokens and a 200 OK is received.
In-Memory Replacement
We have been talking about speed and in-memory replacement. The export-values (usually authtokens and accesstokens) as explained in Step 4 are replaced whenever an error condition occurs. These export-values are stored in memory and additional network requests are not sent every time an error condition occurs.
Let us see it in action now. We have triggered the same request with invalid tokens (with invalid accountId and authToken) twice (request 145, 146). No additional network requests were sent because the plugin had these export- values (accountId, authToken) in memory.
Regex
Regex can be confusing and scary to look at. Below is how we derived at the regex for the authToken in this example.
"authToken":"5_002-00537300-96a8_asfd-453f"
The value contains numbers, alphabets, "_" and "-". So we start our regex with the starting word:
1. authToken"
2. . - this says any character present after authToken
3. " - value starts again with double quotes
4. ([([\d\-\.\=\_\w])])* - any of the chracters inside the [] block can occur any number of times because of the * variableDigging deep into [\d\-\.\=\_\w]
1. \d - any numbers/digits
2. \- the "-" character. Special characters like -.=_ have to be prepended with \
3. \w - any alphabetsReplacement Pattern: authToken”.”([\d\-\.\=\_\w])*
We have added a couple other examples
Sample 1:Cookie: dtCookie=D3EB83FEC6121BE49F100765AAAB3953|X2RlZmF1bHR8MQ
ClientWASP: C1-73-8F-BC-2D-19-8E-A8-0E-D5-7A-79-1E-1B-28-DD-B3-4F-82-CB-96-BE-EB-F6-E7-D2-A5-89-39-21-50-14-BC-0A-6F-25-04-47-76-B5-B6-E8-BE-E2-5E-8E-25-2C-F7-A8-A1-75-9D-D6-E6-82-7B-E7-82-19-EE-E6-55-EA-4E-2C-B4-75-77-3C-E0-3A-6E-EA-24-6C-A9-F9-01-F3-58-FE-AA-96-01-64-C4-58-88-9E-38-CB-68-BC-35-6A-7B-C9-A7-31-BA-05-12-97-3C-DA-B6-86-B6-E6-D1-87-7D-0C-35-56-93-DD-10-B7-D0-B4-4B-75-E9-68-FB-D2-B7-ED-70-58-43-D2-43-49-8B-F3-EE-91-4E-7D-3A-E4-94-06-BC-A4-8D-AB-58-5D-33-2E-19-9F-DB-E6-D0-BA-A3-49-AA-38-D3<soapenv:redacted>Replacement Pattern: ClientWASP: [/\+\w\-\.\=\s]*<soapenv:Replacement Area: ClientWASP: TOKEN<soapenv:Sample 2:<ns:dataAccessKey>CClv1jhGK6yL76NpbyuEJt3cq0evkIna2yOwopGhVRqNJVelkOumb68wvd2NLd/IHSuRbSOD93pFWn9hSR3Ajw==</ns:dataAccessKey>Replacement Pattern: <ns:dataAccessKey>[\s\w\/\=\.\-]*</ns:dataAccessKey>Replacement Area: <ns:dataAccessKey>TOKEN</ns:dataAccessKey>Sample 3:X-Xsrf-Token: lCtvUU86-nxIstTP8wOy1JxaXZvAUtwVekvwReplacement Pattern: X-Xsrf-Token: ([\w\-]*)Replacement Area: X-Xsrf-Token: TOKEN
There will be a part 3 where we will talk about using ATOR for Anti-CSRF Tokens.
Authors
Ashwath Reddy (@ka3hk) — Principal Consultant at Synopsys
Manikandan Rajappan (www.linkedin.com/in/mani2raj) — Consultant at Synopsys