angle-up arrow-clockwise arrow-counterclockwise arrow-down-up arrow-left at calendar card-list chat check envelope folder house info-circle pencil people person person-plus phone plus question-circle search tag trash x

Flask site penetration tests: security headers and the session cookie

27 December 2019 Updated 27 December 2019 by Peter

Penetration testing is an easy way to check if your site is vulnerable to malicious attacks.

post main image
https://unsplash.com/@cathrynlavery

You created a Flask web application, it is running fine and using https. But is it secure enough? Did you do everything to protect your visitors, did you do everything to prevent malicious attacks?

A good way to proceed on this is to pentest your site. Penetration testing tools, or pen testing tools, can identifying security weaknesses. They identify vulnerabilities in the web application that can cause a security breach.

Wikipedia: The National Cyber Security Center, describes penetration testing as the following: 'A method for gaining assurance in the security of an IT system by attempting to breach some or all of that system's security, using the same tools and techniques as an adversary might.'

Most pentest tools must be installed and of course not on your local machine but somewhere on the internet so you can test your production site without going through firewalls, NAT. Someday I will look into these tools more in detail but for now I just wanted to have some indication of possible vulnerabilities.

I used an online test from Pentest-Tools.com, see link below, you get two free tests. Select the Website Vulnerability Scanner, enter the url of your site and sit back and wait for the results. Of course this is just a very very very basic test but at least it showed me that my site was missing security headers and that the session cookie was not secure. I also used Dareboost, see link below, their Website Speed Test and Website Analysis test gave me a nice Quality and Performance report.

Adding missing security headers

It is very easy to add the missing security headers to your Flask site. First I have a function adding the extra headers, I use the flag include_security_headers for sites actually on the internet.

from werkzeug.http import http_date

import datetime


def prepare_response_extra_headers(include_security_headers):

    response_extra_headers = {
        # always
        'Cache-Control': 'no-cache, no-store, must-revalidate',
        'Pragma': 'no-cache',
        'Expires': '0',
        'Last-Modified': http_date(datetime.datetime.now()),
    }
    if include_security_headers:
        response_security_headers = {
            # X-Frame-Options: page can only be shown in an iframe of the same site
            'X-Frame-Options': 'SAMEORIGIN',
            # ensure all app communication is sent over HTTPS
            'Strict-Transport-Security': 'max-age=63072000; includeSubdomains',
            # instructs the browser not to override the response content type
            'X-Content-Type-Options': 'nosniff',
            # enable browser cross-site scripting (XSS) filter
            'X-XSS-Protection': '1; mode=block',
        }
        response_extra_headers.update(response_security_headers)

    return response_extra_headers

Then, in create_app() I add the extra headers to the response in after_request:

    ...
    include_security_headers = config_name in ['staging', 'production']
    ...
    # prepare extra response headers, see after_request
    response_extra_headers = prepare_response_extra_headers(include_security_headers)
    ...
    @app.after_request
    def after_request(response):
        # after_request is not called for 500 error

        response.headers.extend(response_extra_headers)
        return response

Note that we are using extend instead of update, see the Werkzeug datastructures information.

Making the session cookie secure

About the session cookie, my site is using https, http requests are redirected to https, so what is the problem? The problem is that the cookie does not need to come from your browser on the first (!) request. You can set the HTTP Strict Transport Security (HSTS) header and enforce https, but this does not solve the problem because not all browsers support this header.

The only way you can secure your session cookie is by adding the cookie secure attribute. I am still not sure if this solves everything but it is no effort to implement. In Flask we just do:

    SESSION_COOKIE_SECURE = True

If you use Flask-Login and the 'remember me' functionality then also add:

    REMEMBER_COOKIE_SECURE = True
    REMEMBER_COOKIE_HTTPONLY = True

Another (unsolvable) security problem: passwords in memory

There is still another security problem when you run a site on a VPS (Virtual Private Server). Passwords are sent over https but are decoded at the server. Then, using good practices, they are encrypted and stored in the database.

Even if the server has been patched to eliminate vulnerabilities like Zombieload, a person having access to the server can monitor the memory of the server and see the unencrypted passwords. You can encrypt the password on the client using javascript but then the attacker still can use this encrypted value to log in. The minimum you can do is get a reliable VPS provider.

Summary

Without penetration testing you are just hoping for the best. Penetration testing is a very good way to check the vulnerabilities of your site. It is not very difficult but takes some / a lot of time. Remember that running a site on a VPS is never fully secure.

Links / credits

40 Best Penetration Testing (Pen Testing) Tools in 2020
https://www.guru99.com/top-5-penetration-testing-tools.html

Cookie Security for Flask Applications
https://blog.miguelgrinberg.com/post/cookie-security-for-flask-applications

Dareboost
https://www.dareboost.com/en

Data Structures
https://werkzeug.palletsprojects.com/en/0.15.x/datastructures/

HTTP Security Headers Analysis of Top One Million Websites
https://ccdcoe.org/uploads/2018/10/Art-18-HTTP-Security-Headers-Analysis-of-Top-One-Million-Websites.pdf

Mozilla Observatory
https://observatory.mozilla.org/

Penetration test
https://en.wikipedia.org/wiki/Penetration_test

Pentest-Tools.com
https://pentest-tools.com

Secure your Cookies (Secure and HttpOnly flags)
https://blog.dareboost.com/en/2019/03/secure-cookies-secure-httponly-flags/

Securing Cookies with HttpOnly and secure Flags
https://resources.infosecinstitute.com/securing-cookies-httponly-secure-flags/

Security Headers
https://securityheaders.com/

ZombieLoad attack lets hackers steal data from Intel chips
https://www.theverge.com/2019/5/14/18623708/zombieload-attack-intel-processors-speculative-execution

Leave a comment

Comment anonymously or log in to comment.

Comments

Leave a reply

Reply anonymously or log in to reply.