This project is a part of the course Cyber Security Base with F-Secure. It is a free course series by the University of Helsinki in collaboration with F-Secure Cyber Security Academy that focuses on building core knowledge and abilities related to the work of a cyber security professional.
In this assignment, the goal is to create a web application that has at least five different flaws from the OWASP top ten list, point out the flaws in the software, and provide the steps to fix them.
To create the right conditions, make sure to clear browser cookies and restart the web server before trying to reproduce the flaws. Otherwise, the prerequisites might not be correct. In the following text, the assumption is that the site is running under http://localhost:8080.
- Go to http://localhost:8080
- Login with User=ted and Password=ted
- Enter the following in the input field labeled Address:
<script>alert('XSS vulnerability!')</script>
- Press the Submit button
- The javascript in the XSS attack is executed on the confirmation page and an alert message is shown
This vulnerability is an example of Reflected Server XSS. Server XSS is caused by including untrusted data in an HTML response. The easiest and strongest defense against Server XSS is in most cases context-sensitive server side output encoding. To fix this specific problem a good solution would be to HTML-encode the address data in the file /src/main/resources/templates/done.html
by using th:text
instead of th:utext
.
- Go to http://localhost:8080
- Login with User=ted and Password=ted
- Click the link labeled "List future events" at the bottom of the page
- Notice that the URL in the browsers address field is http://localhost:8080/files/events.txt
- Change the URL in the browsers address field to http://localhost:8080/files/passwords.txt and press enter
- The secret password information is shown
Applications frequently use the actual name or key of an object (in this case the file name "passwords.txt") when generating web pages. Applications don’t always verify that the user is authorized for the target object. This results in an insecure direct object reference flaw. Each use of a direct object reference from an untrusted source must include an access control check to ensure the user is authorized for the requested object. To fix this specific problem one solution would be to check that the logged on user is an administrator before returning the file with passwords in the response. But perhaps the best solution would be to never implement a function that returns the content of arbitrary files and especially not store sensitive password information in files that is accessible by the web server.
- Go to http://localhost:8080
- Login with User=admin and Password=admin
- Notice the text "Admin only, click here to list who have signed up" that is shown at the bottom of the page when the user named "admin" is logged in
- Click the link in the text and notice that the new page URL in the browser address field is http://localhost:8080/list
- Click the browsers back button to get back to the page at URL http://localhost:8080/form
- Press the Logout button at the top of the page
- Login with User=ted and Password=ted
- Notice that the text "Admin only, click here to list who have signed up" is not shown at the bottom of the page when the user named "ted" is logged in
- Change the URL in the browsers address field to http://localhost:8080/list (which we took note of earlier) and press enter
- The page is shown and its functionality is accessible even though the logged in user is not an "admin"
Applications do not always protect application functions properly. Sometimes, function level protection is managed via configuration, and the system is misconfigured. Sometimes, developers must include the proper code checks, and they forget. The application should have a consistent and easy to analyze authorization module that is invoked from all business functions. To fix this specific problem one good solution would be to introduce an ADMIN role and add .antMatchers("/list/**").hasRole("ADMIN")
to http.authorizeRequests()
in the file /src/main/java/sec/project/config/SecurityConfiguration.java
.
- Go to http://localhost:8080
- Login with User=ted and Password=ted
- Enter the following in the input field labeled Address:
<script>document.addEventListener("DOMContentLoaded", function() {var form = document.createElement("form"); form.setAttribute('method',"post"); form.setAttribute('action',"/form"); form.setAttribute('id',"csrfForm"); var name = document.createElement("input"); name.setAttribute('type',"text"); name.setAttribute('name',"name"); name.setAttribute('value',"CSRF");var address = document.createElement("input"); address.setAttribute('type',"text"); address.setAttribute('name',"address"); address.setAttribute('value',"vulnerability"); form.appendChild(name); form.appendChild(address); document.getElementsByTagName('body')[0].appendChild(form); document.getElementById('csrfForm').submit();});</script>
- Press the Submit button
- The javascript in the XSS attack is executed on the confirmation page which triggers the CSRF
- Change the URL in the browsers address field to http://localhost:8080/list and verify that a user named "CSRF" with the address "vulnerability" has signed up
Cross-Site Request Forgery (CSRF) is an attack that forces an end user to execute unwanted actions on a web application in which they're currently authenticated. CSRF attacks specifically target state-changing requests, not theft of data, since the attacker has no way to see the response to the forged request. To fix this specific problem one good solution would be to activate the CSRF protection that Spring has built in. This can be done by removing .disable()
from http.csrf().disable()
in the file /src/main/java/sec/project/config/SecurityConfiguration.java
.
- Go to http://localhost:8080
- Login with User=admin and Password=admin
- Click the link in the text "Admin only, click here to list who have signed up" that is shown at the bottom of the page
- Enter the following in the input field:
Roger%' OR address LIKE 'free
- Press the button labeled "Filter by name starting with"
- Notice that the SQL injection has filtered the response for both names beginning with "Roger" and addresses beginning with "free"
SQL Injection flaws are introduced when software developers create dynamic database queries that include user supplied input. To fix this specific problem one good solution would be to use named parameters instead of concatenating the SQL string. This can be done by writing the query as "SELECT name, address FROM Signup WHERE name LIKE :name"
and then set the name-parameter with query.setParameter("name", name + "%")
.