Защита 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, то функция может выглядеть примерно так:

function callAjax(value1,value2) {
     var target=$("#output");
     $.ajax({
          url: "/ajaxcgi.php?arg1="+value1+"&arg2="+value2,
          cache: false,
          beforeSend: function(xhr){
               target.html('<img src="/images/loading.gif">');
               xhr.setRequestHeader("Ajax-Timestamp", Date());
          },
          success: function(html) {
               target.html(html);
          }
     });
}

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

function callAjax(value1,value2) {
     if (window.XMLHttpRequest) {
          http = new XMLHttpRequest();
     } else if (window.ActiveXObject) {
          http=new ActiveXObject("Msxml2.XMLHTTP");
          if (! http) {
               http=new ActiveXObject("Microsoft.XMLHTTP");
          }
     }
     var target=document.getElementById("output");
     var nocache=Math.random();
     http.open('GET', '/ajaxcgi.php?arg1="+value1+"&arg2="+value2+"&nocache ="'+nocache');
     http.setRequestHeader("Ajax-Timestamp",Date())
     http.onreadystatechange = function() {
         if (http.readyState == 4) {
             var response = http.responseText;
             target.innerHTML = response;
         }
         else if (http.readyState == 2) {
             target.innerHTML = '<img src="/images/loading.gif">';
         }
     }
     http.send(null);
}

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

Снимок-1

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

<Location ~ "/ajaxcgi.php">
SecRuleInheritance On
SecDefaultAction log,auditlog,deny,status:403,phase:2

# Запрещаем запросы с отсутствующим заголовком Ajax-Timestamp
SecRule &REQUEST_HEADERS:Ajax-Timestamp "@eq 0"

#Запрещаем запросы, содержащие в этом заголовке не то, что мы ожидаем увидеть
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+\)$"
</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