CSRF-Schutz mit Spring MVC und Thymeleaf

1. Einleitung

Thymeleaf ist eine Java-Template-Engine zum Verarbeiten und Erstellen von HTML, XML, JavaScript, CSS und Klartext. Ein Intro zu Thymeleaf und Spring finden Sie in diesem Artikel.

In diesem Artikel wird erläutert, wie CSRF-Angriffe (Cross-Site Request Forgery) in Spring MVC mit der Thymeleaf-Anwendung verhindert werden können. Um genauer zu sein, werden wir den CSRF-Angriff für die HTTP-POST-Methode testen.

CSRF ist ein Angriff, der einen Endbenutzer dazu zwingt, unerwünschte Aktionen in einer Webanwendung auszuführen, in der derzeit authentifiziert ist.

2. Maven-Abhängigkeiten

Lassen Sie uns zunächst die Konfigurationen sehen, die für die Integration von Thymeleaf in Spring erforderlich sind. Die Thymeleaf-Spring- Bibliothek wird in unseren Abhängigkeiten benötigt:

 org.thymeleaf thymeleaf 3.0.11.RELEASE   org.thymeleaf thymeleaf-spring5 3.0.11.RELEASE 

Beachten Sie, dass für ein Spring 4-Projekt die Bibliothek thymeleaf-spring4 anstelle von thymeleaf-spring5 verwendet werden muss . Die neueste Version der Abhängigkeiten finden Sie hier.

Um Spring Security verwenden zu können, müssen außerdem die folgenden Abhängigkeiten hinzugefügt werden:

 org.springframework.security spring-security-web 5.2.3.RELEASE   org.springframework.security spring-security-config 5.2.3.RELEASE  

Die neuesten Versionen von zwei Spring Security-bezogenen Bibliotheken sind hier und hier verfügbar.

3. Java-Konfiguration

Zusätzlich zur hier behandelten Thymeleaf-Konfiguration müssen wir die Konfiguration für Spring Security hinzufügen. Dazu müssen wir die Klasse erstellen:

@Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true) public class WebMVCSecurity extends WebSecurityConfigurerAdapter { @Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .withUser("user1").password("{noop}user1Pass") .authorities("ROLE_USER"); } @Override public void configure(WebSecurity web) throws Exception { web.ignoring().antMatchers("/resources/**"); } @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .anyRequest() .authenticated() .and() .httpBasic(); } }

Weitere Einzelheiten und eine Beschreibung der Sicherheitskonfiguration finden Sie in der Serie Sicherheit mit Feder.

Der CSRF-Schutz ist standardmäßig in der Java-Konfiguration aktiviert. Um diese nützliche Funktion zu deaktivieren, müssen Sie dies in der configure (…) -Methode hinzufügen :

.csrf().disable()

In der XML-Konfiguration müssen wir den CSRF-Schutz manuell angeben, sonst funktioniert er nicht:

Bitte beachten Sie auch, dass wir, wenn wir eine Anmeldeseite mit Anmeldeformular verwenden, das CSRF-Token immer als versteckten Parameter manuell in den Code in das Anmeldeformular aufnehmen müssen:

Für die verbleibenden Formulare wird das CSRF-Token automatisch zu Formularen mit versteckter Eingabe hinzugefügt:

4. Ansichten Konfiguration

Fahren wir mit dem Hauptteil der HTML-Dateien mit Formularaktionen und der Erstellung von Testprozeduren fort. In der ersten Ansicht versuchen wir, einen neuen Schüler zur Liste hinzuzufügen:

   Add Student   
    

In dieser Ansicht fügen wir der Liste einen Schüler hinzu, indem wir ID , Name , Geschlecht und Prozentsatz angeben (optional, wie in der Formularvalidierung angegeben). Bevor wir dieses Formular ausführen können, müssen wir Benutzer und Passwort angeben , um uns in einer Webanwendung zu authentifizieren.

4.1. Testen von Browser-CSRF-Angriffen

Nun fahren wir mit der zweiten HTML-Ansicht fort. Der Zweck ist es, zu versuchen, CSRF-Angriffe durchzuführen:

Wir wissen, dass die Aktions-URL // localhost: 8080 / spring-thymeleaf / saveStudent lautet . Der Hacker möchte auf diese Seite zugreifen, um einen Angriff auszuführen.

Öffnen Sie zum Testen die HTML-Datei in einem anderen Browser, ohne sich bei der Anwendung anzumelden. Wenn Sie versuchen, das Formular einzureichen, erhalten wir folgende Seite:

Unsere Anfrage wurde abgelehnt, weil wir eine Anfrage ohne CSRF-Token gesendet haben.

Bitte beachten Sie, dass die HTTP-Sitzung zum Speichern des CSRF-Tokens verwendet wird. Wenn die Anforderung gesendet wird, vergleicht Spring das generierte Token mit dem in der Sitzung gespeicherten Token, um zu bestätigen, dass der Benutzer nicht gehackt wird.

4.2. JUnit CSRF Attack Testing

Wenn Sie CSRF-Angriffe nicht mit einem Browser testen möchten, können Sie dies auch über einen schnellen Integrationstest tun. Beginnen wir mit der Spring-Konfiguration für diesen Test:

@RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration @ContextConfiguration(classes = { WebApp.class, WebMVCConfig.class, WebMVCSecurity.class, InitSecurity.class }) public class CsrfEnabledIntegrationTest { // configuration }

Und fahren Sie mit den eigentlichen Tests fort:

@Test public void addStudentWithoutCSRF() throws Exception { mockMvc.perform(post("/saveStudent").contentType(MediaType.APPLICATION_JSON) .param("id", "1234567").param("name", "Joe").param("gender", "M") .with(testUser())).andExpect(status().isForbidden()); } @Test public void addStudentWithCSRF() throws Exception { mockMvc.perform(post("/saveStudent").contentType(MediaType.APPLICATION_JSON) .param("id", "1234567").param("name", "Joe").param("gender", "M") .with(testUser()).with(csrf())).andExpect(status().isOk()); }

Der erste Test führt aufgrund des fehlenden CSRF-Tokens zu einem verbotenen Status, während der zweite ordnungsgemäß ausgeführt wird.

5. Schlussfolgerung

In diesem Artikel haben wir erläutert, wie CSRF-Angriffe mithilfe des Spring Security- und Thymeleaf-Frameworks verhindert werden können.

Die vollständige Implementierung dieses Tutorials finden Sie im GitHub-Projekt - dies ist ein Eclipse-basiertes Projekt, daher sollte es einfach zu importieren und auszuführen sein.