За последние 24 часа нас посетили 19570 программистов и 1606 роботов. Сейчас ищут 1589 программистов ...

Как защитить свои PHP скрипты от CURLE запросов с "чужих" доменов?

Тема в разделе "PHP для новичков", создана пользователем denismix, 31 авг 2021.

Метки:
  1. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.589
    Симпатии:
    1.763
    @musicman3, ТС начинает рассуждать, можно ли обойти. Твою схему тоже можно. Твой CSRF где будет генерится? На сервере. Значит храниться будет в какой-нибудь сессии, значит в куках будет идентификатор сессии. Делаешь курлом запрос №1 с сохранением куков, вытаскиваешь CSRF-токен, делаешь запрос №2, с теми же куками, и радуешься...
     
    musicman3 нравится это.
  2. musicman3

    musicman3 Активный пользователь

    С нами с:
    30 июн 2019
    Сообщения:
    144
    Симпатии:
    12
    Адрес:
    Дыра на карте
    Можно в БД хранить токены. Есть полет для творчества. Можно зашифровать токен и без ключа его не открыть не ведающим.
     
    #27 musicman3, 1 сен 2021
    Последнее редактирование: 1 сен 2021
  3. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.589
    Симпатии:
    1.763
    @musicman3 Но от куки всё равно никуда не уйдёте
     
    musicman3 нравится это.
  4. musicman3

    musicman3 Активный пользователь

    С нами с:
    30 июн 2019
    Сообщения:
    144
    Симпатии:
    12
    Адрес:
    Дыра на карте
    Почему? Вместо куки в БД хранить. По мне так лучше серверную куку с токеном зашифровать.
     
  5. musicman3

    musicman3 Активный пользователь

    С нами с:
    30 июн 2019
    Сообщения:
    144
    Симпатии:
    12
    Адрес:
    Дыра на карте
    Кстати, попутный вопрос. Как через CURL получить/забрать/стащить серверную сессионную куку $_SERVER['token'] ?

    CURLOPT_COOKIEJAR ее читает? Не баловался с этим, так как надобности не было.
     
    #30 musicman3, 1 сен 2021
    Последнее редактирование: 1 сен 2021
  6. musicman3

    musicman3 Активный пользователь

    С нами с:
    30 июн 2019
    Сообщения:
    144
    Симпатии:
    12
    Адрес:
    Дыра на карте
    Сейчас провел эксперимент, и не удалось мне стащить $_SERVER через CURLOPT_COOKIEJAR. В таком случае нет смысла беспокоиться, так как токен всегда хранится либо в $_SERVER, либо в БД.

    Стащить удается только куки из setcookie();

    А для защиты CSRF применяется серверная сессионная кука $_SERVER или БД. Иначе не будет работать защита CSRF. Т.е. даже шифровать не нужно. Обычный CSRF протект достаточно.

    Вот результаты:
    предварительно установил куку через setcookie('TestCookie', '123'). Выдает только сессию и куку. Все что было в $_SERVER не записывается. Т.е. это никак не поможет украсть токен. Если под этой сессией зайти на страницу с целью получить токен, то тут же сгенерируется новый токен. А по другому не достать токен, так как он не отдастся на запрос curl.

    Код (Text):
    1. # Netscape HTTP Cookie File
    2. # https://curl.haxx.se/docs/http-cookies.html
    3. # This file was generated by libcurl! Edit at your own risk.
    4.  
    5. localhost    FALSE    /    FALSE    0    TestCookie    123
    6. localhost    FALSE    /    FALSE    0    PHPSESSID    ebo4ini92rboi6el4v161db4vt8e66oe
    Это сохраняется в файл через флаг CURLOPT_COOKIEJAR
     
    #31 musicman3, 1 сен 2021
    Последнее редактирование: 1 сен 2021
  7. musicman3

    musicman3 Активный пользователь

    С нами с:
    30 июн 2019
    Сообщения:
    144
    Симпатии:
    12
    Адрес:
    Дыра на карте
    Сорри, прошу читать выше не $_SERVER а $_SESSION... Че то запарился. Если можно, отмодерируйте, пожалуйста.
     
    #32 musicman3, 1 сен 2021
    Последнее редактирование: 1 сен 2021
  8. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.589
    Симпатии:
    1.763
    Во, а я уж подумал, что я чего-то не знаю :) А откуда она там берётся? PHPSESSID ebo4ini92rboi6el4v161db4vt8e66oe - вот отсюда. Если эта кука прилетит на ваш сайт, php подключит эту сессию
     
  9. musicman3

    musicman3 Активный пользователь

    С нами с:
    30 июн 2019
    Сообщения:
    144
    Симпатии:
    12
    Адрес:
    Дыра на карте
    Подключит, и выдаст новый токен. Поэтому POST не пройдет. В том то и вся фишка. Процесс следующий:

    0. Сравнивается входящий POST токен и токен в сессии. Если нет токена в сесии или POST токена или они не равны, то POST не обрабатывается и по желанию пишем маты в echo хацкеру. Я предпочитаю хацкеру ничего не говорить, пусть ломает башку.
    1. Генерируется токен и сохраняется в сессию $_SESSION
    2. Размещается в input hidden в POST формах HTML.
    3. При отправке формы передается обработчику.

    Обработчик, получая POST hidden token сравнивает его с сессией в п. 0 и разрешает/запрещает POST, и генерирует опять новый токен вставляя его одновременно в новый FORM hidden.

    Таким образом при генерации нового запроса генерируется новый токен даже с той же сессией, и его нельзя перехватить зная сессию. А сам токен при этом одновременно сохраняется на оригинальной странице в hidden, для дальнейшей его сверки через входящий POST form.
     
    #34 musicman3, 1 сен 2021
    Последнее редактирование: 1 сен 2021
  10. denismix

    denismix Новичок

    С нами с:
    31 авг 2021
    Сообщения:
    14
    Симпатии:
    0
    Я правда очень внимательно ознакомился с CSRF и наглухо не могу понять, как это мне может помочь...
    У меня на странице есть код, который запрашивает этот самый "CSRF-токен", что мешает взять этот код и встроить его в страницу на другом сайте, запросить токен и спокойно валидироваться у моего .php?
    Допустим "токен" передается при загрузке страницы, тогда "пират" эмулирует браузер, загружает "в тень" мою страницу, получает заветный токен и дальше по накатанной... и никакие привязки к объему данных на странице и т.п. не сработают, т.к. я должен всё дешифровывать на стороне клиента, достаточно просто спарсить js который это делает.

    Где я ошибаюсь?

    Вот если бы мне нужно было организовать множественные постоянные обмены, и я боялся, что данные будут перехвачены "по дороге", тогда да, все эти "короткие сессии" и токены работают. А у мня то одно единственное обращение к .php - тут делов то: глянул как запрашивается "токен", получил его ровно тем же способом, потом использовал для получения результата.
    --- Добавлено ---
    Ну в крайнем случае "пират", может использовать не cURL, а мой же код js, взятый с моей же страницы...
     
  11. musicman3

    musicman3 Активный пользователь

    С нами с:
    30 июн 2019
    Сообщения:
    144
    Симпатии:
    12
    Адрес:
    Дыра на карте
    Получает токен, и передает его на сервер со своего хоста, получая новый сеанс связи, а значит и генерацию нового токена. А значит токены не совпадут и POST запросы не обработаются. Вникните в мой предыдущий пост, не знаю как уже подробнее объяснить.
     
    #36 musicman3, 1 сен 2021
    Последнее редактирование: 1 сен 2021
  12. denismix

    denismix Новичок

    С нами с:
    31 авг 2021
    Сообщения:
    14
    Симпатии:
    0
    Ну и что? У меня же на сайте одновременно "сидят" десятки разных пользователей, я не могу ограничить доступ к .php только одной текущей сессией.
    Как сервер отличит моего пользователя от "пирата"? Ну запросил "кто то там" токен - сервер его радостно выдал. А кто запросил и откуда, как я понимаю, сервер понятия не имеет. Дальше "пират" просто вставляет мой же js код-обработчик на свою страницу и радостно пользуется всеми рулёзами на тех же правах, что и другие мои пользователи.

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

    Надеюсь, что я упускаю что то важное, прошу ткнуть носом =)
    --- Добавлено ---
    Давайте для чистоты эксперимента, представим, что "пират" просто полностью скопировал мою страницу со всеми js, разметками и т.п. и разместил на своем домене. Ваша схема защиты сработает в таком случае?
     
  13. musicman3

    musicman3 Активный пользователь

    С нами с:
    30 июн 2019
    Сообщения:
    144
    Симпатии:
    12
    Адрес:
    Дыра на карте
    Ну ё-мое... Вы читаете что написано выше? Мне перепечатать? В суть вникните.
    Где генерация происходит? На сервере, для любой сессии. Перед формированием страницы стоит генерация. На самом верху до HTML. Затем идет проверка на токен. Если не прошла, то и POST не проходит.

    Напишу уже грубым примером, простейшим для понимания сути наброском:

    PHP:
    1. <?php session_start();
    2. csrfToken(); // генерируем токен
    3. csrfVerification(); // Верифицируется токен. Сравниваем входящий POST токен и токен из  $_SESSION['csrf_token'], и если FALSE то делаем exit; к примеру.
    4. $_SESSION['csrf_token'] = getCsrfToken(); // забираем ТОТ ЖЕ токен в сессию (он не генерируется теперь ,а просто отдается)
    5.  
    6. ?>
    7. <html>
    8.     <head>
    9.       <body>
    10.  
    11. Далее некая POST форма типа
    12. <input type="hidden" name="csrf_token" value="<?php echo getCsrfToken(); ?>" />
    13.  
    14. </body>
    15. </head>
    16. </html>
    Вы можете эту форму хоть всю спарсить вместе с
    PHP:
    1. <div id="csrf_token" class='hidden' data-csrf='<?php getCsrfToken(); ?>'></div>
    но, при этом при вашем НОВОМ (повторюсь, НОВОМ сеансе), вы попадете на начало этого кода и опять будет сгенерирован новый токен, даже если у вас сессия та же.Токены не совпадут и финица ля комедия.
     
    #38 musicman3, 1 сен 2021
    Последнее редактирование: 1 сен 2021
  14. musicman3

    musicman3 Активный пользователь

    С нами с:
    30 июн 2019
    Сообщения:
    144
    Симпатии:
    12
    Адрес:
    Дыра на карте
    Суть CSRF примерно такая. Вот как стянуть еще на стадии HTML сессию чтобы запихнуть ее в CURL и передать вместе со стянутым токеном?
     
    #39 musicman3, 1 сен 2021
    Последнее редактирование: 1 сен 2021
  15. musicman3

    musicman3 Активный пользователь

    С нами с:
    30 июн 2019
    Сообщения:
    144
    Симпатии:
    12
    Адрес:
    Дыра на карте
    Я вот покумекал и понимаю откуда у вас вопросы. Если спарсить и сессию и токен к примеру в браузере, и вручную заменить заголовки на CURL и передать все это на обработчик, то в этом случае можно обойти стандартную защиту CSRF так как мы подменяем запрос браузера от формы с теми же заголовками. Нужно еще подумать... Но писать скрипт под этот CURL-снифер уже придется под расширение браузера ну или еще как то. Т.е. это уже другой уровень по идее. Видимо действительно CSRF в чистом виде не подойдет, разве что осложнит действия.
     
    #40 musicman3, 1 сен 2021
    Последнее редактирование: 1 сен 2021
  16. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.589
    Симпатии:
    1.763
    @musicman3 Забавный ты человек. CSRF должен генерироваться на два запроса. Если он генерируется на один запрос, то ни один запрос не будет просто проходить. Он генерируется, когда запрошена форма гет-запросом и записывается да, в сессию. Потом сверяется, когда форма обрабатывается, и тогда, в принципе, может быть анулирован. Если после начала обработки формы ты, как в твоём коде, сгенеришь другой токен, не обработав форму, то всё, кердык, тот, что пришёл с формой с ним не совпадёт.
     
  17. Sail

    Sail Старожил

    С нами с:
    1 ноя 2016
    Сообщения:
    1.593
    Симпатии:
    362
    @musicman3, однако, токены используются для уже однажды прошедшего аутентификацию клиента.
    Вопрос же в том, чтобы эту самую аутентификацию выполнить, без регистрации клиентов.
    @denismix Соответствнно, вопрос: по каким признакам пользователей причисляете к "своим"?
     
  18. musicman3

    musicman3 Активный пользователь

    С нами с:
    30 июн 2019
    Сообщения:
    144
    Симпатии:
    12
    Адрес:
    Дыра на карте
    Генерация токена и присвоение для $_SESSION происходят между верификацией.
    PHP:
    1. csrfToken();
    2. csrfVerification(); // Сравниваем входящий POST токен и токен из  $_SESSION['csrf_token']
    3. $_SESSION['csrf_token'] = getCsrfToken();
    Т.е. верификация это - Сравниваем входящий POST токен и токен из $_SESSION['csrf_token']. Входящий POST и старую сессию. Вроде бы все логично. Т.е. верификация происходит еще со старой сессией, а потом уже третьей строчкой присваивается свежая сессия. В принципе если поменять местами первые 2 строчки то ничего не поменяется. Можно вначале верифицировать, а потом генерировать.
    --- Добавлено ---
    Да, это понятно. Защитой CSRF можно избавиться только от простых CURL запросов, которые скорее всего его так и юзают, но если найдется парсер + CURL с малым временем парсинг-отправка, то конечно же здесь уже такой вариант не прокатит.
     
    #43 musicman3, 1 сен 2021
    Последнее редактирование: 1 сен 2021
  19. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.799
    Симпатии:
    1.331
    Адрес:
    Лень
    Не поможет тебе защита с CSRF токеном. На самих убежденных, в ней защите, людей, тратить время тоже нет смысла.
    CURL - это абсолют тот же браузер пользователя. Только без мозгов.
    Сессия привязывается через - куки. Это тоже легко сейвится и используется.

    Не выдумывайте всякий пи3дешь.
    --- Добавлено ---
    Когда противоречие сочинять будешь для CURL, не забудь для браузера сочинить
    --- Добавлено ---
    куда тебя несет ? Ты вообще не в теме. Сниферы ему....
     
  20. musicman3

    musicman3 Активный пользователь

    С нами с:
    30 июн 2019
    Сообщения:
    144
    Симпатии:
    12
    Адрес:
    Дыра на карте
    Мы тут разбираем по косточкам, ищем хоть какие варианты а тут такое.... Давай тогда, решение...
     
  21. Sail

    Sail Старожил

    С нами с:
    1 ноя 2016
    Сообщения:
    1.593
    Симпатии:
    362
    @denismix, каким образом осуществляете "подключение" клиентов к сервису?
     
  22. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.799
    Симпатии:
    1.331
    Адрес:
    Лень
    У тебя варианты как у кодера с его СуперПупер защитой пароля - преобразовать пароль в хеш код, поменять местами каждый пятый символ - Win.
    Приходит другой кодер - ломает твою верификацию пароля.
    Аминь.
     
  23. musicman3

    musicman3 Активный пользователь

    С нами с:
    30 июн 2019
    Сообщения:
    144
    Симпатии:
    12
    Адрес:
    Дыра на карте
    У тебя какие варианты есть? Мой вариант хотя бы простые CURL без парсинга отрежет если у него нет никакой проверки для формы. Что ты предлагаешь? Обосрать на ровном месте тему?
     
  24. denismix

    denismix Новичок

    С нами с:
    31 авг 2021
    Сообщения:
    14
    Симпатии:
    0
    Господа, пожалуйста не ссорьтесь по пустякам! (с)
    ======================

    Проблема, что "никак" - я ищу вариант причислять пользователей к "своим", если они послали запрос именно с моего сайта (с моего домена).


    Ваш метод работает только для идентификации "последующих" запросов, от перехвата и подмены, а не от первичной проблемы.
    Я же для наглядности задал вам вопрос: "будет ли работать ваш метод, если "пират" полностью скопирует мою страницу на свой домен" - т.е. его "подложная" страница будет загружаться точно так же как и моя с самого начала, с единственной разницей, что домен будет изначально "чужим", но с "подставленным" заголовком, что он мой.
     
  25. Sail

    Sail Старожил

    С нами с:
    1 ноя 2016
    Сообщения:
    1.593
    Симпатии:
    362
    То есть, важно, чтобы человек или робот обязательно открыл страничку и увидел, например, рекламный блок?
    Этим сервисом тоже вы управляете?
    --- Добавлено ---
    Вчитался:
    Проблема оказывается, в том, чтобы с других сайтов не обращались к вашему сервису обработки фотографий...
    Так?
    --- Добавлено ---
    Вот что означала фраза "с чужих доменов" в первом сообщении :)