The OWASP Juice Shop is a vulnerable web application to train web application hacking on, much like OWASP WebGoat which I’ve already covered on this blog.
Without spoiling too much, the login form is vulnerable to SQL injection, and it is possible to dump the database from here. I’ll cover the detection of the vulnerability and how to automate exploiting it.
It is very easy to bypass the password check and login as anyone by using some Boolean logic and commenting out the rest of the query, as shown here:
myemail@somewhere.com’ OR 1=1 — –
What exactly does this do? Digging a little deeper in the login form and provoking an error (by only injecting a quote), we can see that the query done by the backend is the following:
“SELECT * FROM Users WHERE email = ‘myemail@somewhere.com’ AND password = ’81dc9bdb52d04dc20036dbd8313ed055′ AND deletedAt IS NULL”
So by injecting a quote (‘) we can break out of the email field and inject our own SQL query, in the above case one that equates to true and comments out the rest of the query, bypassing the password and deletedAt check.
Having identified the vulnerability, let’s try and dump the Users table. First step is to check the number of columns in the table and the name of these. We do this by constructing a UNION query and querying each column by ‘null’ (since we don’t know its name yet).
myemail@somewhere.com’ UNION SELECT null FROM users — –
This returns the following error:
SQLITE_ERROR: SELECTs to the left and right of UNION do not have the same number of result columns
So we continue adding nulls separated by a comma, until the error goes away:
myemail@somewhere.com’ UNION SELECT null,null,null,null,null,null,null,null,null,null,null,null from users — –
12 columns, that’s a lot! Let’s try and find names for them.
At this point we can guess the names, however the Java Web Token the application sets actually tells us almost all the column names, except one.
To find them, base64-decode the JWT.
id,username,email,isAdmin,lastLoginIp,profileImage,isActive,createdAt,
updatedAt,deletedAt,password,totpSecret
With this information, it is relatively easy to put together a Python script to completely automate the extraction of the database. The only really interesting info in the Users table is the password, so I’ve focused my script on extracting those. Although yes, I’m completely aware that the very first thing I did was bypass the password check, but it’s still nice to be able to login as anyone with their password (Juice Shop actually has an ‘achievement’ for just that!).
If you’re interested head over to my GitHub repo to check out the script.
So what do we fill up in the Password section?
It doesn’t matter, when putting OR 1=1 the query is always True. Also, the — – comments out the password check completely, so you can put anything you want.