Song Ge учит вас, как защищаться от CSRF-атак в SpringBoot! так легко!

Spring Boot
Song Ge учит вас, как защищаться от CSRF-атак в SpringBoot! так легко!

CSRF — это подделка междоменных запросов, полное английское название — подделка межсайтовых запросов.

Это очень распространенный метод веб-атак, и на самом деле это хорошая защита, однако, поскольку многие разработчики часто игнорируют его, многие веб-сайты действительно имеют риски безопасности CSRF-атак.

Сегодня Brother Song расскажет вам, что такое CSRF-атака и как защититься от CSRF-атаки.

Эта статья является 18-й статьей в этой серии. Чтение предыдущих статей этой серии поможет вам лучше понять эту статью:

  1. Выкопайте большую яму и позвольте Spring Security сделать это!
  2. Song Ge поможет вам начать работу с Spring Security, не спрашивайте, как снова расшифровать пароль.
  3. Научите, как настроить вход в форму в Spring Security
  4. Spring Security разделяет внешний и внутренний интерфейсы, давайте не будем переходить по страницам! Все взаимодействия JSON
  5. Операции авторизации в Spring Security оказались такими простыми
  6. Как Spring Security хранит пользовательские данные в базе данных?
  7. Spring Security+Spring Data Jpa объединяют усилия, управление безопасностью становится еще проще!
  8. Spring Boot + Spring Security реализует функцию автоматического входа в систему
  9. Spring Boot автоматически входит в систему, как контролировать риски безопасности?
  10. В проекте микросервиса, где Spring Security лучше, чем Shiro?
  11. Два способа для Spring Security настроить логику аутентификации (расширенный игровой процесс)
  12. Как быстро просмотреть IP-адрес пользователя для входа и другую информацию в Spring Security?
  13. Spring Security автоматически удаляет предыдущего пользователя, вошедшего в систему, одна конфигурация выполнена!
  14. Spring Boot + Vue разделяет интерфейсные и серверные проекты, как выгнать вошедших в систему пользователей?
  15. Spring Security поставляется с собственным брандмауэром! Вы даже не представляете, насколько безопасна ваша система!
  16. Что такое атака с фиксацией сеанса? Как защититься от атак фиксации сеанса в Spring Boot?
  17. Развертывание кластера, как Spring Security обрабатывает совместное использование сеансов?

1. Принцип CSRF

Чтобы защититься от CSRF-атак, мы должны сначала выяснить, что такое CSRF-атаки.Сонг Гэ использует следующую картинку, чтобы вместе с вами разобраться в процессе CSRF-атаки:

На самом деле процесс очень простой:

  1. Предположим, пользователь открывает веб-сайт онлайн-банкинга China Merchants Bank и входит в систему.
  2. После успешного входа онлайн-банкинг вернет файл cookie на внешний интерфейс, и браузер сохранит файл cookie.
  3. Пользователь открыл новую вкладку в браузере, не выходя из онлайн-банкинга, а затем перешел на опасный сайт.
  4. На этом опасном веб-сайте есть гиперссылка, и адрес гиперссылки указывает на интернет-банк China Merchants Bank.
  5. Когда пользователь нажимает на эту гиперссылку, поскольку гиперссылка автоматически содержит файл cookie, сохраненный в браузере, пользователь неосознанно получает доступ к онлайн-банкингу, что может нанести ему убытки.

Процесс CSRF примерно таков: Далее Сонг Гэ использует простой пример, чтобы показать своим друзьям, что такое CSRF.

2. Практика CSRF

Затем я создаю проект Spring Boot с именем csrf-1, который эквивалентен веб-сайту онлайн-банкинга, о котором мы упоминали выше.При создании проекта я ввожу зависимости Web и Spring Security следующим образом:

После успешного создания для удобства мы напрямую настраиваем имя пользователя/пароль Spring Security в файле application.properties:

spring.security.user.name=javaboy
spring.security.user.password=123

Затем мы предоставляем два тестовых интерфейса:

@RestController
public class HelloController {
    @PostMapping("/transfer")
    public void transferMoney(String name, Integer money) {
        System.out.println("name = " + name);
        System.out.println("money = " + money);
    }
    @GetMapping("/hello")
    public String hello() {
        return "hello";
    }
}

Предположение/transferЭто интерфейс передачи (это предположение, в основном для демонстрации атаки CSRF, реальный интерфейс передачи сложнее этого).

Наконец, нам нужно настроить Spring Security, потому что Spring Security по умолчанию может автоматически защищаться от CSRF-атак, поэтому нам нужно отключить это:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().anyRequest().authenticated()
                .and()
                .formLogin()
                .and()
                .csrf()
                .disable();
    }
}

