The project aimed to expose us to the world of computer security through research and hands-on experimentation. As we were attached to the purple team of the Enterprise IT programme centre who were in-charge of the cybersecurity needs of the EIT PC, we were guided through the use of Webgoat and the research of our chosen web application vulnerability.
We were tasked with trying out the various challenges found on Webgoat. Through the lessons we learnt from Webgoat, we were then supposed to research on one of the OWASP Top 10 vulnerabilities and present it to the director, our mentors and our fellow interns. Webgoat is a web application intentionally designed with various vulnerabilities in order for us to learn how we can exploit these vulnerabilities and how we can mitigate its impacts. The OWASP Top 10 is a list of the most pressing web application vulnerabilities published by OWASP, the Open Web Application Security Project.
During the December holidays, we were tasked by our mentors to read up more about the following topics related to computer security so that we will have a basic foundation regarding web applications:
Throughout the attachment, we spent a considerable amount of time trying to complete the challenges found on Webgoat. Some of the challenges were relatively easier while some of them required a lot of effort in order to resolve. There were a handful of questions that were too challenging for us and we resorted to finding the solutions online. However, when we did this, we made sure that, after checking to make sure that the solution works, we thoroughly read through and understood the solutions before moving on.
There were also many terms that appeared in the Webgoat lessons that were new to us. Hence, we had to search up the meaning of these terms and the part that they play in web applications. These searches typically brought up other words that we had not seen before and we searched those new words online as well in order to ensure that we get a full picture of web application security.
The deliverable that we had to present to DSTA was an individual presentation to the director, mentors, other EIT staff as well as other interns on the 23rd of January. For our presentation, we had to choose one of the Top 10 vulnerabilities to research and present in a 5 minutes long presentation. Our presentations contained a self-introduction to tell the director and staff more about who we are, our interests as well as our motivation for choosing this project. We then dived into the impacts of our chosen vulnerabilities before showing what we learnt about the vulnerability, including how it can be exploited as well as how it can be defended. At the end, all the interns also presented more about our experiences at DSTA and what we took away from this 3 weeks long attachment.
We had prepared a report containing all the information that we managed to find regarding our chosen vulnerabilities that contains information that did not make it into the presentation to the directors due to the limited time. We also prepared a daily log containing our day-to-day activities as well as a reflection containing the hard and soft skills as well as lesson that we had learnt through this attachment to DSTA.
The Open Web Application Security Project, abbreviated as OWASP, is a non-profit foundation aimed at improving the security of web applications through collaborative, community-led open-source project[1]. The OWASP Top 10 project aimed to raise awareness amongst developers and companies but it has since evolved into the de facto application standard. It is released every 3 to 4 years and has collaborated with the community to highlight the biggest vulnerabilities present in contemporary web applications[2].
SQL Injection has been at the top of the OWASP top 10 for the past three releases[3] which highlights how prevalent and how much of a risk it poses to web security. SQL injection makes use of input fields in web applications. These types of input fields typically query against a database in order to retrieve relevant information to display for the user. However, if they are not properly implemented, the fields may allow the user to execute malicious code by entering specific queries[4].
SQL Injection has the potential to compromise what’s known as the CIA triad. SQL Injection can compromise availability by simply dropping the databases required or by preventing users from accessing them via some other means. SQL Injection can compromise integrity by removing or adding certain rows or columns in a table that could cause users to misunderstand the dataset or be provided with inaccurate information. Lastly, SQL Injection can compromise confidentiality by disclosing information to unauthorised people who should not have that information[5].
SQL injection has high exploitability as almost anything and any web application that contains any type of user input has could potentially have vulnerabilities that can be exploited using SQL injection. It is also very prevalent and extremely easy for attackers to exploit as many web applications, especially those containing legacy code, contains input fields that are vulnerable to SQL injection and many services, such as scanners and fuzzers[6] are able to automatically detect these vulnerabilities if they are present on web apps. Lastly, they pose significant technical risk due to its ability to compromise all 3 aspects of the CIA triad and potentially reveal information that allow attackers to gain full admin access and rights[7].
Now, you might be wondering what the relevance of SQL injection might be in the real world, and here are a few examples of how SQL injection could have been used maliciously in the past and also some SQL injection vulnerabilities disclosed by whitehat hackers.
The first example here was disclosed on HackerOne, a website dedicated to connecting businesses with penetration testers and cybersecurity experts in order to discover and responsibly disclose potential vulnerabilities for at-risk companies to fix or mitigate[8]. The first example here was disclosed by a user by the name of moskowsky and it was disclosed on the 28th of July, 2018. The vulnerability, as summarised by Valve, the vulnerability affected the Steam gaming platform and could be used to read certain data to read certain SQL data from a single backing database due to an unvalidated parameter[9]. The vulnerability was given a severity rating of Critical with a numerical rating of 9.9 out of 10 on the Common Vulnerability Scoring Scheme which allows companies to appropriate gauge and triage the impact of the vulnerabilities[10]. Valve proceeded to pay a $20000 bug bounty and an additional $5000 bonus to moskowsky.
Additionally, in the leak of the Panama Papers[11], it is suspected that the people involved in the leakages exploited a vulnerability related to an SQL injection in order to gain access to the database. Mossack Fonseca, the law firm involved in the leaks, was a Panama-based law firm that helped people transfer their wealth to tax havens such as Panama to avoid taxation. According to a security expert, they had shown “astonishing” disregard for security by not updating their services in a timely manner. As of 2016, their Outlook Web Access login was last updated in 2009 and their client login portal was last updated in 2013. It was the outdated version of Drupal, an open-source website content management system, that had 25 vulnerabilities, one of which was a high-risk SQL injection vulnerability that allows people to execute arbitrary command within their database[12].
Using the following example vulnerable code provided regarding injection[13],
SELECT name FROM users WHERE
username = 'username'
AND password = 'password'
The vulnerability exists because of the section highlighted in red. It takes unescaped and unvalidated user input, in this case, presumably from a text input asking for the users’ username and password and proceeds to run the following query against the database. The database table could potentially look similar to the following database:
In a perfect scenario, what will happen is that the user will enter their actual username and password, in this case John_doe123
and thisissecure
:
SELECT name FROM users WHERE
username = 'John_doe123'
AND password = 'thisissecure'
This will only return the details of John Doe’s account as the parts highlighted will only both return true for John Doe’s own account as only then will the username and password associated with the account in the database equal to those in the data entered, thus returning only John Doe’s name, John Doe.
However, if someone was aware that this was a vulnerable field and they were looking to maliciously exploit the entry field, they could gain entry into the administrator account through the following input which would be read by the programme as actual code instead of just user input, allowing the attacker to execute any code they’d want:
Username: administrator'--
Password: (anything)
The will result in the following query being executed, if there are no validations in place.
SELECT name FROM users WHERE
username = 'administrator'--'
AND password = '(anything)'
This will automatically log the attacker into the administrator’s account. This is because the --
[14] character sequence is recognised in SQL to designate that anything after it is a comment and should not be executed. Hence, the query above will only check that there is an account with the username administrator and log the attacker in without double-checking the password as the password check is commented out.
The attacker can also enter the following input:
Username: administrator'; SELECT * FROM users;--
Password: (anything)
This will effectively result in the entire table being printed as the *
character tells the programme that you want to return everything from the table that contains all the user data. This is because the ;
represents a new query, starting the query of SELECT * FROM users;
[15].
Even without an entry field, SQL injection can still be carried by modifying the URL of a website. For example, a website’s URL might look something like this:
http://w34ksite.com/products.php?category=1
The highlighted part is a SQL query that has been disguised in the URL of the website. When it is converted into an SQL query, it will look something like this[16]:
SELECT * FROM products WHERE category=1;
Hence, the attacker can then modify the URL to the following or something similar in order to be able to extract information, in this case all the emails, from the website in question:
http://w34ksite.com/products.php?category=1 UNION ALL SELECT *, NULL, NULL FROM email
This indicates that the URL of websites are also potentially vulnerable to SQL injection and that it is not only input fields that have to be guarded against SQL injection
Error-based SQL Injections rely on there being an error that is thrown by the programme and consequently displayed to the user to tell the attacker more about the structure of the programme, including the functions involved and the programme’s data structure[17]. Through trial and error, it is possible for the attacker to find out critical information such as the name of the database and tables and also the number and names of the columns[18]. For example, the attacker can add the following to the end of his input[19]:
' ORDER BY 1
' ORDER BY 2
' ORDER BY 3
The ORDER BY
function is intended to sort a table according to a certain column’s data, however, by enumerating through the different columns, we can find out how many columns there are in the table, which is important when executing a Union-based SQL Injection. This is because an error of the following will be thrown if we exceed the number of columns in the original select query, allowing us to know the number of columns present:
The ORDER BY position number 3 is out of range of the number of items in the select list.
After obtaining adequate information about the database and tables, such as the number and data types of the columns, we can then find out more information by exploiting a union-based SQL injection. This exploits the way that the UNION
operator works in SQL. The function of the UNION
operator is to join the results of two separate SELECT
operations into a single table. However, the UNION
operator only works when both tables have the same number of columns, which is why it is important to figure out the number of columns in a table using Error-based SQL Injections or through other means[20].
For example, the following code might have been used to sort though and only return things from a certain category:
SELECT name FROM products WHERE category='toys';
However, this field can be maliciously manipulated to return data that should be kept confidential and not publicly available, even if the data was kept on another table. By entering an input similar to the following, the attacker can retrieve information from another table in the same database[21], such as users, along with sensitive data:
INPUT: toys' AND 1=2 UNION SELECT CONCAT(username, “~”, password) AS login FROM members;--
SELECT name FROM products WHERE category=1 AND 1=2 UNION SELECT CONCAT(username, “~”, password) AS login FROM members;--
The first highlighted portion will always return a value of false
as 1=2
will always return false
which makes the entire WHERE
conditional false
due to the AND
operator. This ensures that any data that is returned will always be the data the attacker is aiming to extract which comes from the back half of the UNION
query. The CONCAT()
[22] operator is important as the UNION
operator only works when the first SELECT
operation and the second SELECT
operation returns the same number of columns, as such, we have to join the username and password into one column which we give the alias of login.This will return the table of information containing all of the users’ username and password which can be maliciously used[23].
Boolean-based SQL Injection queries the database using queries that are designed to return either true
or false
boolean values. This approach is extremely time-consuming as the attacker has to manually enumerate through all the possible characters for the entire length of the entry that they are trying to find out.
For example, in trying to find out the password of an account, the attacker can try to insert something similar to the following query into a login field where 'tom'
is a registered account name:
USERNAME: tom' AND substring(password,1,1)='t
The complete query will look similar to this:
SELECT * FROM user WHERE username='tom' AND substring(password,1,1)='t';
We know that the first part will return true
as 'tom'
is indeed a valid account name. However, the entire statement will only return true
when the second part, which is highlighted, returns true as well. It will only return true
when the first letter of tom’s password is t
as the substring()
function takes in 3 parameters. The first one is the string to cut, which in this case, is the password of tom’s account. The next integer represents the location of the first character included in the cut and the last integer represents the length of the cut[24]. The attacker will then continue to try out all the possible characters for the second character by running:
USERNAME: tom' AND substring(password,1,2)='tx
The attacker will continue to do so until they have guessed the entire length of the password through fuzzing the possible characters. This method however, only works when the web application gives a different response depending on if the query returns true
or false
[25].
By using the IF()
operator in SQL injections, the attacker can implement a delay if a certain boolean conditional constructed returns true or false. This is especially useful if the web application is indeed vulnerable to SQL injections but do not show a visible difference in response if the query returns true or false. Additionally, such attacks will usually also not be logged by the web application, allowing the attacker to carry out their attack discretely. By analysing the differences in the time taken for a response to the query to be generated, the attacker can tell if the conditional they added into the query returned true
or false
.
For example, an attacker can input the following code to try to fuzz the password of the administrator’s account, with the highlighted section being the attacker’s input:
SELECT * FROM products WHERE id=1; IF SYSTEM_USER='sa' WAIT FOR DELAY '00:00:15';--
In this case, if SYSTEM_USER
does indeed equal to 'sa'
, there would be a 15 seconds delay in the response provided by the web application as the delay will also execute when the first conditional evaluates to true
. This process will require the attacker to slowly enumerate through the various possible characters and also keenly monitor the delays in the responses provided by the web application[27].
Most of the ways of mitigating the impacts of SQL injection involves explicitly differentiating and indicating which segments of the query are meant to be executed as part of the SQL query and which parts of the query are meant to be understood and interpreted to be user input. This mainly involves inserting user input into the SQL query as parameters or by escaping certain characters so that the programme understands that it is not meant to be read as part of the code.
The simplest way to prevent SQL injection is to ensure that a value that does not correspond to a valid search term will not even be allowed to execute[28].
For example, in the case of searching through a catalog of items at a store, the following code can be used to ensure that only search terms that contain valid categories will be allowed through, otherwise, an error will be thrown, preventing any malicious injected code from being erroneously run by the programme (the example is done in JavaScript)[29]:
String columnName;
switch(PARAM):
case "food" : x.do();
break;
case "drinks": y.do();
break;
...
default : Throw Error;
Hence, if anyone were to enter code for an SQL injection, it would not be recognised as a valid column name and therefore, it will not be run as the programme will run the default function which is to throw an error.
Prepared statements with parameterised queries forces the application developer to first write all the SQL query-related code explicitly before passing each of the users’ input into the query as parameters later on. This allows the application to very clearly and easily distinguish between what is meant to be a user-input string and what is meant to be part of the SQL query[30].
The following code, written in JavaScript, makes it clear to the programme that "customerName"
should be considered as a user-input string and not to be part of the query to be executed:
String custname = request.getParameter("customerName");
String query = "SELECT account_balance FROM user_data WHERE user_name = ? ";
PreparedStatement pstmt = connection.prepareStatement( query );
pstmt.setString( 1, custname);
ResultSet results = pstmt.executeQuery( );
The first line simply obtains the user input from a field known as "customerName"
. The second line crafts the SQL query, leaving the ?
to indicate a parameter where the user input should be substituted into to form a complete query. The third line creates a PreparedStatement
using the query defined in line 2. The fourth line then replaces the first parameter, the ?
, with the user-input. The last line stores the value returned by the query as a ResultSet
[31].
[1] OWASP. (2020). Who is the OWASP Foundation? Retrieved January 18, 2020, from https://owasp.org/
[2] OWASP. (2017). OWASP Top 10 - Foreward. Retrieved January 18, 2020, from https://owasp.org/www-project-top-ten/OWASP_Top_Ten_2017/
[3] Open Web Application Security Project (OWASP). (2010, April 19). OWASP TOP 10 FOR 2010 RELEASED. Retrieved January 16, 2020, from http
s://www.owasp.org/index.php/OWASPTop10-2010-PressRelease
[4] w3schools.com. (n.d.). SQL Injection. Retrieved January 27, 2020, from https://www.w3schools.com/sql/sql_injection.asp
[5] Purcell, A. (2018, January 15). 3 key ideas to help drive compliance in the cloud. Retrieved January 27, 2020, from https://www.ibm.com/blogs/cloud-computing/2018/01/16/drive-compliance-cloud/
[6] OWASP. (n.d.). Fuzzing. Retrieved January 18, 2020, from https://owasp.org/www-community/Fuzzing
[7] OWASP. (n.d.). A1-Injection. Retrieved January 19, 2020, from https://owasp.org/www-project-top-ten/OWASP_Top_Ten_2017/Top_10-2017_A1-Injection.html
[8] Perlroth, N. (2015, June 8). HackerOne Connects Hackers With Companies, and Hopes for a Win-Win. Retrieved January 16, 2020, from https://www.nytimes.com/2015/06/08/technology/hackerone-connects-hackers-with-companies-and-hopes-for-a-win-win.html?_r=0
[9] Artem (moskowsky). (2018, July 28). Valve disclosed on HackerOne: SQL Injection in report_xml.php... Retrieved January 16, 2020, from https://hackerone.com/reports/383127
[10] Rouse, M., Bacon, M., Judith Myerson, Rob Wright, & Margaret Rouse. (n.d.). What is CVSS (Common Vulnerability Scoring System)? - Definition from WhatIs.com. Retrieved January 16, 2020, from https://searchsecurity.techtarget.com/definition/CVSS-Common-Vulnerability-Scoring-System
[11] Lim, Q. H. (2018, March 23). Real Life Examples Of Web Vulnerabilities. Retrieved January 16, 2020, from https://www.horangi.com/blog/real-life-examples-of-web-vulnerabilities/
[12] Burgess, M., & Temperton, J. (2017, October 4). The security flaws at the heart of the Panama Papers. Retrieved January 16, 2020, from https://www.wired.co.uk/article/panama-papers-mossack-fonseca-website-security-problems
[13] What is SQL Injection? Tutorial & Examples. (n.d.). Retrieved January 15, 2020, from https://portswigger.net/web-security/sql-injection.
[14] w3schools.com. (n.d.). SQL Comments. Retrieved January 20, 2020, from https://www.w3schools.com/sql/sql_comments.asp
[15] w3schools.com. (n.d.). Introduction to SQL. Retrieved January 20, 2020, from https://www.w3schools.com/sql/sql_intro.asp
[16] tgogostgogos, & BaptisteBaptiste. (2017, November 15). SQL injection: how to find urls to attack to. Retrieved January 20, 2020, from https://security.stackexchange.com/questions/173459/sql-injection-how-to-find-urls-to-attack-to
[17] Hatori, N. (2019, May 22). Example of a Error-Based SQL Injection. Retrieved January 20, 2020, from https://medium.com/@hninja049/example-of-a-error-based-sql-injection-dce72530271c
[18] Network Security. (2016, October 11). Error based SQL injection attack. Retrieved January 20, 2020, from https://hydrasky.com/network-security/error-based-sql-injection-attack/
[19] SQL injection UNION attacks. (n.d.). Retrieved January 20, 2020, from https://portswigger.net/web-security/sql-injection/union-attacks
[20] w3schools.com. (n.d.). SQL UNION Operator. Retrieved January 20, 2020, from https://www.w3schools.com/sql/sql_union.asp
[21] Leach, B. (2017, January 4). What is the difference between database and table? - Quora. Retrieved January 20, 2020, from https://www.quora.com/What-is-the-difference-between-database-and-table
[22] w3schools.com. (n.d.). SQL Server CONCAT() Function. Retrieved January 20, 2020, from https://www.w3schools.com/sql/func_sqlserver_concat.asp
[23] sqlinjection. (n.d.). SQL Injection Using UNION. Retrieved January 20, 2020, from https://www.sqlinjection.net/union/
[24] w3schools.com. (n.d.). SQL Server SUBSTRING() Function. Retrieved January 20, 2020, from https://www.w3schools.com/sql/func_sqlserver_substring.asp
[25] KLARSEN.NET. (2018, August 20). OWASP WebGoat SQL advanced lesson 5. Retrieved January 20, 2020, from https://klarsen.net/infosec/owasp-webgoat-sql-advanced-lesson/
[26] imperva. (n.d.). What is SQL Injection: SQLI Attack Example & Prevention Methods: Imperva. Retrieved January 20, 2020, from https://www.imperva.com/learn/application-security/sql-injection-sqli/
[27] sqlinjection. (n.d.). Time-Based Blind SQL Injection Attacks. Retrieved January 20, 2020, from https://www.sqlinjection.net/time-based/
[28] OWASP. (n.d.). SQL Injection Prevention Cheat Sheet. Retrieved January 20, 2020, from https://owasp.org/www-project-cheat-sheets/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html
[29] w3schools.com. (n.d.). JavaScript Switch Statement. Retrieved January 20, 2020, from https://www.w3schools.com/js/js_switch.asp
[30] OWASP. (n.d.). SQL Injection Prevention Cheat Sheet. Retrieved January 20, 2020, from https://owasp.org/www-project-cheat-sheets/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html
[31] GeeksforGeeks. (2018, March 21). Mitigation of SQL Injection Attack using Prepared Statements (Parameterized Queries). Retrieved January 20, 2020, from https://www.geeksforgeeks.org/mitigation-sql-injection-attack-using-prepared-statements-parameterized-queries/