@musicman3, ТС начинает рассуждать, можно ли обойти. Твою схему тоже можно. Твой CSRF где будет генерится? На сервере. Значит храниться будет в какой-нибудь сессии, значит в куках будет идентификатор сессии. Делаешь курлом запрос №1 с сохранением куков, вытаскиваешь CSRF-токен, делаешь запрос №2, с теми же куками, и радуешься...
Можно в БД хранить токены. Есть полет для творчества. Можно зашифровать токен и без ключа его не открыть не ведающим.
Кстати, попутный вопрос. Как через CURL получить/забрать/стащить серверную сессионную куку $_SERVER['token'] ? CURLOPT_COOKIEJAR ее читает? Не баловался с этим, так как надобности не было.
Сейчас провел эксперимент, и не удалось мне стащить $_SERVER через CURLOPT_COOKIEJAR. В таком случае нет смысла беспокоиться, так как токен всегда хранится либо в $_SERVER, либо в БД. Стащить удается только куки из setcookie(); А для защиты CSRF применяется серверная сессионная кука $_SERVER или БД. Иначе не будет работать защита CSRF. Т.е. даже шифровать не нужно. Обычный CSRF протект достаточно. Вот результаты: предварительно установил куку через setcookie('TestCookie', '123'). Выдает только сессию и куку. Все что было в $_SERVER не записывается. Т.е. это никак не поможет украсть токен. Если под этой сессией зайти на страницу с целью получить токен, то тут же сгенерируется новый токен. А по другому не достать токен, так как он не отдастся на запрос curl. Код (Text): # Netscape HTTP Cookie File # https://curl.haxx.se/docs/http-cookies.html # This file was generated by libcurl! Edit at your own risk. localhost FALSE / FALSE 0 TestCookie 123 localhost FALSE / FALSE 0 PHPSESSID ebo4ini92rboi6el4v161db4vt8e66oe Это сохраняется в файл через флаг CURLOPT_COOKIEJAR
Сорри, прошу читать выше не $_SERVER а $_SESSION... Че то запарился. Если можно, отмодерируйте, пожалуйста.
Во, а я уж подумал, что я чего-то не знаю А откуда она там берётся? PHPSESSID ebo4ini92rboi6el4v161db4vt8e66oe - вот отсюда. Если эта кука прилетит на ваш сайт, php подключит эту сессию
Подключит, и выдаст новый токен. Поэтому POST не пройдет. В том то и вся фишка. Процесс следующий: 0. Сравнивается входящий POST токен и токен в сессии. Если нет токена в сесии или POST токена или они не равны, то POST не обрабатывается и по желанию пишем маты в echo хацкеру. Я предпочитаю хацкеру ничего не говорить, пусть ломает башку. 1. Генерируется токен и сохраняется в сессию $_SESSION 2. Размещается в input hidden в POST формах HTML. 3. При отправке формы передается обработчику. Обработчик, получая POST hidden token сравнивает его с сессией в п. 0 и разрешает/запрещает POST, и генерирует опять новый токен вставляя его одновременно в новый FORM hidden. Таким образом при генерации нового запроса генерируется новый токен даже с той же сессией, и его нельзя перехватить зная сессию. А сам токен при этом одновременно сохраняется на оригинальной странице в hidden, для дальнейшей его сверки через входящий POST form.
Я правда очень внимательно ознакомился с CSRF и наглухо не могу понять, как это мне может помочь... У меня на странице есть код, который запрашивает этот самый "CSRF-токен", что мешает взять этот код и встроить его в страницу на другом сайте, запросить токен и спокойно валидироваться у моего .php? Допустим "токен" передается при загрузке страницы, тогда "пират" эмулирует браузер, загружает "в тень" мою страницу, получает заветный токен и дальше по накатанной... и никакие привязки к объему данных на странице и т.п. не сработают, т.к. я должен всё дешифровывать на стороне клиента, достаточно просто спарсить js который это делает. Где я ошибаюсь? Вот если бы мне нужно было организовать множественные постоянные обмены, и я боялся, что данные будут перехвачены "по дороге", тогда да, все эти "короткие сессии" и токены работают. А у мня то одно единственное обращение к .php - тут делов то: глянул как запрашивается "токен", получил его ровно тем же способом, потом использовал для получения результата. --- Добавлено --- Ну в крайнем случае "пират", может использовать не cURL, а мой же код js, взятый с моей же страницы...
Получает токен, и передает его на сервер со своего хоста, получая новый сеанс связи, а значит и генерацию нового токена. А значит токены не совпадут и POST запросы не обработаются. Вникните в мой предыдущий пост, не знаю как уже подробнее объяснить.
Ну и что? У меня же на сайте одновременно "сидят" десятки разных пользователей, я не могу ограничить доступ к .php только одной текущей сессией. Как сервер отличит моего пользователя от "пирата"? Ну запросил "кто то там" токен - сервер его радостно выдал. А кто запросил и откуда, как я понимаю, сервер понятия не имеет. Дальше "пират" просто вставляет мой же js код-обработчик на свою страницу и радостно пользуется всеми рулёзами на тех же правах, что и другие мои пользователи. Проблема в том, что я во всей этой "хитрой" схеме не вижу никакой привязки к домену, все эти токены можно получить с какого угодно сайта, было бы желание... Надеюсь, что я упускаю что то важное, прошу ткнуть носом =) --- Добавлено --- Давайте для чистоты эксперимента, представим, что "пират" просто полностью скопировал мою страницу со всеми js, разметками и т.п. и разместил на своем домене. Ваша схема защиты сработает в таком случае?
Ну ё-мое... Вы читаете что написано выше? Мне перепечатать? В суть вникните. Где генерация происходит? На сервере, для любой сессии. Перед формированием страницы стоит генерация. На самом верху до HTML. Затем идет проверка на токен. Если не прошла, то и POST не проходит. Напишу уже грубым примером, простейшим для понимания сути наброском: PHP: <?php session_start(); csrfToken(); // генерируем токен csrfVerification(); // Верифицируется токен. Сравниваем входящий POST токен и токен из $_SESSION['csrf_token'], и если FALSE то делаем exit; к примеру. $_SESSION['csrf_token'] = getCsrfToken(); // забираем ТОТ ЖЕ токен в сессию (он не генерируется теперь ,а просто отдается) ?> <html> <head> <body> Далее некая POST форма типа <input type="hidden" name="csrf_token" value="<?php echo getCsrfToken(); ?>" /> </body> </head> </html> Вы можете эту форму хоть всю спарсить вместе с PHP: <div id="csrf_token" class='hidden' data-csrf='<?php getCsrfToken(); ?>'></div> но, при этом при вашем НОВОМ (повторюсь, НОВОМ сеансе), вы попадете на начало этого кода и опять будет сгенерирован новый токен, даже если у вас сессия та же.Токены не совпадут и финица ля комедия.
Суть CSRF примерно такая. Вот как стянуть еще на стадии HTML сессию чтобы запихнуть ее в CURL и передать вместе со стянутым токеном?
Я вот покумекал и понимаю откуда у вас вопросы. Если спарсить и сессию и токен к примеру в браузере, и вручную заменить заголовки на CURL и передать все это на обработчик, то в этом случае можно обойти стандартную защиту CSRF так как мы подменяем запрос браузера от формы с теми же заголовками. Нужно еще подумать... Но писать скрипт под этот CURL-снифер уже придется под расширение браузера ну или еще как то. Т.е. это уже другой уровень по идее. Видимо действительно CSRF в чистом виде не подойдет, разве что осложнит действия.
@musicman3 Забавный ты человек. CSRF должен генерироваться на два запроса. Если он генерируется на один запрос, то ни один запрос не будет просто проходить. Он генерируется, когда запрошена форма гет-запросом и записывается да, в сессию. Потом сверяется, когда форма обрабатывается, и тогда, в принципе, может быть анулирован. Если после начала обработки формы ты, как в твоём коде, сгенеришь другой токен, не обработав форму, то всё, кердык, тот, что пришёл с формой с ним не совпадёт.
@musicman3, однако, токены используются для уже однажды прошедшего аутентификацию клиента. Вопрос же в том, чтобы эту самую аутентификацию выполнить, без регистрации клиентов. @denismix Соответствнно, вопрос: по каким признакам пользователей причисляете к "своим"?
Генерация токена и присвоение для $_SESSION происходят между верификацией. PHP: csrfToken(); csrfVerification(); // Сравниваем входящий POST токен и токен из $_SESSION['csrf_token'] $_SESSION['csrf_token'] = getCsrfToken(); Т.е. верификация это - Сравниваем входящий POST токен и токен из $_SESSION['csrf_token']. Входящий POST и старую сессию. Вроде бы все логично. Т.е. верификация происходит еще со старой сессией, а потом уже третьей строчкой присваивается свежая сессия. В принципе если поменять местами первые 2 строчки то ничего не поменяется. Можно вначале верифицировать, а потом генерировать. --- Добавлено --- Да, это понятно. Защитой CSRF можно избавиться только от простых CURL запросов, которые скорее всего его так и юзают, но если найдется парсер + CURL с малым временем парсинг-отправка, то конечно же здесь уже такой вариант не прокатит.
Не поможет тебе защита с CSRF токеном. На самих убежденных, в ней защите, людей, тратить время тоже нет смысла. CURL - это абсолют тот же браузер пользователя. Только без мозгов. Сессия привязывается через - куки. Это тоже легко сейвится и используется. Не выдумывайте всякий пи3дешь. --- Добавлено --- Когда противоречие сочинять будешь для CURL, не забудь для браузера сочинить --- Добавлено --- куда тебя несет ? Ты вообще не в теме. Сниферы ему....
У тебя варианты как у кодера с его СуперПупер защитой пароля - преобразовать пароль в хеш код, поменять местами каждый пятый символ - Win. Приходит другой кодер - ломает твою верификацию пароля. Аминь.
У тебя какие варианты есть? Мой вариант хотя бы простые CURL без парсинга отрежет если у него нет никакой проверки для формы. Что ты предлагаешь? Обосрать на ровном месте тему?
Господа, пожалуйста не ссорьтесь по пустякам! (с) ====================== Проблема, что "никак" - я ищу вариант причислять пользователей к "своим", если они послали запрос именно с моего сайта (с моего домена). Ваш метод работает только для идентификации "последующих" запросов, от перехвата и подмены, а не от первичной проблемы. Я же для наглядности задал вам вопрос: "будет ли работать ваш метод, если "пират" полностью скопирует мою страницу на свой домен" - т.е. его "подложная" страница будет загружаться точно так же как и моя с самого начала, с единственной разницей, что домен будет изначально "чужим", но с "подставленным" заголовком, что он мой.
То есть, важно, чтобы человек или робот обязательно открыл страничку и увидел, например, рекламный блок? Этим сервисом тоже вы управляете? --- Добавлено --- Вчитался: Проблема оказывается, в том, чтобы с других сайтов не обращались к вашему сервису обработки фотографий... Так? --- Добавлено --- Вот что означала фраза "с чужих доменов" в первом сообщении