После завершения настройки запускаем проект csrf-1.

Далее мы создадим проект csrf-2, который эквивалентен опасному веб-сайту.Для удобства нам нужно только ввести веб-зависимости при его создании здесь.

После успешного создания проекта сначала измените порт проекта:

server.port=8081

Затем мы создаем hello.html в каталоге resources/static со следующим содержимым:

<body>
<form action="http://localhost:8080/transfer" method="post">
    <input type="hidden" value="javaboy" name="name">
    <input type="hidden" value="10000" name="money">
    <input type="submit" value="点击查看美女图片">
</form>
</body>

Здесь есть гиперссылка, текст гиперссылкиНажмите, чтобы посмотреть красивые картинки, когда вы нажмете на гиперссылку, она автоматически запроситhttp://localhost:8080/transferинтерфейс, а скрытое поле также содержит два параметра.

После завершения настройки вы можете запустить проект csrf-2.

Далее пользователь сначала обращается к интерфейсу в проекте csrf-1.При доступе пользователю необходимо войти в систему, и пользователь выполняет операцию входа в систему.После завершения доступа пользователь не выполняет операцию выхода из системы, а затем пользователь обращается к странице в csrf-2.Когда я увидел гиперссылку, мне стало любопытно, как выглядит эта красота.Как только я нажал, деньги были переведены.

3. Защита от CSRF

Сначала поговорим об обороне.

Одна из основных идей защиты от CSRF — добавить случайное число во внешний запрос.

Потому что при CSRF-атаке сайт хакера фактически не знает, что такое файл cookie пользователя, и просит пользователя отправить запрос на сайт онлайн-банкинга, потому что этот процесс автоматически перенесет информацию в файл cookie.

Итак, наша идея защиты такова: когда пользователь получает доступ к онлайн-банкингу, в дополнение к информации в файле cookie, ему также необходимо иметь случайное число.Если пользователь не будет использовать это случайное число, веб-сайт онлайн-банкинга отклонит запрос. . Когда хакерский веб-сайт побуждает пользователей щелкнуть гиперссылку, он автоматически переносит информацию в файл cookie, но не переносит автоматически случайное число, таким образом успешно избегая атак CSRF.

В Spring Security для этого есть хорошая поддержка, давайте посмотрим.

3.1 Схема по умолчанию

Spring Security фактически обеспечивает защиту csrf по умолчанию, но разработчикам нужно делать больше.

Во-первых, давайте создадим новый проект Spring Boot с Spring Security, Thymeleaf и веб-зависимостями.

После успешного создания проекта мы все еще настраиваем имя пользователя/пароль в application.properties:

spring.security.user.name=javaboy
spring.security.user.password=123

Далее мы предоставляем тестовый интерфейс:

@Controller
public class HelloController {
    @PostMapping("/hello")
    @ResponseBody
    public String hello() {
        return "hello";
    }
}

Обратите внимание, что этот тестовый интерфейс представляет собой запрос POST, поскольку по умолчанию GET, HEAD, TRACE и OPTIONS не требуют проверки CSRF-атак.

Затем мы создаем новый шаблон тимелеафа в каталоге resources/templates следующим образом:

<body>
<form action="/hello" method="post">
    <input type="hidden" th:value="${_csrf.token}" th:name="${_csrf.parameterName}">
    <input type="submit" value="hello">
</form>
</body>

Обратите внимание, что при отправке POST-запроса также переносится дополнительное скрытое поле.Ключ скрытого поля${_csrf.parameterName}, значение${_csrf.token}.

Эти два значения будут автоматически вынесены сервером, и нам нужно только отобразить их на фронтенде.

Затем добавьте контроллер на интерфейсную страницу hello.html следующим образом:

@GetMapping("/hello")
public String hello2() {
    return "hello";
}

После завершения добавления запустите проект, и мы посетим страницу приветствия. При посещении нам нужно сначала войти в систему. После успешного входа в систему мы видим, что в запросе на вход есть дополнительный параметр, как показано ниже:

Как видите, их больше_csrfпараметр.

Здесь мы используем страницу входа Spring Security по умолчанию.Если вы используете пользовательскую страницу входа, вы можете обратиться к написанию hello.html выше и передать его через скрытое поле._csrfпараметр.

После посещения страницы приветствия нажмите кнопку, чтобы получить доступ к интерфейсу приветствия.

Друзья могут сами попробовать на странице hello.html удалить_csrfпараметры, чтобы увидеть эффект доступа к интерфейсу приветствия.

Это схема по умолчанию в Spring Security, которая передает соответствующие данные во внешний интерфейс через модель.

