Pen-testing: Badstore v1.2.3 Walkthrough — Vulnhub

Feb 12, 2018 · 8 min read

The following is a walkthrough of this vulnhub machine from 2004. I know… it’s crazy old stuff. If this machine would still exist it’d probably look like this:

But, for the propose of experimenting with classic low-hanging web app vulnerabilities, it’s still a reliable source for beginners like me. So, the goal was to search for and exploit every vulnerability regarding the web page. My findings include:

  • Exposed directories
  • Design flaws in password reset
  • SQLi
  • XSS
  • CSRF
  • Parameter manipulation vulnerabilities
  • Poor hash algorithm
  • Poor password policy
  • Information disclosure
  • Flaws in access privileges for directories and functionalities
  • Some default credentials

Let’s start with this!

1- Doing reconnaissance and enumeration

First I boot the machine and run an Nmap scan to find where it is:

Here we can find our target on

Nmap scan report for
Host is up (0.00021s latency).
MAC Address: 08:00:27:FF:EB:3E (Oracle VirtualBox virtual NIC)

Then I ran a couple more scans to find open ports and service versions exposed:

For now I know the target runs a Linux based OS, Apache 1.3.28 (on ports 80 and 443 TCP) and a MySql server on port 3306 TCP.

Then I go to the site to get a glance of it and what type of functionalities it has. I do this while using ZAP proxy to catch all the requests and feed it with the data it needs to run the scans properly:

After playing with the site a little I go and download the site in order to do some code analysis:

2- Searching for vulnerabilities

In order to find vulnerabilities, I used the information gathered during the previous phase: OS type and version, Services information, open ports, technologies used to build the site, enumeration of inputs and functionalities.

With all that data I ran automated spidering and vulnerability scans using ZAP with custom configs, directory brute-force using DirBuster and test for XSS and SQLi both manually and using automated tools. Also, analyze the parameters and structure of every request using the browser debugger while surfing the site:

DirBuster brute-force for action inside badstore.cgi
DirBuster looking for hidden files or directories using a wordlist
sqlmap testing for injection on “cartadd” action

3- Findings

Let’s start with a big one! Observing the parameters for the registration request I noticed the role of the user to be added is actually part of the payload. This allowed me to create new admin users by modifying the parameter:

Next! There is a publicly accessible directory containing sensitive information on /supplier:

Since the data on /supplier/accounts looked like a psswd file from Linux I figure out after some time that the data was base64 encoded:

There we have… plain text credentials!

Found another exposed directory on /backup containing even more sensitive data: This time it’s a couple of backup tables of orders and users… so bad :(

To make this even worst passwords are in MD5 and they are not strong passwords at all. As an example I used heinrich@supplier’s password: / 5f4dcc3b5aa765d61d8327deb882cf99

Using hash identifier I confirm that it’s MD5

Then I can simply use an online service to recover the plaintext:

password password is password

To complete the triad of information disclosure we have a third directory exposed in /DoingBussiness containing a ‘contract’:

Much lorem such ipsum

Actually, I found a fourth accessible directory but… given the circumstances of the previous findings this is nothing:

I shouldn’t be able to access this directory like this and I should be able to see the UploadProc.html file only if I’m a supplier. But given the severity of the other vulnerabilities found and the fact that the file does not reveal information that is not already public this is not a big deal… I won’t be that hard on poor Badstore.

Now… this is huge… there are a couple of severe design issues with the password reset functionality:

  • You can reset a password just by supplying a username. The password hint is not even been used.
  • The password hint is predefined between 3 options
  • The functionality always resets the password to the predefined, hardcoded string ‘Welcome’

This results in the following issues:

  • Even tough guessing the password hint would be trivial since there are only three possibilities it’s not even necessary because the site does not check for it.
  • We only need a valid username to reset its password (and if we don’t have any we could brute force that to death because the site does not have a restriction for that)
  • We could try the password ‘Welcome’ on any user we find since there’s a chance it’s a valid password

Taking advantage of this issues I reset the admin password and get access to the admin panels:

Fuckign Kevin Spander doesn’t even have a password! C’mon men!

Also, besides this, the main page for the admin panel is accessible even for unregistered users:

This gives critical information about how the menu is and which type of operations can an admin perform using it with details about how are the request formed. The operation can’t be performed unless you are an admin but a lot of useful data is revealed.

Another huge problem here is that the traffic is not encrypted at all. Anyone sniffing the traffic could obtain plain text credentials as easily as this:

As we’d expect from a bad store, XSS is not missing. I managed to take over browsers using Beef by exploiting an XSS vulnerability in the guestbook:


The login is also broken. A simple SQLi query can give us access without having to provide a username. The SQLi becomes really obvious after trying using a quotation mark and obtaining the following error message:

Using a string as admin’ or ‘asd’=’asd as the email address let us log in as an admin user:

These guys also left a test page there… full of secrets:

m00r3 z3kr375

Oh! look! There are backups available too:

Last but not least: We go Sea-Surfing

The store has no protection against CSRF. We can observe this on user creation. There are no tokens being sent or received during the process of creating a new user:

After having collected the data needed to create a new user I now proceed to implement a javascript payload to repeat the request:

I serve the payload in my local machine on port TCP 666:

If a user would be tricked to go to my malicious link the payload would be executed:

Creating a new user with admin privileges from an IP that’s not even mine, using the resources of a victim:

This could also be used to purchase items in the store and/or abuse any other functionality that the store is offering.

Lastly, we have another possible attack vector brute forcing the DB credentials directly since the service is available for remote access.

The initial Nmap scan performed revealed a MySQL instance running on the default port. Using Metasploit mysql_login scanner module I was able to get the credentials for the database as follows:

root root root root

After having run the module we can go straight to the DB, check for the credentials and start messing around with it:

Apart from all the vulnerabilities I mentioned I also noticed there are no protections set on the headers (like X-XSS-Protection, Content-Security-Policy, and X-Frame-Options) and also Apache, MySql and OpenSSL are extremely outdated but since this Vulnhub image is from 2004 I don’t think those are things to be considered right now.

So… that’s all. I hope you like this writeup and see you around!


Shellcode for the masses


Written by


Twitter: @syscall59 | |



Shellcode for the masses

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade