什么是CSRF攻击,以及如何防御

x33g5p2x  于2022-04-15 转载在 其他  
字(13.1k)|赞(0)|评价(0)|浏览(261)

1.CSRF攻击的概念

1.CSRF全称为Cross Site Request Forgery,跨域请求伪造。这是一种很常见的Web攻击方式,如下为一个简单的攻击流程。
1)假设用户打开了一个银行网站,并且登录了
2)登录成功后,会返回一个cookie给前端,浏览器将cookie保存下来
3)用户在没有登出银行网站的情况下,在当前浏览器又新打开多了一个选项卡,访问了一个危险的网站
4)这个网站有个危险的超链接,这个超链接指向了银行网站
5)用户点击这个超链接,由于这个超链接会自动携带上cookie,所以用户不知不觉在点击这个超链接的时候,还要一些请求是发到了银行网站那里去。

2.CSRF攻击简单案例

2.1 银行网站项目

1.pom.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <parent>
  6. <groupId>org.springframework.boot</groupId>
  7. <artifactId>spring-boot-starter-parent</artifactId>
  8. <version>2.6.6</version>
  9. <relativePath/> <!-- lookup parent from repository -->
  10. </parent>
  11. <groupId>com.yl</groupId>
  12. <artifactId>csrf-1</artifactId>
  13. <version>0.0.1-SNAPSHOT</version>
  14. <name>csrf-1</name>
  15. <description>Demo project for Spring Boot</description>
  16. <properties>
  17. <java.version>11</java.version>
  18. </properties>
  19. <dependencies>
  20. <dependency>
  21. <groupId>org.springframework.boot</groupId>
  22. <artifactId>spring-boot-starter-security</artifactId>
  23. </dependency>
  24. <dependency>
  25. <groupId>org.springframework.boot</groupId>
  26. <artifactId>spring-boot-starter-web</artifactId>
  27. </dependency>
  28. <dependency>
  29. <groupId>org.springframework.boot</groupId>
  30. <artifactId>spring-boot-starter-test</artifactId>
  31. <scope>test</scope>
  32. </dependency>
  33. <dependency>
  34. <groupId>org.springframework.security</groupId>
  35. <artifactId>spring-security-test</artifactId>
  36. <scope>test</scope>
  37. </dependency>
  38. </dependencies>
  39. <build>
  40. <plugins>
  41. <plugin>
  42. <groupId>org.springframework.boot</groupId>
  43. <artifactId>spring-boot-maven-plugin</artifactId>
  44. </plugin>
  45. </plugins>
  46. </build>
  47. </project>

2.application.properties

  1. spring.security.user.name=admin
  2. spring.security.user.password=123

3.security的配置

  1. package com.yl.csrf1.config;
  2. import org.springframework.context.annotation.Configuration;
  3. import org.springframework.security.config.annotation.web.builders.HttpSecurity;
  4. import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
  5. @Configuration
  6. public class SecurityConfig extends WebSecurityConfigurerAdapter {
  7. @Override
  8. protected void configure(HttpSecurity http) throws Exception {
  9. http.authorizeRequests()
  10. .anyRequest()
  11. .authenticated()
  12. .and()
  13. .formLogin()
  14. .permitAll()
  15. .and()
  16. .csrf().disable();
  17. }
  18. }

4.controller,假设这个接口就是真实涉及到转账的

  1. package com.yl.csrf1.controller;
  2. import org.springframework.web.bind.annotation.PostMapping;
  3. import org.springframework.web.bind.annotation.RestController;
  4. @RestController
  5. public class HelloController {
  6. @PostMapping("/transfer")
  7. public void transfer(String username,Double money) {
  8. System.out.println("username=" + username);
  9. System.out.println("money=" + money);
  10. }
  11. }

2.2 危险网站的项目

