Security

Passwords

Passwords should never be stored as plain text. If the database was breached then the attackers have instant access to every account and could even use the stolen credentials to try and gain access to accounts on other websites. A hash function is a one-way function which always gives the same, fixed-length output for the same input. Common hashing algorithms include MD5, SHA-256 and bcrypt. Hashing is used to make the password infeasible to recover for attackers. Hashing alone is not sufficient though, as it is easy to precompute a table of common passwords and their hashes. Adding a salt to the end of the password, then hashing provides better security. When the user registers an account the password is salted and hashed and then the hash and salt are stored in the database. When the user signs in the salted hash of their given password is compared to the stored hash. If they match then the user has given the right password and can be allowed access.

SQL injection

Poorly handled user input can lead to SQL injection. This is where the user sends text specially formatted to trick the server into running SQL it didn't intent to.
Consider the following:

cursor.execute("SELECT * FROM records WHERE firstName = '" + name + "'")

If the user input their name as name' OR 1=1;-- then all the records would be returned. If the user input name'; DROP TABLE records;-- and the database allowed multiple queries then the records table would be deleted.

To prevent SQL injection it is important to parameterise SQL queries. The method for this varies by language and database but it ensures parameters are not interpreted as SQL and executed. SQLAlchemy is designed to prevent SQL injection so it is not as much of a concern when using it.

GET requests and sensitive data

GET requests should not be used to send sensitive data. GET parameters are visible in the address bar, but also visible to anyone listening to the connection, the routers, servers and logs even when using HTTPS because the URL isn't encrypted. This is not safe and POST request must always be used for sending sensitive data.

Session Hijacking

Session hijacking involves the exploitation of session cookies. Session sniffing involves listening to unencrypted traffic, intercepting cookies and then using then to impersonate a user. Session fixing involves tricking the user into logging in using a session ID known to the attacker. The attacker can then use this session ID and the server allows them access.

Cross site scripting

Cross Site Scripting (XSS) is a technique which allows an attacker to inject content into a web page. This is caused by poor input sanitisation. For example, if the user's query string was inserted directly into the web page, then HTML could be included in the query string to inject anything in to the page. If an unsuspecting user received an XSS login link and clicked it, the attacker could then inject their own form into the legitimate page and steal credentials, even though to the user the page seems legitimate. It is also possible to steal session cookies using this method, which can be used for session hijacking. To avoid XSS attacks, input should be sanitised and output should be escaped. Jinja does this by default.

Directory traversal

A user may request a file outside of the web server directory using a path like ../../../etc/shadow. This can be prevented by configuring the web server to only allow access to files within the web server directory and using the secure_filename function in Flask.