CSRF — это подделка междоменных запросов, полное английское название — подделка межсайтовых запросов.
Это очень распространенный метод веб-атак, и на самом деле это хорошая защита, однако, поскольку многие разработчики часто игнорируют его, многие веб-сайты действительно имеют риски безопасности CSRF-атак.
Сегодня Brother Song расскажет вам, что такое CSRF-атака и как защититься от CSRF-атаки.
Эта статья является 18-й статьей в этой серии. Чтение предыдущих статей этой серии поможет вам лучше понять эту статью:
- Выкопайте большую яму и позвольте Spring Security сделать это!
- Song Ge поможет вам начать работу с Spring Security, не спрашивайте, как снова расшифровать пароль.
- Научите, как настроить вход в форму в Spring Security
- Spring Security разделяет внешний и внутренний интерфейсы, давайте не будем переходить по страницам! Все взаимодействия JSON
- Операции авторизации в Spring Security оказались такими простыми
- Как Spring Security хранит пользовательские данные в базе данных?
- Spring Security+Spring Data Jpa объединяют усилия, управление безопасностью становится еще проще!
- Spring Boot + Spring Security реализует функцию автоматического входа в систему
- Spring Boot автоматически входит в систему, как контролировать риски безопасности?
- В проекте микросервиса, где Spring Security лучше, чем Shiro?
- Два способа для Spring Security настроить логику аутентификации (расширенный игровой процесс)
- Как быстро просмотреть IP-адрес пользователя для входа и другую информацию в Spring Security?
- Spring Security автоматически удаляет предыдущего пользователя, вошедшего в систему, одна конфигурация выполнена!
- Spring Boot + Vue разделяет интерфейсные и серверные проекты, как выгнать вошедших в систему пользователей?
- Spring Security поставляется с собственным брандмауэром! Вы даже не представляете, насколько безопасна ваша система!
- Что такое атака с фиксацией сеанса? Как защититься от атак фиксации сеанса в Spring Boot?
- Развертывание кластера, как Spring Security обрабатывает совместное использование сеансов?
1. Принцип CSRF
Чтобы защититься от CSRF-атак, мы должны сначала выяснить, что такое CSRF-атаки.Сонг Гэ использует следующую картинку, чтобы вместе с вами разобраться в процессе CSRF-атаки:
На самом деле процесс очень простой:
- Предположим, пользователь открывает веб-сайт онлайн-банкинга China Merchants Bank и входит в систему.
- После успешного входа онлайн-банкинг вернет файл cookie на внешний интерфейс, и браузер сохранит файл cookie.
- Пользователь открыл новую вкладку в браузере, не выходя из онлайн-банкинга, а затем перешел на опасный сайт.
- На этом опасном веб-сайте есть гиперссылка, и адрес гиперссылки указывает на интернет-банк China Merchants Bank.
- Когда пользователь нажимает на эту гиперссылку, поскольку гиперссылка автоматически содержит файл 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? На самом деле нет, обратите внимание на следующие две проблемы:
- Хакерский веб-сайт вообще не знает, что находится в вашем файле cookie, и ему это не нужно знать, потому что атака CSRF заключается в том, что браузер автоматически переносит данные в файл cookie.
- Мы помещаем случайное число, сгенерированное сервером, в куки, а интерфейс должен извлечь его из самого куки.
_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:
- Сначала введите jquery и jquery.cookie, чтобы позже мы могли управлять файлами cookie.
- Определите три входа, первые два — это имя пользователя и пароль, а третий — кнопка входа.
- После нажатия кнопки входа в систему мы сначала извлекаем XSRF-TOKEN из файла cookie, который является параметром csrf, который мы хотим загрузить.
- Выполните операцию входа через 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/Судный день, ты…
Ну, я не знаю, дошли ли до этого друзья? Если у вас есть какие-либо достижения, не забудьте нажать и подбодрить Сонг Гэ ~