1.pom.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <parent>
  6. <groupId>org.springframework.boot</groupId>
  7. <artifactId>spring-boot-starter-parent</artifactId>
  8. <version>2.6.6</version>
  9. <relativePath/> <!-- lookup parent from repository -->
  10. </parent>
  11. <groupId>com.yl</groupId>
  12. <artifactId>csrf2</artifactId>
  13. <version>0.0.1-SNAPSHOT</version>
  14. <name>csrf2</name>
  15. <description>Demo project for Spring Boot</description>
  16. <properties>
  17. <java.version>11</java.version>
  18. </properties>
  19. <dependencies>
  20. <dependency>
  21. <groupId>org.springframework.boot</groupId>
  22. <artifactId>spring-boot-starter-web</artifactId>
  23. </dependency>
  24. <dependency>
  25. <groupId>org.springframework.boot</groupId>
  26. <artifactId>spring-boot-starter-test</artifactId>
  27. <scope>test</scope>
  28. </dependency>
  29. </dependencies>
  30. <build>
  31. <plugins>
  32. <plugin>
  33. <groupId>org.springframework.boot</groupId>
  34. <artifactId>spring-boot-maven-plugin</artifactId>
  35. </plugin>
  36. </plugins>
  37. </build>
  38. </project>

2.application.properties

  1. server.port=8081

3.static下的静态资源

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <form method="post" action="http://localhost:8080/transfer">
  9. <input type="hidden" name="username" value="张三">
  10. <input type="hidden" name="money" value="1000">
  11. <input type="submit" value="点击查看美女图片">
  12. </form>
  13. </body>
  14. </html>

2.3 测试

1.登录银行网站

2.访问危险网站,并且点击超链接

可以看到在危险网站上点击某些超链接,其可以访问到银行网站的转账接口

3.默认的CSRF防御策略

1.pom.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <parent>
  6. <groupId>org.springframework.boot</groupId>
  7. <artifactId>spring-boot-starter-parent</artifactId>
  8. <version>2.6.6</version>
  9. <relativePath/> <!-- lookup parent from repository -->
  10. </parent>
  11. <groupId>com.yl</groupId>
  12. <artifactId>csrf3</artifactId>
  13. <version>0.0.1-SNAPSHOT</version>
  14. <name>csrf3</name>
  15. <description>Demo project for Spring Boot</description>
  16. <properties>
  17. <java.version>11</java.version>
  18. </properties>
  19. <dependencies>
  20. <dependency>
  21. <groupId>org.springframework.boot</groupId>
  22. <artifactId>spring-boot-starter-security</artifactId>
  23. </dependency>
  24. <dependency>
  25. <groupId>org.springframework.boot</groupId>
  26. <artifactId>spring-boot-starter-thymeleaf</artifactId>
  27. </dependency>
  28. <dependency>
  29. <groupId>org.springframework.boot</groupId>
  30. <artifactId>spring-boot-starter-web</artifactId>
  31. </dependency>
  32. <dependency>
  33. <groupId>org.thymeleaf.extras</groupId>
  34. <artifactId>thymeleaf-extras-springsecurity5</artifactId>
  35. </dependency>
  36. <dependency>
  37. <groupId>org.springframework.boot</groupId>
  38. <artifactId>spring-boot-starter-test</artifactId>
  39. <scope>test</scope>
  40. </dependency>
  41. <dependency>
  42. <groupId>org.springframework.security</groupId>
  43. <artifactId>spring-security-test</artifactId>
  44. <scope>test</scope>
  45. </dependency>
  46. </dependencies>
  47. <build>
  48. <plugins>
  49. <plugin>
  50. <groupId>org.springframework.boot</groupId>
  51. <artifactId>spring-boot-maven-plugin</artifactId>
  52. </plugin>
  53. </plugins>
  54. </build>
  55. </project>

2.application.properties

  1. spring.security.user.name=root
  2. spring.security.user.password=123

3.controller

  1. package com.yl.csrf3.controller;
  2. import org.springframework.stereotype.Controller;
  3. import org.springframework.web.bind.annotation.GetMapping;
  4. import org.springframework.web.bind.annotation.PostMapping;
  5. import org.springframework.web.bind.annotation.ResponseBody;
  6. @Controller
  7. public class HelloController {
  8. @PostMapping("/hello")
  9. @ResponseBody
  10. public String hello() {
  11. return "hello";
  12. }
  13. @GetMapping("/01")
  14. public String hello2() {
  15. return "01";
  16. }
  17. }

4.template目录下的静态资源

  1. <!DOCTYPE html>
  2. <html lang="en" xmlns:th="http://www.thymeleaf.org">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <form method="post" action="/hello">
  9. <input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}">
  10. <input type="submit" value="提交">
  11. </form>
  12. </body>
  13. </html>

5.访问01接口,然后登录

6.然后提交,获取内容

7.然后我们观察hello请求,发现,其实在发请求的时候,不仅仅是把cookie传到后台,还把一个随机参数传到了后台,后台还要校验这个随机参数,这种方式可以解决CSRF攻击

