Default Schutz durch Spring Security

Dies ist das vierte Kapitel der Tutorial-Beitragsreihe zu Spring Security. Dieser Beitrag veranschaulicht einige Sicherheitsmechanismen von Spring Security, die per Default aktiviert sind, und zeigt anhand eines Beispiels, wann es Sinn macht, diese zu deaktivieren oder anzupassen. Als Basis hierfür dient das Projekt aus dem Beitrag JPA und Spring Security. Den Source Code zu diesem Tutorial findet ihr auf dem Micromata Github Bereich.

Einen Überblick über das gesamte Tutorial, bereits veröffentlichte Kapitel sowie den Ausblick auf kommende Kapitel ist hier zu finden. Falls ihr Fragen zum Tutorial oder Source Code habt, meldet euch einfach über das LABS Kontaktformular oder wendet euch direkt über den Micromata Github Bereich an mich, Jürgen Fast (Micromata).

CSRF

Schauen wir uns beispielsweise das HTML unserer Login Form an:

  
  
  

<form name="f" method="post" action="/login">
    <fieldset>
        <legend>Please Login</legend>
            <div class="form-group">
                <label for="username">Username</label>
                <input type="text" id="username" name="username" />
            </div>
            <div class="form-group">
                <label for="password">Password</label>
                <input type="password" id="password" name="password" />
            </div>
            <button type="submit" class="btn btn-primary">Log in</button>
    </fieldset>
    <input type="hidden" name="_csrf" value="b1f1cfe2-56b4-407b-8b53-5764701c2199" />
</form>

Hier sieht man bereits eines dieser per Default aktiven Sicherheitsmechanismen. Bei dem Hidden Field mit dem Namen _csrf handelt es sich um einen CSRF-Token zum Schutz vor Cross-Site-Request-Forgery- Angriffen (CSRF).

Security Headers

Neben dem CSRF-Token bietet Spring Security diverse Security Header, die in die Response eingefügt werden und in der WebSecurityConfig durch den Aufruf von http.headers().defaultsDisabled() deaktiviert werden können. Nachfolgend ist diese Methode zu sehen:

public HeadersConfigurer<H> defaultsDisabled() {
    contentTypeOptions.disable();
    xssProtection.disable();
    cacheControl.disable();
    hsts.disable();
    frameOptions.disable();
    return this;
}

Die einzelnen Felder haben dabei folgenden Inhalt:

Feld Header Wert
contentTypeOptions X-Content-Type-Options nosniff
xssProtection X-XSS-Protection 1; mode=block
cacheControl Cache-Control no-cache, no-store, max-age=0, must-revalidate
cacheControl Pragma no-cache
cacheControl Expires 0
hsts Strict-Transport-Security max-age=31536000 ; includeSubDomains
frameOptions X-Frame-Options DENY

Der HSTS-Eintrag ist nur dann im Header zu finden, wenn die Applikation unter HTTPS aufgerufen wird. Wie dies mit einer Spring Boot Applikation gemacht wird, wird im noch ausstehenden Beitrag HTTPS mit Spring Boot erklärt.

Aktivierung der H2 Console

Um die in Spring Boot integrierte H2 Console aufrufen zu können, genügt es diese in der Konfigurationsdatei der Applikation einzutragen. Die Konfigurationsdatei ist dabei unter /resources/application.properties oder /resources/application.yml zu finden. Welche Dateiendung gewählt wird, ist Geschmacksache und beeinflusst die spätere Notation der Konfiguration.

application.properties

spring.datasource.url=jdbc:h2:mem:mydb
spring.h2.console.enabled=true
spring.h2.console.path=/console

application.yml

spring:
    datasource.url: jdbc:h2:mem:mydb
    h2.console:
        enabled: true
        path: /console

Nach einem Aufruf von /console sollte nun die H2 Console erscheinen:

CSRF Ausnahmen

Bei einem Klick auf Connect erscheint jedoch die folgende Fehlerseite:

Damit wir uns in die H2 Console einloggen können, müssen wir den CSRF Sicherheitsmechanismus für /console deaktivieren.

Dazu wird die WebSecurityConfig angepasst:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests().antMatchers("/noSecurity").permitAll()
        .anyRequest().authenticated()
        .and().formLogin().loginPage("/login").permitAll()
        .and().logout().permitAll();

    http.csrf().ignoringAntMatchers("/console/**");
}

Durch http.csrf().ignoringAntMatchers("/console/**") erreichen wir genau dieses Verhalten. Alles unter /console/* wird nun nicht mehr auf ein CSRF-Token überprüft.

Frame Options Anpassung

Klicken wir nun auf Connect in der H2 Console, dann sehen wir nichts. Die Console des Chrome zeigt jedoch folgendes:

Diesen Fehler erhalten wir, da die H2 Console in einem Frame läuft, das durch die Security Header per Default verboten wird. Aus diesem Grund müssen die Header angepasst und die X-Frame-Options von Deny auf SAMEORIGIN gesetzt werden.

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests().antMatchers("/noSecurity").permitAll()
        .anyRequest().authenticated()
        .and().formLogin().loginPage("/login").permitAll()
        .and().logout().permitAll();

    http.csrf().ignoringAntMatchers("/console/**")
        .and().headers().frameOptions().sameOrigin();
}

Nun können wir uns erfolgreich in die H2 Console einloggen.

Autor

Jürgen Fast arbeitet seit 2014 bei der Micromata GmbH als Softwareentwickler in verschiedenen Projekten der Logistik- und Automobilbranche. Sein Schwerpunkt liegt in der Entwicklung von javabasierten Webapplikationen.