Back Arrow
From the blog

8 Non-Obvious Vulnerabilities in E-Commerce Projects Built with NextJS

Ensuring security during development is crucial, especially as online and e-commerce services become more complex. To mitigate risks, we train developers in web security basics and regularly perform third-party penetration testing before launch.

Dmitry Bastron

Solution Architect / Kentico MVP

In this article, we will talk about security using the example of a multilingual e-commerce service —an online store with a buyer account. The project is built on NextJS, which is part of the backend written in JS by front-end developers. This architecture requires extra vigilance regarding security, as we'll explore in the following cases.

Penetration tests are usually performed before launching a service. While there are well-known vulnerabilities that are commonly checked, effective pentests go beyond standard methodologies to uncover unique vulnerabilities.

As mentioned above, the service we are talking about is built on NextJS with the following architecture: 

  • Page rendering occurs on NextJS
  • Content and user data are retrieved via Umbraco’s API (which recently released its Content Delivery API for headless solutions) 
  • User sessions are created in Umbraco and then used in NextJS
  • E-commerce functionality is handled by Shopify, with which the NextJS site interacts via API 

This architecture distributes security responsibilities between backend and frontend developers, potentially leading to vulnerabilities on both sides.

Problem #1 – Data Leakage When Passing Filter Values ​​to the API

Feature: In the personal account, the user can view their current subscriptions. The data is retrieved via a POST request from the “my account” API to Umbraco, which then pulls active subscriptions from Shopify. The tester intercepted this request, examined its contents, removed the user session cookie from it, and passed an empty request body. As a result, they received all subscriptions of all users.

When developing such features, it’s crucial to consider the overall architecture of the application and how the backend and frontend communicate. Looking at the diagram above, consider the sequence of receiving subscriptions:

  1. The client JS application requests subscriptions of the current user from the NextJS website, passing the cookie of the current user session and the email of the current user—the data that the tester removed during testing.
  2. NextJS website, knowing the secret Application token of Umbraco, requests subscriptions from Umbraco, forwarding the same user email as a filter.
  3. Umbraco, knowing the secret Application token of Shopify, requests subscriptions from Shopify, again forwarding the user email from the parameters.

Separately, both the frontend and backend functioned correctly, but a security hole appeared when integrated —no one checked the user's session: the frontend thought that the session would be checked by the backend on Umbraco, and the backend thought that the frontend would check the session on NextJS.

Additionally, the Shopify API, when passed an empty email as a parameter, returns all subscriptions of all users, meaning the email parameter acts as a filter, and if it is empty, everything is returned. This combination led to the discovered problem.

How to do it right

You shouldn't pass email and other user data as request parameters from a client JS application. Instead, retrieve the user's email from the current user's session context, and validate this session.

Problem #2 – Access Rights Verification Using Request Parameters Instead of Current Session

The website has the ability to change the password. Testers intercepted the change password request,removed the identification cookie, and sent an empty request with only a body, containing the old and new passwords, to the backend. In one place, security allowed such a request, and checked it in another. When making a request to change the password, retrieve information about the logged-in user from identification cookies, not parameters.

Another similar case : the website has a project builder section, like favourites, where the user can arrange the products they like in project folders. Testers intercepted a request, removed the identification cookie, but left the request body, which included information on which user to create a collection for and from which products. As a result, they could update another user's favourites without authentication. None of the security levels prevented such penetration.

In both cases, the same vulnerability: data is transmitted as parameters in the API instead of being taken from the current user's session.

Problem #3 – Possibility of Recording a Malicious Script When Creating Entities

There may be situations on the website when a user, especially true for user portals,can create some entity that the website will display later. For example, the above-mentioned project folders. In some cases, the website allows the insertion of not only letters as a project name but also a piece of script that, for example, will steal user cookies. When an intruder does this, user cookies may appear in the alert or be sent somewhere.

One might argue: I create a project for myself, so no one except me can see this data.However, this functionality can evolve: initially, the project name display is available only to a unique user, but later, an admin role might appear.If an admin user encounters this vulnerability, their data might be compromised. Another development possibility is adding the function of sharing projects between users. The user gives the project to another, the script executes, and the cookies are stolen.

Problem #4 – Possibility of Сreating a Redirect to a Phishing Website

Redirects. A user navigating the site can add a product to the cart and then proceed to checkout. The peculiarity of the website implementation is that e-commerce is made on Shopify – the cart is rendered on our website, but for checkout – delivery and payment – ​​we redirect the user to the Shopify portal.

If the user is logged in on our website, the same logged-in state must be preserved when redirecting to Shopify. In Shopify terminology, this Single-SignOn implementation is called Multipass, and you can read about it in detail here.