4前后端分离的CSRF防御策略

1.pom.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <parent>
  6. <groupId>org.springframework.boot</groupId>
  7. <artifactId>spring-boot-starter-parent</artifactId>
  8. <version>2.6.6</version>
  9. <relativePath/> <!-- lookup parent from repository -->
  10. </parent>
  11. <groupId>com.yl</groupId>
  12. <artifactId>csrf3</artifactId>
  13. <version>0.0.1-SNAPSHOT</version>
  14. <name>csrf3</name>
  15. <description>Demo project for Spring Boot</description>
  16. <properties>
  17. <java.version>11</java.version>
  18. </properties>
  19. <dependencies>
  20. <dependency>
  21. <groupId>org.springframework.boot</groupId>
  22. <artifactId>spring-boot-starter-security</artifactId>
  23. </dependency>
  24. <dependency>
  25. <groupId>org.springframework.boot</groupId>
  26. <artifactId>spring-boot-starter-thymeleaf</artifactId>
  27. </dependency>
  28. <dependency>
  29. <groupId>org.springframework.boot</groupId>
  30. <artifactId>spring-boot-starter-web</artifactId>
  31. </dependency>
  32. <dependency>
  33. <groupId>org.thymeleaf.extras</groupId>
  34. <artifactId>thymeleaf-extras-springsecurity5</artifactId>
  35. </dependency>
  36. <dependency>
  37. <groupId>org.springframework.boot</groupId>
  38. <artifactId>spring-boot-starter-test</artifactId>
  39. <scope>test</scope>
  40. </dependency>
  41. <dependency>
  42. <groupId>org.springframework.security</groupId>
  43. <artifactId>spring-security-test</artifactId>
  44. <scope>test</scope>
  45. </dependency>
  46. </dependencies>
  47. <build>
  48. <plugins>
  49. <plugin>
  50. <groupId>org.springframework.boot</groupId>
  51. <artifactId>spring-boot-maven-plugin</artifactId>
  52. </plugin>
  53. </plugins>
  54. </build>
  55. </project>

2.application.properties

  1. spring.security.user.name=root
  2. spring.security.user.password=123

3.security的配置

  1. package com.yl.csrf3.config;
  2. import org.springframework.context.annotation.Configuration;
  3. import org.springframework.security.config.annotation.web.builders.HttpSecurity;
  4. import org.springframework.security.config.annotation.web.builders.WebSecurity;
  5. import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
  6. import org.springframework.security.core.Authentication;
  7. import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
  8. import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
  9. import javax.servlet.ServletException;
  10. import javax.servlet.http.HttpServletRequest;
  11. import javax.servlet.http.HttpServletResponse;
  12. import java.io.IOException;
  13. @Configuration
  14. public class SecurityConfig extends WebSecurityConfigurerAdapter {
  15. @Override
  16. public void configure(WebSecurity web) throws Exception {
  17. web.ignoring().antMatchers("/js/**");
  18. }
  19. @Override
  20. protected void configure(HttpSecurity http) throws Exception {
  21. http.authorizeRequests()
  22. .anyRequest()
  23. .authenticated()
  24. .and()
  25. .formLogin()
  26. .loginPage("/01.html")
  27. .loginProcessingUrl("/login")
  28. .successHandler(new AuthenticationSuccessHandler() {
  29. @Override
  30. public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
  31. response.getWriter().write("login success");
  32. }
  33. })
  34. .permitAll()
  35. .and()
  36. .csrf()
  37. .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
  38. }
  39. }

4.static下的静态资源,01.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <script src="js/jquery-1.8.3.min.js"></script>
  7. <script src="js/jquery.cookie.js"></script>
  8. </head>
  9. <body>
  10. <div>
  11. <input type="text" id="username"/>
  12. <input type="text" id="password"/>
  13. <input type="submit" value="登录" id="loginBtn">
  14. </div>
  15. <script>
  16. $('#loginBtn').click(function () {
  17. $.post('/login',{username:$('#username').val(),password:$('#password').val(),_csrf:$.cookie('XSRF-TOKEN')},function (data) {
  18. alert(data)
  19. })
  20. })
  21. </script>
  22. </body>
  23. </html>

5.还要在satic目录下加入jquery.js和jquery-cookie.js

6.访问登录页面,登录root账号

7.再去看登录接口,发现其实它也传了一个随机参数

相关文章