2010-07-23 2 views
21

Я работаю на совершенно АЯКС-ориентированное приложение, где все запросы проходят через то, что в основном сводится к главному контроллеру, который, на его голые кости, выглядит примерно так:Является ли сервер заголовка X-Requested-With достаточным для защиты от CSRF для приложения, управляемого ajax?

if(strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') { 
    fetch($page); 
} 

Является ли это обычно достаточно, чтобы защитить против подделок поддельных запросов?

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

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

EDIT - Возможно, статический токен, такой как UUID пользователя, будет лучше, чем ничего?

EDIT # 2 - As The Rook указал, что это может быть вопрос, связанный с волосами. Я читал спекуляции в обоих направлениях и слышал отдаленные шепоты о более старых версиях флеш-памяти, которые можно использовать для таких махинаций. Поскольку я ничего не знаю об этом, я предлагаю щедрость всем, кто может объяснить, как это риск CSRF. В противном случае, я даю это Artefacto. Благодарю.

+0

для записи Артефакто был верным. Вы должны прочитать руководство по безопасности браузера, а не спрашивать SO. Многие из ответов на SO неверны, особенно для таких разделов волос. – rook

+0

В старых версиях флэш-памяти действительно существовали некоторые уязвимости (http://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_Flash). Тем не менее, для пользователей, которые действительно используют эти старые версии Flash, я бы сказал, что атаки CSRF являются меньшими из их проблем при столкновении с произвольными уязвимостями выполнения кода. – Artefacto

+0

http://stackoverflow.com/questions/17478731/whats-the-point-of-the-x-requested-with-header | http://security.stackexchange.com/questions/23371/csrf-protection-with-custom-headers-and-without-validating-token –

ответ

13

Я бы сказал, этого достаточно. Если разрешены междоменные запросы, вы все равно обречены на то, что злоумышленник может использовать Javascript для извлечения маркера CSRF и использовать его в поддельном запросе.

Статический токен - отличная идея. Маркер должен генерироваться не реже одного раза в сеанс.

EDIT2 Майк не прав, в конце концов, извините. Я не читал связанную с ним страницу. Он говорит:

простой запрос кросс-сайт один, что: [...] Не установить пользовательские заголовки с HTTP-запросом (например, X-Modified и т.д.)

Поэтому, если вы установили X-Requested-With, запрос должен быть предварительно обработан, и если вы не ответите на запрос перед пролетом OPTIONS, разрешающий запрос на межсайтовый сайт, он не пройдет.

EDIT Mike прав, с Firefox 3.5, межсайтовый XMLHttpRequests - permitted. Следовательно, вы также должны проверить, соответствует ли заголовок Origin, когда он существует, ваш сайт.

if (array_key_exists('HTTP_ORIGIN', $_SERVER)) { 
    if (preg_match('#^https?://myserver.com$#', $_SERVER['HTTP_ORIGIN']) 
     doStuff(); 
} 
elseif (array_key_exists('HTTP_X_REQUESTED_WITH', $_SERVER) && 
     (strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest')) 
    doStuff(); 
+0

Джентльмену, который проголосовал за меня, не можете объяснить, что случилось с моим ответом? – Artefacto

+0

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

+0

@musicfreak Этот заголовок добавляется только тогда, когда запрос выполняется через Javascript. CSRF нельзя выполнить с помощью Javascript из-за ограничений между сайтами. Следовательно, этого достаточно. Конечно, вы можете «подделать» заголовок, например. создав браузер, который всегда отправляет этот заголовок. Но, сделав это, вы стреляете в ногу. Защита от CRFS - это защита для пользователей ** от самих себя **, по отношению к запросам, которые были злонамеренно и программно сделаны сами по себе. – Artefacto

0

Я не думаю, что это предлагает какую-либо защиту. Атакующий сайт все еще может использовать xmlhttprequest для запроса кросс-сайта в обход вашей проверки.

+0

Не могли бы вы найти правильное решение? Вам не нужно держать меня за руку и проводить через нее, но, возможно, вы могли бы указать мне в правильном направлении? :) – Greg

+0

@Greg: Нет, не совсем. Я думал, что использовать одноразовый токен - это путь. Но я не испытываю этого. – Alex

0

Короткий ответ: нет. Любой злоумышленник просто использует Ajax для атаки вашего сайта. Вы должны создать случайный токен с коротким, но не слишком большим сроком службы, который вы будете обновлять во время каждого запроса ajax.

Вам нужно будет использовать массив токенов в javascript, так как вы можете одновременно запускать несколько запросов ajax.

+2

У меня создалось впечатление, что междоменные запросы AJAX не разрешены? Наверное, есть обходные пути? – Greg

+0

Злоумышленник может использовать Firebug или другую консоль разработчика для AJAX в домене. –

+2

-1, нужно написать эксплойт для резервного копирования этого комментария? Нет? Я так не думал. xmlhttprequest не может быть перекрестным сайтом, что является нарушением той же политики происхождения. это может быть не сильный метод неповиновения, но вы не можете написать для этого эксплойт. Прочтите руководство по безопасности браузера Google. – rook

0

Что вы делаете, это безопасно, потому что xmlhttprequest обычно не уязвим для подделки подпроса.

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

(Это резюме, я добавляю этот ответ, потому что этот вопрос очень проблематично, посмотрим, что говорят голоса)

1

Я не считаю, что это безопасно. Те же политики происхождения предназначены для предотвращения доступа документов из разных доменов к содержимому, которое возвращается из другого домена. Вот почему проблемы XSRF существуют в первую очередь. Вообще XSRF не заботится об ответе. Он используется для выполнения определенного типа запроса, например, для удаления. В простейшей форме это можно сделать с помощью правильно отформатированного тега img. Ваше предлагаемое решение предотвратит эту простую форму, но не защитит кого-либо от использования объекта XMLHttp для запроса. Вам необходимо использовать стандартные методы предотвращения XSRF. Мне нравится генерировать случайное число в javascript и добавлять его в файл cookie и переменную формы. Это гарантирует, что код также может записывать файлы cookie для этого домена. Если вы хотите получить дополнительную информацию, см. this entry.

Кроме того, чтобы упредить комментарии о том, что XMLHttp не работает в скрипте. Я использовал следующий код с firefox 3.5, чтобы сделать запрос на google из html, запущенного в домене localhost. Содержимое не будет возвращено, но с использованием firebug вы можете увидеть, что запрос выполнен.

<script> 
var xmlhttp = false; 

if (!xmlhttp && typeof XMLHttpRequest != 'undefined') { 
    try { 
     xmlhttp = new XMLHttpRequest(); 
    } catch (e) { 
     xmlhttp = false; 
    } 
} 
if (!xmlhttp && window.createRequest) { 
    try { 
     xmlhttp = window.createRequest(); 
    } catch (e) { 
     xmlhttp = false; 
    } 
} 

xmlhttp.open("GET", "http://www.google.com", true); 
xmlhttp.onreadystatechange = function() { 
    if (xmlhttp.readyState == 4) { 
     alert("Got Response"); 
     alert(xmlhttp.responseText) 
    } 
} 

xmlhttp.send(null) 
alert("test Complete"); 

+0

Извините, мне пришлось отредактировать его, чтобы удалить мой верхний угол. – Artefacto

+0

Я передаю его Artefacto, потому что похоже, что X-Requested-With не проходит, но это было интересно. Спасибо. – Greg

Смежные вопросы