In short, to generate a redirect, NextJS sends a request with the URL for the redirect to the Umbraco API, which encrypts this URL with a secret key from Shopify, and substitutes the user ID needed for login during the redirect. Our Umbraco API code allows any URL to be inserted into the redirect , and URL Shopify doesn't check it during the redirect. 

This is dangerous because it can lead to phishing. An intruder can prepare a phishing website that looks like your website: the first domain will be valid, but when clicking on the link, the user will be redirected to the phishing site and may trust the initial appearance, giving out their data.

How to do it right

Ensure that the redirect logic checks the redirect URL for a known domain before executing the redirect.

Problem #5 – Unhindered Password Guessing

When logging into a website, the user enters a login and password, after which a request is sent to the server. Some websites do no limit the number of login attempts. In such cases, an attacker can prepare a script for password guessing and run it for a long time.

Usually, a couple of levels of protection are implemented. Login forms can be hidden under a captcha —thus, an attacker must automate captcha solving for repeated attempts. 

Alternatively, an invisible Google captcha can be used, checked on the backend before further code execution. Another method is rate limiting:limit attempts from one IP, browser, etc.  The simplest approach is to return an error after several login attempts from one IP address. Algorithms can also increase waiting times: the first incorrect login attempt gets a quick response, the second takes more time, and so on. If response time increases exponentially, several failed attempts will result in a long wait.

Problem #6 – Active Sessions After Password Change

Imagine someone has hacked a user's account and started doing something on the website on their behalf. The user immediately resets the password, but the attacker remains logged in, since their session is still active.

Resetting the password should also invalidate all active sessions created for the user. Thus, if the NextJS application is responsible for creating and checking sessions, all active sessions should be reset when the user's password is reset to prevent a security hole.

How to do it right

To implement this logic, store the user's active sessions somewhere, since NextJS does not do this natively. In our case, we stored active sessions in the Umbraco database, and the NextJS application updated session data via the API.

Problem #7 – Script and HTML Injection in User Registration

In the registration form on the website, you can enter a script and HTML markup in the user's first and last name fields. Usually, the backend provides protection against SQL injections, but protection against frontend scripts is not always obvious.

Why is this dangerous? Registration data collected by the website is often inserted into the registration confirmation email. For example, “Good afternoon, UserName! Thank you for registering on our portal.”

A user can register on a third-party website on behalf of a victim, who will receive an email from a valid site with links and scripts that execute if the victim clicks the link. This problem is solved by validating input parameters during user registration.

Problem #8 – Risk of Increasing Third-Party Service Bills

Incorrect Google Maps API keys setup (and any other paid services and APIs allowing domain usage limits). If domain settings are incorrect, these keys can be used on other sites, and the client will pay more money. There are cases when keys were stolen, and the website owner paid thousands of dollars.

How to do it right

In addition to setting up restrictions for these keys, it’s crucial to optimise the number of requests to paid services.. Inefficient code can lead to excessive API calls, potentially allowing competitors to exploit your resources and increase your costs.

 To limit the number of requests, consider reducing the search area and minimising requests to Google Places.  A common inefficiency occurs when the map component is initialised on every page load, even when the map is located far down the page or hidden in an inactive tab. Implement lazy loading to initialise map components only when necessary.

Conclusion

These security considerations apply to software development in general, not just e-commerce platforms or similar projects. However, NextJS applications are particularly prone to security vulnerabilities due to the unique redistribution of responsibilities between frontend and backend tasks. By keeping these scenarios in mind, development teams can better protect themselves and their users from potential security risks.

It's easy to start working with us. Just fill the brief or call us.

Find out more
White Arrow
From the blog
Related articles

Inspecting raw database data in Xperience by Kentico

Dmitry Bastron

This article is a cheat sheet to inspect what's going on with the imported data by Xperience by Kentico Migration Toolkit, resolve some CI/CD issues and on many other occasions!

Kentico

Learnings from using Sitecore ADM

Anna Bastron

Let's try to understand how the ADM module works, its limitations and tactics for optimising its performance.

Sitecore

Your last migration to Xperience by Kentico

Dmitry Bastron

The more mature Xperience by Kentico product becomes, the more often I hear "How can we migrate there?”

Kentico

5 Key Software Architecture Principles for Starting Your Next Project

Andrey Stepanov

In this article, we will touch on where to start designing the architecture and how to make sure that you don’t have to redo it during the process.

Architecture
Software development

Assessing Algorithm Complexity in C#: Memory and Time Examples

Anton Vorotyncev

Today, we will talk about assessing algorithm complexity and clearly demonstrate how this complexity affects the performance of the code.

.NET

Top 8 B2B Client Service Trends to Watch in 2024

Tatiana Golovacheva

