Защита данных POST в веб-приложении - PullRequest
3 голосов
/ 13 сентября 2009

У меня есть веб-приложение с базовой аутентификацией - имя пользователя, пароль, сеанс и прочее. Однако у меня есть особая необходимость, чтобы пользователи не могли подделать запросы POST (даже для зарегистрированных пользователей). В моем приложении я специально проверяю сеанс пользователя, прежде чем принимать данные POST (заботясь о XSS и прочем).

Как:

if(user session exists)
{
    // handle the data POSTed
}

else {
   // ...
}

Я храню идентификаторы сеансов в базе данных. Есть ли еще что-то, о чем я должен знать, чтобы предотвратить поддельные POST-запросы, или этого достаточно?

Ответы [ 8 ]

3 голосов
/ 13 сентября 2009

Я специально проверяю сеанс пользователя перед принятием POST

Если вы имеете в виду то, что обычно подразумевается под «сессией»: постоянный токен, хранящийся в файле cookie, который идентифицирует пользователя и связанные с ним данные сеанса, то нет, этого недостаточно. Этот файл cookie автоматически отправляется браузером, даже если запрос POST был спровоцирован другим (атакующим) сайтом.

Ключевое слово, которое вы ищете здесь - это подделка межсайтовых запросов или XSRF , где злоумышленник может сделать аутентифицированного пользователя (с помощью сценариев или других методов), чтобы сделать запрос GET или POST твой сайт. Такие запросы обычно не отличаются от законных запросов. (Некоторые люди пытаются это сделать, проверяя данные HTTP-реферера, но это ненадежно.)

Эти атаки не так быстро наносят ущерб, как инъекции на стороне сервера (SQL, команда) или на стороне клиента (HTML, JavaScript), но они встречаются чаще, чем оба: к сожалению, немногие веб-программисты включают надлежащие контрмеры , Пока их сайты не будут скомпрометированы дырой XSRF.

Существуют различные способы защиты от XSRF, но единственный действительно эффективный подход - включить в каждую отправляемую форму секретное значение, которое сторонний злоумышленник не узнает. Это часто называют почтовым ключом, как упомянул Eimantas.

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

<form method="post" action="delete.php"><div>
    <input type="hidden" name="key" value="<?php echo(htmlspecialchars($user['key'])); ?>"/>
    <input type="submit" value="Delete" />
</div></form>

if ($_POST['key']!=$user['key'])
    // error

Злоумышленник не знает ключ для этого пользователя, поэтому не может создать ссылку / форму, которая его содержит.

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

2 голосов
/ 13 сентября 2009

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

1 голос
/ 13 сентября 2009

Использовать CAPTCHA изображение.

Сеть построена на REST, который по определению предназначен для передачи состояния из одной точки в другую. Кто-то, у кого достаточно времени, может создать запрос POST, который имитирует активный сеанс.

Как и все безопасные запросы, CAPTCHA проверяется на стороне сервера.

1 голос
/ 13 сентября 2009

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

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

0 голосов
/ 13 сентября 2009

В вашей модели (и особенно если вы используете целые числа для идентификаторов сеансов) злоумышленник может легко отправить запрос от имени другого пользователя (например, уменьшить свой собственный идентификатор сеанса, и вы уже являетесь кем-то другим, если этот идентификатор сеанса существует) , Вам необходимо иметь уникальный ключ / идентификатор сеанса, связанный с каждым идентификатором сеанса и сохраненный как в БД, так и на клиенте в файлах cookie. Каждый раз, когда ваш клиент отправляет запрос, вы должны читать не только идентификатор сеанса, но и идентификатор GUID сеанса, а затем проверять их оба на соответствие значениям вашей базы данных. В дополнение к этому вы также можете рассмотреть некоторые стратегии смягчения последствий XSRF.

0 голосов
/ 13 сентября 2009

Принимая пользовательский ввод, перед началом сохранения данных в базе данных необходимо выполнить нулевой уровень, чтобы убедиться, что вы запускаете данные с помощью функции mysql_real_escape_string ($ MyPostData).

Кроме того, для каждой переменной / данных, которые вы хотите принять через POST, целесообразно программно проверять их на основе их типа и того, что вы собираетесь с ними делать.

Это два основных правила, гарантирующих, что от пользователя не будет «забавного» бизнеса: убедитесь, что вы работаете с действительными переменными И убедитесь, что данные, попадающие в базу данных, проверены и правильно экранированы.

0 голосов
/ 13 сентября 2009

Если пользовательский сеанс является долгоживущим, вы по-прежнему подвержены XSRF . Вы должны принять меры против этого тоже.

Если вы находитесь на .NET, проверьте AntiForgeryToken,

http://msdn.microsoft.com/en-us/library/dd492767.aspx

0 голосов
/ 13 сентября 2009

В моем текущем приложении у меня есть некоторый код, который отправляется в браузер, а затем браузер отправляет обратно и не может его изменить. Я добавляю к значению секретную строку, получаю контрольную сумму SHA1 для этой полной строки, а затем требую, чтобы браузер отправил обратно как значение, так и контрольную сумму. Я почти уверен, что именно так .NET делает viewstate тоже.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...