Continuous Security - how to get involved as a tester?

Introduction

As you may have already noticed I often drift into the security domain. My interests focus mainly on continuous security (i.e. automated security tests). So far I had featured three tools on my blog: OWASP Dependency-Check, OWASP ZAP, and Find-Sec-Bugs and showed how to use Selenium to automate your XSS tests.

When I talk to my peers on various testing meetups I’m often surprised how rarely professional testers engage in security-related work. Throughout my activities, I try to debunk the myth that application security should be dealt with exclusively by full-time professionals. Of course, I’m far from saying that their work is not needed (quite contrary actually), but testers should start to get themselves involved. I predict that companies will soon start to put OWASP Top 10 knowledge as a job requirement for testing positions.

How to get involved?

As with almost everything in life we need to start somewhere. How? Perhaps with the already featured OWASP ZAP. First, run an automated scan against your application. If you don’t have any use OWASP Juice Shop.

Most likely even with the simplest possible scan, you will be able to find vulnerabilities and things you can improve to make your application more secure. Here is sample output from OWASP Juice Shop.

Today I’ll focus on hardening (improving security) with security headers. In the next post, I’ll analyze what to do as a tester when an actual vulnerability has been found.

Hardening

If you take a look at my blog response headers you may find two security headers: X-Xss-Protection and X-Content-Type-Options. Check it in browser developer tools though, scanning Blogger via OWASP ZAP is illegal.

It’s usually a good idea to add a cheap API test just to make sure headers do not disappear during development. Let’s use the newly released Rest-Assured 4.0.0 framework for that purpose.

At first, it’s good to list application endpoints we want to check. For me, it will be:

abstract class AbstractSecurityHeaderTest {

    static final List<String> CHECKED_URLS = ImmutableList.of(
            "https://www.awesome-testing.com",
            "https://www.awesome-testing.com/search/label/security",
            "https://www.awesome-testing.com/2019/06/throttling-network-in-selenium-tests.html",
            "https://www.awesome-testing.com/2017/"
    );

}

Test for X-Xss-Protection (header which enables cross-site scripting filtering):

    @Test
    public void shouldHaveXssProtectionHeader() {
        CHECKED_URLS.forEach(url -> {
            String header = given()
                    .when()
                    .get(url)
                    .then()
                    .extract()
                    .header("x-xss-protection");

            assertThat(header)
                    .isNotNull()
                    .isEqualTo("1; mode=block");
        });
    }

And X-Content-Type-Options (header which disables MIME sniffing and forces browser to use the type given in Content-Type):

    @Test
    public void shouldHaveContentTypeHeader() {
        CHECKED_URLS.forEach(url -> {
            String header = given()
                    .when()
                    .get(url)
                    .then()
                    .extract()
                    .header("x-content-type-options");

            assertThat(header)
                    .isNotNull()
                    .isEqualTo("nosniff");
        });
    }

Tests are really simple. If you have trouble understanding them please take a look at my Rest-Assured introduction.

TDD?

Let’s assume now that for some reason my blog needs to meet PCI requirements and I have to add two more headers:

a) Strict-Transport-Security/HSTS ( header which forces communication using HTTPS instead of HTTP)

b) X-Frame-Options (header which indicates whether a browser should be allowed to render a page in a frame, iframe, embed or object)

In TDD fashion, I can start the work with the acceptance test. Developer job to add such header would be much easier now.

a) HSTS

    @Test
    public void shouldHaveHstsHeader() {
        CHECKED_URLS.forEach(url -> {
            String header = given()
                    .when()
                    .get(url)
                    .then()
                    .extract()
                    .header("strict-transport-security");

            assertThat(header)
                    .isNotNull()
                    .isEqualTo("max-age=31536000; includeSubDomains");
        });
    }

b) X-Frame-Options

    @Test
    public void shouldHaveXFrameOptionsHeader() {
        CHECKED_URLS.forEach(url -> {
            String header = given()
                    .when()
                    .get(url)
                    .then()
                    .extract()
                    .header("x-frame-options");

            assertThat(header)
                    .isNotNull()
                    .isEqualTo("deny");
        });
    }

Simple, right? :)

As usual, all code can be found on my GitHub project. If you would like to support this blog please join 38 stargazers for a repository. Thank you.

Tags: ,

Categories:

Updated: