If you're a returning visitor to our CTF Recaps, feel free to dive straight into the insights! For first-time explorers, let us quickly introduce you to the essence of these recaps. Wizer CTFs were introduced to challenge developers, encouraging them to adopt a hacker's mindset and thereby code more securely. This initiative is a pivotal part of our new security awareness training, specially crafted for development teams - Wizer's Secure Code Training for Developers!
After a challenge retires, our Wizer Wizard and CTO, Itzik Spitzen, crafts takeaways that offer valuable insights into the challenge, focusing on the defensive perspective for your script. Curious to test-drive a CTF before delving into the notes? Visit wizer-ctf.com – it's free, and there's something for all skill levels!
In this challenge, we went back to the basics to uncover and investigate an SQL injection. Did you manage to spot the vulnerability?
The login code will first call the getUser function with the supplied username and password values. This function will retrieve a record from the database where both the username and password match. If only a single row is returned, meaning a user with that username and password was found, then it returns a JSON format record with the user details, otherwise it returns an error message.
In reviewing the code, we can notice that it's likely vulnerable to SQL Injection due to the way the input variables are incorporated into the SQL Query unverified or sanitized. The variables are added using string interpolation, which is practically the same as concatenating strings, meaning that user-input (the username) is flowing directly into another system (the database). User-input flowing directly into queries to other systems always makes injection vulnerabilities likely. In this case user input flows into an SQL query, which leads to an SQL injection
A successful SQL Injection attack in this case would allow an attacker to bypass the login mechanism and login as a user without knowing the password. The attacker could achieve this by injecting a SQL query that would always return a record, regardless of the password provided. For example, inject a query that would return the first user record in the database, which would allow the attacker to login as that user. This would be typically possible by providing a payload such as 'admin' or 1 = 1
--' as the password, which would result in the following query: `SELECT userName, password, type, firstName, lastName FROM all_users WHERE userName = 'some-name' and password = 'admin' OR 1 = 1
-- limit 1` that returns all the user records in the table. However, it wouldn't be quite enough in our case, since the code checks that the query returns a single record exactly. Can you think of a way around this validation as well? hint: try to limit your injected query to return only one record :).
An SQL Injection is one of the oldest and well known vulnerabilities out there. Surprisingly, even after >20 years since it was first made public by Jeff Forristal, who published a detailed article on the security website Phrack, it still exists in the wild. An SQL Injection is potentially very harmful, and could equip an attacker with a wide range of options starting from getting unauthorized access to data all the way through account takeover or major data wipeouts.
Wanna join us on our next challenge? Sign up for our mailing list at wizer-ctf.com.