Cyber Security Play

Cyber Security ‘Play’

I keep meaning to put together a thread of “learning cyber security through play”, so here it is.

First… as with all things, we need some background understanding.

Static vs Dynamic Websites

Okay, so – first, we need a little background understanding in how websites actually work. Having had a quick read around the topic, this is probably the most accessible explanation I can readily find.

Static vs Dynamic Websites – What’s The Difference?

Have a quick read, and then pop back.

SQL

As we saw above, the server for a dynamic website processes data, and presents relevant information to the user. We have a web page, rendered using HTML. This HTML can come from a static file of HTML (simply put, a text file), or the HTML can be produced as a consequence of code, running on the server, producing HTML (a dynamic webpage).

This site expands on the previous example, and provides a little more information.

https://www.geeksforgeeks.org/dynamic-websites/

The programming that is the dynamic website, runs queries against the database. Information that is retrieved from the database is presented to the user.

Let us have a think about a worked example.

Simple ERD of a User table.

We have a database table called User. It stores all our Users. We won’t worry about the other tables for now – but if you want to understand the above Entity Relationship Diagram in more detail, it won’t hurt.

Each user has an idUser, a name, a password, and a register.

When a user logs in to the website, the website will take the username and password, via the website, using textboxes.

Using the programmed dynamic website, it runs a query against the database, to see if the name and password exist in the database. I should add, at this point, that this is a very simple, insecure example. Once we have explained why, I will link you to designs that are far more secure.

Assume for a moment, a user exists called ‘paul’ with a password of ‘test123’. When a user attempts to log in, a query like this will be executed:

SELECT * FROM User WHERE name = 'paul' AND password = 'test123';

The database will run the query, and return 1 record. The code in the dynamic website will be set up to respond:

'get the username and password that the user typed in, and save them in variables.'

$username = textboxUser
$password = textboxPassword

sqlQuery = "SELECT * FROM User WHERE name = $username AND password = $password"

if number_of_records == 0:
  print("The username or password was not found")
  
if number_of_records > 0:
  login()

The above is some pseudocode. Pseudocode isn’t real programming. It uses words and sentences that are very similar to programming, to express the underlying ideas and principles of programming, without requiring the reader to know a specific language. It may remove syntax like semi-colons, curly-brackets, and other complicating factors of a programming language to try and simplify; to make it easier for the writer (that’s me!) to make their point to the reader (that’s you!).

If the database finds a record where ‘that specific’ user and password combination are found, it will log in. If ‘that specific user and password’ are not found, it will prevent a log in.

Hopefully, so far, so good?

SQL Injection

The user is allowed to influence what query is executed on the database, as ‘whatever they type in to the website’ is stored in the variables for username and password, and then combined with the SQL code.

If they were malicious, they might type in ” or “”=” instead of paul and ” or “”=” instead of test123.

This turns the query into:

SELECT * FROM Users WHERE Name ="" or ""="" AND Pass ="" or ""=""

The query has been manipulated, and now – because of the ORs we added, will ‘always’ return records in the database.

I’ve set up a database called User to demonstrate:

SQL example of a Select All.

Here, we can see SELECT * FROM `user` returns 3 records.

If I try and log in with a real username, but the wrong password, we get:

SQL example returning 0 records.

0 records returned. Our code does not log in.

However…

If we manipulate the variables, and use ” or “”=” , we get:

SQL example using SQL injection to return records.

Using our really bad code, this would perform a log in! We were able to log in, without knowing a username or password!

WE JUST PERFORMED A HACK!

You can find out more about this, with some examples that you can try yourself, over at W3Schools – https://www.w3schools.com/sql/sql_injection.asp

Thankfully, there are some very simple steps a programmer can use to prevent this kind of SQL injection attack. Prepared statements, stored procedures, and parameterized queries prevents the user from being able to influence the query that is being executed. It sanitises the input, which is a vital concept for security.

https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html

If you would like to test SQL injection, there are websites available, SPECIFICALLY DESIGNED for educational purposes.

Remember – attempting to hack a website is ILLEGAL. These resources are designed exclusively for teaching purposes, and to help students develop an understanding of security.

With that disclaimer out of the way – a good starting point is https://redtiger.labs.overthewire.org and https://pwn.college/

If you want LOTS of training resources, have a look at https://www.wechall.net/active_sites

How To Build More Secure Websites

We mentioned above, that the example provided was very simple. It is very, very bad practice to store a password in a database in clear text. Any hacker who is able to gain access would have a list of usernames and passwords, that they could attempt to use on other websites.

We can take steps to protect our users, by hashing the password.

This website will generate a hash for any string you enter, using either the MD5 algorithm, or the SHA-1 algorithm.

https://www.md5hashgenerator.com/

A hash is a one-way algorithm. It takes a string, and returns the hashed equivalent. However, you cannot take the hashed string, and return the original password – it is a one-way process. This means that even if hackers get access to your database, and all the hashed passwords, they do NOT gain access to the passwords; only the hash of the password.

Using an MD5 generator.

In the screenshot, you can see that the string “password”, run through the MD5 algorithm, becomes 5f4dcc3b5aa765d61d8327deb882cf99

However, MD5 is deemed very insecure for security purposes. SHA-1 is also somewhat insecure, and is being replaced by SHA-2 or SHA-3. Over time, increasing computing power, and vulnerabilities in algorithms, mean that it is an ongoing game of cat and mouse, with programmers using more modern hashing algorithms to try and beat the hackers.

Here we are, using the https://www.browserling.com/tools/sha2-hash website to generate an SHA-2 hash.

SHA-2 generator, creating a hash.

Using SHA-2, we can see that “password” hashed using SHA-2 is “d63dc919e201d7bc4c825630d2cf25fdc93d4b2f0d46706d29038d01”.

There are plenty of options of hashing passwords, and some are more suitable than others. The most modern examples include the bcrypt algorithm and the Argon2 algorithm, but fall outside the scope of this article.

How does this help us? Let us have a look at that sample pseudocode I was using, earlier.

'get the username and password that the user typed in, and save them in variables.'

$username = textboxUser

$password = sha2(textboxPassword)
`I am using the sha-2 function, to get the hash of what the user typed in for a password. If I only store the sha-2 version of their password in my database - even if a hacker gets access to my database, they will NOT know what the original password was. They will only have the HASH of the password. I've just saved my users from being hacked on lots of other websites`

sqlQuery = "SELECT * FROM User WHERE name = $username AND password = $password"

if number_of_records == 0:
  print("The username or password was not found")
  
if number_of_records > 0:
  login()

This does not solve the SQL injection issue(!), but it does at least mean the passwords are protected WHEN we get exploited. =D

You would need to combine the hashing with prepared SQL statements / stored procedures / parametrised SQL, to limit the likelihood of being hacked to begin with, combined with a reduced impact if you end up hacked anyway.

More information can be found here: https://nordvpn.com/blog/what-are-salted-passwords-and-password-hashing/

What To Take Away

We have looked at an awful lot of topics today. We have introduced how dynamic websites work, and how they interact with databases, using Structured Query Language.

We looked at how a dynamic website ‘works’, which a very important step in understanding how hacking can take place. We need to understand how a website works, to understand how they can be vulnerable. And we need to understand what makes them vulnerable, to understand what we can do to protect them.

We looked at hashing of passwords, to protect the underlying data, and we briefly discussed using prepared SQL statements / stored procedures / parameterised SQL as a means of sanitising the input – although I did not want this to become a programming article.

Let me know what you think, and please feel free to send in suggestions for future topics you would like to see explored.