The development market today feels like a race - each lap is quicker, and one wrong move can cost you. In this race, excellent client service can either add extra points or lead to a loss dot to high competition.

Customer Service
Client Service

How personalisation works in Sitecore XM Cloud

Anna Bastron

In my previous article, I shared a comprehensive troubleshooting guide for Sitecore XM Cloud tracking and personalisation. This article visualises what happens behind the scenes when you enable personalisation and tracking in your Sitecore XM Cloud applications.

Sitecore

Server and client components in Next.js: when, how and why?

Sergei Pestov

All the text and examples in this article refer to Next.js 13.4 and newer versions, in which React Server Components have gained stable status and became the recommended approach for developing applications using Next.js.

Next.js

How to properly measure code speed in .NET

Anton Vorotyncev

Imagine you have a solution to a problem or a task, and now you need to evaluate the optimality of this solution from a performance perspective.

.NET

Formalizing API Workflow in .NET Microservices

Artyom Chernenko

Let's talk about how to organize the interaction of microservices in a large, long-lived product, both synchronously and asynchronously.

.NET

Hidden Aspects of TypeScript and How to Resolve Them

Dmitry Berdnikov

We suggest using a special editor to immediately check each example while reading the article. This editor is convenient because you can switch the TypeScript version in it.

TypeScript

Troubleshooting tracking and personalisation in Sitecore XM Cloud

Anna Gevel

One of the first things I tested in Sitecore XM Cloud was embedded tracking and personalisation capabilities. It has been really interesting to see what is available out-of-the-box, how much flexibility XM Cloud offers to marketing teams and what is required from developers to set it up.

Sitecore

Mastering advanced tracking with Kentico Xperience

Dmitry Bastron

We will take you on a journey through a real-life scenario of implementing advanced tracking and analytics using Kentico Xperience 13 DXP.

Kentico
Devtools

Why is Kentico of such significance to us?

Anastasia Medvedeva

Kentico stands as one of our principal development tools, we believe it would be fitting to address why we opt to work with Kentico and why we allocate substantial time to cultivating our experts in this DXP.

Kentico

Where to start learning Sitecore - An interview with Sitecore MVP Anna Gevel

Anna Gevel

As a software development company, we at Byteminds truly believe that learning and sharing knowledge is one of the best ways of growing technical expertise.

Sitecore

Sitecore replatforming and upgrades

Anastasia Medvedeva

Our expertise spans full-scale builds and support to upgrades and replatforming.

Sitecore

How we improved page load speed for Next.js ecommerce website by 50%

Sergei Pestov

How to stop declining of the performance indicators of your ecommerce website and perform optimising page load performance.

Next.js

Sitecore integration with Azure Active Directory B2C

Dmitry Bastron

We would like to share our experience of integrating Sitecore 9.3 with the Azure AD B2C (Azure Active Directory Business to Consumer) user management system.

Sitecore
Azure

Activity logging with Xperience by Kentico

Dmitry Bastron

We'll dive into practical implementation in your Xperience by Kentico project. We'll guide you through setting up a custom activity type and show you how to log visitor activities effectively.

Kentico

Interesting features of devtools for QA

Egor Yaroslavcev

Chrome DevTools serves as a developer console, offering an array of in-browser tools for constructing and debugging websites and applications.

Devtools
QA

Kentico replatforming and upgrades

Anastasia Medvedeva

Since 2015, we've been harnessing Kentico's capabilities well beyond its core CMS functions.

Kentico

Umbraco replatforming and upgrades

Anastasia Medvedeva

Our team boasts several developers experienced in working with Umbraco, specialising in development, upgrading, and replatforming from other CMS to Umbraco.

Umbraco

Sitecore Personalize: tips & tricks for decision models and programmable nodes

Anna Gevel

We've collected various findings around decision models and programmable nodes working with Sitecore Personalize.

Sitecore

Fixed Price, Time & Materials, and Retainer: How to Choose the Right Agreement for Your Project with Us

Andrey Stepanov

We will explain how these agreements differ from one another and what projects they are suitable for.

Customer success

Enterprise projects: what does a developer need to know?

Fedor Kiselev

Let's talk about what enterprise development is, what nuance enterprise projects may have, and which skills you need to acquire to successfully work within the .NET stack.

Development

Headless CMS. Identifying Ideal Use Cases and Speeding Up Time-to-Market

Andrey Stepanov

All you need to know about Headless CMS. We also share the knowledge about benefits of Headless CMS, its pros and cons.

Headless CMS

Dynamic URL routing with Kontent.ai

We'll consider the top-to-bottom approach for modeling content relationships, as it is more user-friendly for content editors working in the Kontent.ai admin interface.

Kontent Ai
This website uses cookies. View Privacy Policy.