Если ваш проект представляет собой фронтенд и бэкенд, это решение подойдет, но если ваш проект представляет собой проект разделения фронтенда и бэкенда, этого решения явно недостаточно.

3.2 Схема разделения фронтенда и бэкенда

Если это проект разделения внешнего и внутреннего интерфейса, Spring Security также предлагает решение.

Не в этот раз_csrfПоместите его в модель и вернитесь к внешнему интерфейсу, но поместите его в файл cookie, чтобы вернуться к внешнему интерфейсу.Конфигурация выглядит следующим образом:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().anyRequest().authenticated()
                .and()
                .formLogin()
                .and()
                .csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
    }
}

Некоторые друзья могут сказать, что хакерские веб-сайты снова не украли файл cookie? На самом деле нет, обратите внимание на следующие две проблемы:

  1. Хакерский веб-сайт вообще не знает, что находится в вашем файле cookie, и ему это не нужно знать, потому что атака CSRF заключается в том, что браузер автоматически переносит данные в файл cookie.
  2. Мы помещаем случайное число, сгенерированное сервером, в куки, а интерфейс должен извлечь его из самого куки._csrfПараметры, а потом склеить в параметры и передать на бэкенд, бесполезно просто передавать данные в куке на сервер.

Поняв два вышеуказанных пункта, вы обнаружите,_csrfПоместить его в куку не проблема, но учтите, что при настройке мы получили экземпляр CookieCsrfTokenRepository через метод withHttpOnlyFalse, который установит атрибут HttpOnly в куке в значение false, то есть разрешит работу фронтенда куки через js (иначе вы никак не сможете получить_csrf).

После завершения настройки перезапускаем проект, в это время обнаруживаем, что в возвращенной куке есть еще одна кука:

Далее давайте посмотрим, как работает внешний интерфейс, настроив страницу входа.

Сначала мы создаем новую html-страницу с именем login.html в каталоге resources/static:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/jquery.min.js"></script>
    <script src="js/jquery.cookie.js"></script>
</head>
<body>
<div>
    <input type="text" id="username">
    <input type="password" id="password">
    <input type="button" value="登录" id="loginBtn">
</div>
<script>
    $("#loginBtn").click(function () {
        let _csrf = $.cookie('XSRF-TOKEN');
        $.post('/login.html',{username:$("#username").val(),password:$("#password").val(),_csrf:_csrf},function (data) {
            alert(data);
        })
    })
</script>
</body>
</html>

Позвольте мне объяснить вам этот html:

  1. Сначала введите jquery и jquery.cookie, чтобы позже мы могли управлять файлами cookie.
  2. Определите три входа, первые два — это имя пользователя и пароль, а третий — кнопка входа.
  3. После нажатия кнопки входа в систему мы сначала извлекаем XSRF-TOKEN из файла cookie, который является параметром csrf, который мы хотим загрузить.
  4. Выполните операцию входа через POST-запрос, будьте осторожны, чтобы_csrfпараметр.

Мы также немного модифицировали серверную часть следующим образом:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/js/**");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/login.html")
                .successHandler((req,resp,authentication)->{
                    resp.getWriter().write("success");
                })
                .permitAll()
                .and()
                .csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
    }
}

С одной стороны, здесь выложен js-файл.

С другой стороны, настройте страницу входа и обратный вызов для успешного входа.В простой период я ​​могу просто указать строку для обратного вызова успешного входа. Если вы заинтересованы, вы можете проверитьэта серияВ предыдущей статье есть подробное объяснение обратного вызова после успешного входа в систему.

Хорошо, после того, как все сделано, мы заходим на страницу login.html и вводим имя пользователя и пароль для входа в систему. Результаты следующие:

Как видите, наш_csrfКонфигурация уже действует.

Друзья, можете попробовать убрать его из параметров входа самостоятельно_csrf, а потом посмотрите на эффект.

4. Резюме

Что ж, сегодня я в основном представил атаку csrf и то, как ее защитить с моими друзьями. Как вы можете видеть, атака csrf в основном опирается на механизм, который браузер отправляет файлы cookie по умолчанию, поэтому, если ваш внешний интерфейс представляет собой приложение, такое как приложение, небольшую программу и не использует приложение браузера, вы можете на самом деле игнорировать эту проблему.Если вы, если интерфейс сервера включает в себя приложение браузера, этот вопрос необходимо серьезно рассмотреть.

Хорошо, это все для этой статьи. Я загрузил соответствующие кейсы этой статьи на GitHub, и вы можете скачать их самостоятельно:GitHub.com/Len VE/Судный день, ты…

Ну, я не знаю, дошли ли до этого друзья? Если у вас есть какие-либо достижения, не забудьте нажать и подбодрить Сонг Гэ ~