Exploiting open redirect - Whitelist bypass using Salesforce environment
Hey folks, Today, I am going to discuss one of the interesting scenarios that I came across while testing an application. A scenario of exploiting an Open Redirect vulnerability. I know it’s not a big deal to exploit open redirect, but it’s a little bit different, and exploitation of this requires basic knowledge of salesforce. So instead of moving round & round, let’s discuss the vulnerability straight.
Note: This is not about open the redirect vulnerability in salesforce.com.
Overview of vulnerability
Recently I did a security assessment of an application; instead of disclosing the name, lets say it example.com, so when I open one of the subdomains, for example, abc.example.com, that page shows an error saying “Invalid redirect URL”. It immediately strikes me that there could be an Open redirect vulnerability.
First, I have used a very basic approach, I tried to fuzz that parameter with values like, redirectUrl, redirectTo, etc… but none of them gave success. Then I quickly open a page source and come to know that it’s a state parameter, silly me.
Here the application will,
- Read the value of
- Then it split the string by
- Grab the first value out of it,
- And lastly, perform base64 decoding on that value which should be a valid URL.
Now here comes a 1st complexity, as you can see in the above screenshot, the application uses a whitelist of domains, and only values that belong to that whitelist are allowed as a value of state parameter. After seeing this, I surrender for that day and move to other functionality.
But my gut feeling kept pinging me to check that again, After doing some more digging, I came to know that
salesforce.com allows its user to create a custom domain, they use a terminology called
My Domain. That means I can create
customsubdomain.my.salesforce.com. Now if you have seen the above screenshot, you will come to know that the application uses
.endswith() method to compare the string that means,
"salesforce.com".endsWith('salesforce.com') == "customsubdomain.my.salesforce.com".endsWith('salesforce.com').
After knowing this, I crafted a payload (base64 encoded) and passed it as query parameter in the request and yes, it redirected to
Without wasting any more time, I have reported this to the program owner, and by my all excitement, they had marked it as Not Applicable, saying you can not redirect it to any domain, and therefore, we are marking it as Not Applicable. I was like what….
This should not be the reason for marking this vulnerability as N\A, so I have responded to them by providing various standard definitions saying open redirect does not mean to redirect any domain, it only meant to redirect the victim to the attacker’s controlled domain. And as the answer to my concerns, they told me to provide a working exploit of it, and there comes my 2nd complexity.
Literally don’t have much idea of what salesforce is and how its subdomain works. Initially, I was thinking like if salesforce.com is allowing users to create their own subdomain, then surely they will allow users to host his/her own content as well. But that becomes my biggest myth about it.
Salesforce is the customer relationship management (CRM) platform, it also provides a complementary suite of enterprise applications focused on customer service, marketing automation, analytics, and application development, you can know more by visiting salesforce.com.
After getting basic information about salesforce I come to know that although salesforce allows us to create a
my domain, we can not host our content like serving index.html or index.php file or any other page which can directly serve when user navigates to the URL
https://customsubdomain.my.salesforce.com. Moreover, when we open the link/page (For ex:
https://customsubdomain.my.salesforce.com) it will first ask us to enter salesforce credentials, and once we provide valid credentials, it will navigate us to our salesforce dashboard page. Also, the salesforce login page is not in user/attacker’s control that means asking for credentials from the victim will also not make any sense as there would be no way to get those credentials.
Failed test cases
I have asked a few of my friends for some help, I have tried or thought of many other things myself as well, but none of them worked.
I have tried or thought of the below things:
Page without login: I was thinking whether it is possible to host a page on salesforce without login or not, By this, I meant to host a page that does not ask for salesforce credentials, but there is no such thing salesforce allows, as per my understanding.
Is login parameters controlled by administrator: By this what I want is, is there anything on login page that can be controlled by admin user of our site, that way also we can grab the credentials of victim as we were the admin of our salesforce account, but again no success.
Redirect after login: I thought of one more scenario where salesforce redirects users immediately after login to the 3rd party page, which can be controlled by the attacker, and as the attacker owns the salesforce page, he/she can set up 3rd party domain on salesforce. I am not sure, but one can work on this point as I do have some gut feeling for this option. But I did not give much effort on this as I do not want the complexity of this exploit to be much difficult.
Internal Trigger or Webhook: By this, I meant, whether there is any trigger that can inform the admin that someone has tried to login and provide any way where we can log credentials of the victim who tried to log in or is there any webhook for login attempt where we can log victim’s credentials.
But, unfortunately, I did not get any success or maybe my efforts were not up to the mark.
3rd party authentication wins !!!
When I was searching for a way to get something on the login page or anything that I can control on the login page, I found an article about how we can integrate 3rd party authentication providers in salesforce and also read about Apex classes. This gave me an idea to set up a 3rd party auth provider and also write an apex class for login handler. I planned to integrate Github as a 3rd party authentication provider.
Now, the path is clear. Our aim is to grab the victim’s github access token.
To execute this plan, we have to setup Github SSO as 3rd party authentication provider in salesforce, and for that, we need to follow below steps,
1. My Domain: In salesforce, you can create your custom domain under
My Domain, that domain will look like
yourCustomDomain.my.salesforce.com. So we need to create a new domain having a similar name to which you are performing phishing.
2. Custom metadata: Next step is to create custom metadata in salesforce, where we will be storing Github details like what is clientId, client secret, what will be callback url, etc…, You can type “metadata” in the quick search box and create new custom metadata.
3. Custom fields: Once we have created a custom metadata, we need to create custom fields which we will later map in the apex class. We need to create below-mentioned fields with its proper data type, the usage of those fields are self explanatory: - Auth URL: Used to get authorization code - Callback URL: callback URL is the one where the user will redirect once the authentication is completed. - Consumer Key: Github consumer key will be stored here - Consumer Secret: Github secret key will be stored here - scope: Scope will define what kind of access we wanted to get from the victim’s Github account. - Token URL: Used to get access token - User Info URL: This will help us to get the URL endpoint from where we can get the logged user’s details.
4. OAuth application: Before moving further, we need to create a new OAuth application in Github which allows users to login into the salesforce environment using Github. We can create it from the developer setting of Github settings. In the OAuth application setting, at this moment, set any dummy URL as a
callback URL parameter, we will need to change it later. Once the application is created, there will be Client Id & client secret generated, just note it down we will use these values later.
5. Apex class: We need to create a new APEX class to handle the login. To create this class, we need to extend the
Auth.AuthProviderPluginClass class as we wanted to use its methods in our apex class. You can search it in google
Auth.AuthProviderPluginClass for more details.
Above code will basically redirect victim to a page where it will ask for Github credentials, and once the user will be authorized from Github below code will execute and allow us to capture the access token of the user.
As an attacker, I skipped the last part of the actual implementation of 3rd party auth provider as I do not want to add any user in my salesforce account, I just need the victim user’s access token, and that’s it.
For readability I am not showing full class details, you can find it here: GithubRegistrationHandlerToExploitOpenRedirect
6. Auth Provider: Once the class generation is completed and if everything went well, you will find a new entry in the list of
Auth. Provider. Open that provider and Add details. You would require to enter details like authorize url, token url, consumer key & secret (You can copy it from github app), scope, callback url, etc… To know this value, one needs to look through Github’s API document, you will find the value of authorization URL, token URL, what are the possible values for scope there. Leave the Callback URL empty for a while.
Once you added all the details, you will find a
salesforce configuration values generated below auth provider values, copy
Callback URL and paste it at both the place, first in auth provider itself and second in our Github OAuth application we created in step-4.
7. Add Remote Sites: This configuration of salesforce allow user to add domain which could be opened or requested from salesforce environment ( For example in our case, we need to add these values in remote sites settings: https://github.com , https://api.github.com & burpcollaborator URL)
8. My domain login configuration: Update the
authentication configuration from
My domain settings, you can allow both logins (Login using salesforce & Login using Github like in below screenshot), but as an attacker, if you want to exploit victim you should only allow login using Github, which force the user to redirect on Github login page when you will send your salesforce URL.
I did not know how to write apex class in much detail, so pardon me if I had made any mistake, and if you have any doubts or confusion on how we can add 3rd party authentication provider in salesforce, I suggest you to watch this video. This video basically has an in-detail explanation of how we can integrate 3rd party authentication. Also, it has full flow information where in my case, I don’t want the victim to be login into my salesforce environment, so I explicitly write a code that will give an exception to the user who has attempted to log in at the end of login process that is once authorized from Github.
Now we are all good to exploit the victim for a phishing attack.
- Perform base64 decoding on our
My Domainvalue with some junk token value as 2nd parameter, place that value as a
stateparameter and prepare a link
- Send that link to the victim user.
- Once the user opens the URL, it navigates to the Github login page as we have set up Github SSO only and not salesforce login.
- Victim will try to login with their github credentials.
- Our loginhandler apex class will be invoked.
- We have written a logic there which will send an error page to the victim and meanwhile also send the access token of victim’s github account to the Burp collaborator, and that is it, once we have access token we can grab whatever details we want as mentioned in the scope parameter.
After all this explanation and video PoC, the program owner accepts it as a valid security issue , and there it is, a HAPPY ENDING, :)
Cheers & Happy hacking.
Payatu is a Research Focused, CERT-In impaneled Cybersecurity Consulting company specializing in security assessments of IoT product ecosystem, Web application & Network with a proven track record of securing applications and infrastructure for customers across 20+ countries. Get in touch with us. Click on the get started button below.