Защита web-приложения, использующего Ajax (Ajax Fingerprinting)

Date January 28th, 2010 Author Vitaly Agapov

ajaxНа редком сайте сейчас не увидишь привычных уже крутящихся иконок асинхронной загрузки через Ajax. Однако новые технологии приносят и новые беды в виде новых уязвимостей и дыр в безопасности. Меж тем, недавно я узнал о таком понятии как “Ajax fingerprinting”. Почитал про него, попробовал в деле, узнал кое-какие тонкости и сейчас об этом пишу. В целом идея тривиальна: в браузере JavaScript’ом генерируем Ajax’овый GET-запрос с дополнительным полем в заголовке XHR (XMLHttpRequest), а на стороне сервера с помощью mod_security фильтруем всё Ajax-запросы, не содержащие этого поля или содержащие неверное значение. Не самая крепкая защита, но лучше, чем ничего. Не зря гласит народная мудрость: “Если у Вас паранойя, то это не значит, что за Вами не следят”.

Посмотрим, как это всё реализовать.

Допустим, у нас есть некоторый сайт, динамически обновляющийся с помощью Ajax. При этом Ajax-запросы идут на некоторый web-сценарий с названием ajaxcgi.php, то есть сайт подгружает ссылки вида http://domain.name/ajaxcgi.php?arg1=value1&arg2=value2. При этом мы хотим защитить этот сценарий от запусков со стороны посторонних.

Для начала обратимся к JS-функции, производящей фоновый Ajax-запрос к ajaxcgi.php. Если мы используем фрэймворк jQuery и вызов $.ajax, то функция может выглядеть примерно так:

01.function callAjax(value1,value2) {
02.     var target=$("#output");
03.     $.ajax({
04.          url: "/ajaxcgi.php?arg1="+value1+"&arg2="+value2,
05.          cache: false,
06.          beforeSend: function(xhr){
07.               target.html('<img src="/images/loading.gif">');
08.               xhr.setRequestHeader("Ajax-Timestamp", Date());
09.          },
10.          success: function(html) {
11.               target.html(html);
12.          }
13.     });
14.}

Если jQuery мы не используем, то эта функция может выглядеть так:

01.function callAjax(value1,value2) {
02.     if (window.XMLHttpRequest) {
03.          http = new XMLHttpRequest();
04.     } else if (window.ActiveXObject) {
05.          http=new ActiveXObject("Msxml2.XMLHTTP");
06.          if (! http) {
07.               http=new ActiveXObject("Microsoft.XMLHTTP");
08.          }
09.     }
10.     var target=document.getElementById("output");
11.     var nocache=Math.random();
12.     http.open('GET', '/ajaxcgi.php?arg1="+value1+"&arg2="+value2+"&nocache ="'+nocache');
13.     http.setRequestHeader("Ajax-Timestamp",Date())
14.     http.onreadystatechange = function() {
15.         if (http.readyState == 4) {
16.             var response = http.responseText;
17.             target.innerHTML = response;
18.         }
19.         else if (http.readyState == 2) {
20.             target.innerHTML = '<img src="/images/loading.gif">';
21.         }
22.     }
23.     http.send(null);
24.}

В обоих случаях мы сделали добавление к заголовкам запроса заголовок Ajax-Timestamp с текущим временем. Само собой, можно сделать какое-то более сложное значение.

Снимок-1

Теперь обратимся к тёмной серверной стороне. Там мы уже подключили к Apache модуль mod_security2 и готовы добавить парочку правил SecRule. Открываем наш файл modsecurity_crs_15_customrules.conf (или любой другой конфиг, читаемый Апачем) и пишем:

01.<Location ~ "/ajaxcgi.php">
02.SecRuleInheritance On
03.SecDefaultAction log,auditlog,deny,status:403,phase:2
04. 
05.# Запрещаем запросы с отсутствующим заголовком Ajax-Timestamp
06.SecRule &REQUEST_HEADERS:Ajax-Timestamp "@eq 0"
07. 
08.#Запрещаем запросы, содержащие в этом заголовке не то, что мы ожидаем увидеть
09.SecRule REQUEST_HEADERS:Ajax-Timestamp "!^\w{3}\s\w{3}\s\d{2}\s\d{4}\s\d{1,2}\:\d{2}\:\d{2}\sGMT(\+|-)\d{4}\s\(\w+\)$"
10.</Location>

Перечитываем Апачем конфиги и пытаемся воспользоваться Ajax-вызовом. Работает! А если старой версией JS-функции?

Снимок-2

Не работает! Получили отбой с ошибкой 403, как и хотели.

В целом идея такова, дальше можно подумать над её усовершенствованием и use cases.

Ссылка:

http://www.modsecurity.org/documentation/Ajax_Fingerprinting_and_Filtering_with_ModSecurity_2.0.pdf

Tags: , ,
Category: Apache, Security, Web-dev | 1 Comment »

Comments

Один комментарий на “Защита web-приложения, использующего Ajax (Ajax Fingerprinting)”

  1. Evil

    хм.. а в чём защита?

    Это запрос подменяется на раздва…

Leave a comment

 Comment Form