Расширения браузера пользуются огромной популярностью: каждый третий пользователь Firefox или Google Chrome имеет хотя бы одно расширение. Но мало кто использует расширения браузеров как средства для проверки Web-сайтов на уязвимости. В этой статье предложен способ анализа Web-приложений на уязвимости на примере расширения для Chrome.
В этой статье пойдет речь о некоторых особенностях расширений для Chrome, которые являются важными при разработке средств безопасности. Примером будет расширение для Google Chrome — «Yel-CSRF-tool» разработанное при финансовой поддержке «Фонд содействия развитию малых форм предприятий в научно-технической сфере», это расширение помогает специалистам по анализу защищенности веб приложений тестировать сайты на CSRF уязвимости.
Сross Site Request Forgery (CSRF) или Межсайтовая подделка запроса — вид атак на посетителей веб-сайтов, использующий недостатки протокола HTTP. Например если жертва заходит на сайт, созданный злоумышленником, то от её лица тайно отправляется запрос на другой сервер (например, на сервер платёжной системы), осуществляющий некую вредоносную операцию (например, перевод денег на счёт злоумышленника). Для осуществления данной атаки жертва должна быть аутентифицирована на том сервере, на который отправляется запрос, и этот запрос не должен требовать какого-либо подтверждения со стороны пользователя, который не может быть проигнорирован или подделан атакующим скриптом. CSRF защита реализуется с помощью подписанных CSRF токенов. Данная уязвимость встречается достаточно часто.
У расширений для Chrome очень простая и прозрачная архитектура. У всех расширений есть фоновая страница — «background.html», которая может содержать JavaScript код для управления расширением. Так же, у расширений есть «manifest.json» который является настройками приложения. Что бы взаимодействовать с содержимым веб. страницы, в статье будет использоваться «devtools.html», именно он будет иметь доступ ко всему содержимому страницы и обеспечивать работу вкладки в инструментах разработчика.
Для того чтобы расширение имело право на взаимодействие с содержимым веб. страницы, необходимо такое разрешение выдать. Сделать это можно в настройках расширения, а именно в «manifest.json». Расширение, создаваемое для анализа сайтов на уязвимости, должно иметь доступ к самой странице и всем необходимым сторонним сайтам, именно такие параметры можно указать (Листинг 1).
«permissions»: [
«tabs»,
"
]
Листинг 1.
Фаил «backgroud.js» обеспечивает работу фоновых функций. Для того, что бы анализировать приложения на CSRF уязвимости, необходимо перехватывать запросы. Для этого Chrome позволяет создать Listener — специальную функцию, которая будет «слушать», что происходит и в зависимости от описанных свойств выполнять те или иные действия. Перехваченные запросы так же нужно обработать и вывести на экран, сделать это можно, например отправив объект запроса как сообщение другим модулям расширения, например, как в (Листинг 2).
chrome.runtime.onConnect.addListener(function(port) {
var requestData;
port.onMessage.addListener(function(message) {
if (port.name == «new tab» || port.name == «selected query») {
requestData = message;
}
});
})();
Листинг 2.
Обработкой запросов это очень важная часть расширения, обрабатывать и выводить данные о запросах удобно в на панели в инструментах разработчика. В рамках статьи, будут рассмотрены только POST запросы, однако реализация для других типов запросов не будет существенно отличаться.
И так, первое что нужно сделать, это получить объект с запросом от функции представленной выше и как то записать эти запросы на панели (Листинг 3).
var allRequests = [],
availableTypesOfRequests = [«POST»];
var requestPort = chrome.runtime.connect({ name: «request» });
chrome.devtools.network.onRequestFinished.addListener(function(request) {
if (availableTypesOfRequests.includes(request.request.method)) {
requestPort.postMessage(request);
var $div = $("");
$div.append(""+request.request.method+""+request.request.url.split('/') [2]+" x");
$div.append(""+request.request.url+"");
$(".requests_list»).append($div);
$(".request»).filter(":even»).addClass("_v2");
allRequests.push(request);
}
});
Листинг 3.
Как видно из кода выше, получив запрос, программа создает DOM структуру для нового запроса и добавляет сам запрос в массив allRequests — массив, в котором содержатся все перехваченные запросы. Теперь для проверки, есть ли CSRF уязвимость, нужно сначала проверить наличие CSRF токена в списке параметров запроса. Такую проверку можно сделать только вручную, так как программисты могут использовать любые имена для обозначения CSRF токенов, кроме того, не редки случаи, когда наличие токена не гарантирует отсутствие уязвимости. Для того, что бы убедиться в отсутствие CSRF уязвимости, можно заменить значение некоторых полей (в том числе значение поля CSRF токена) и отправить запрос повторно. Для этого, в рамках статьи, будет представлено, как можно реализовать пользовательский интерфейс для выполнения всех вышеуказанных действий (Листинг 4).
$(".requests_list»).on(«click», ".request», function(e) {
e.preventDefault();
$(".options»).text(" ");
var current_request = allRequests [parseInt($(this).prop(«id»))],
$form = $("
");$form.prop(«id», $(this).prop(«id»));
var selectedQuery = chrome.runtime.connect({ name: «selected query» });
selectedQuery.postMessage(current_request);
var $formParams = $("");
$(".options»).append("decodeURI");
$(".options»).append("encodeURI");
function form_filling(myArray) {
myArray.forEach(function(item, i, arr) {
var $input = $("");
$input.prop({ 'value': decodeURIComponent(item.name), «id»: i });
$formParams.append($input);
var $input = $("");
$input.prop({ 'value': decodeURIComponent(item.value), «id»: i });
$formParams.append($input);
$formParams.append("x");
});
$form.append($formParams);
var $myDiv = $("");
$myDiv.append($("Add field"));
$myDiv.append($(""));
$form.append($myDiv);
}
switch (current_request.request.method.toString()) {
case «POST»:
$formParams.append(«URL:
");
if (current_request.request.postData.params) {
form_filling(current_request.request.postData.params);
} else {
$(".options»).append("
There are no params
");}
$(".options»).append($form);
break;
default:
$(".options»).append("
This request type not supported
"+JSON.stringify(current_request.request)+"}
});
Листинг 5.
Как видно, в коде, представленном выше, формируется форма с уже заполненными парами полей, где первое поле из пары это имя поля исходного запроса, а второе поле, это значение исходного запроса. Теперь специалист по безопасности, может изменить значения полей или вовсе удалить поле из запроса и нажав на созданную выше кнопку «submit» он должен отправить модифицированный запрос на известный адрес. В силу особенностей архитектуры всех расширений для Chrome, мы должны создать страницу с новой формой и отправить ее на исходный адрес, для этого нужно отправить новые данные в модуль отправки запроса — «request_sending_page.html» (Листинг 6).
$(".options»).on(«submit», «form», function(e) {
e.preventDefault();
var newTabPort = chrome.runtime.connect({ name: «new tab» }),
new_url,
params = [];
$.each($(".options»).find(«form»).find(«input»), function(i, val) {
params.push($(val).val());
});
new_url = params [0];
params.shift();
newTabPort.postMessage({
params: params,
request: allRequests [parseInt($(this).prop(«id»))].request,
new_url: new_url
});
});
Листинг 6.
Затем, отправив данные, в модуле отправки запросов, необходимо сгенерировать новую форму и отправить ее. Для этого, аналогично тому, как это делалось раньше, модуль получает сообщение и обрабатывает данные, так, как это представлено в коде ниже (Листинг 7).
request_sending_page.html
request_sending_page.js
$(function() {
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if (request.request.method === «POST») {
var $form = $("
");$form.prop({ «method»: «POST», «action»: request.new_url });
for (var i = 1; i < request.params.length; i += 2) {
$("").prop({ «name»: request.params [i-1], «value»: request.params [i]}).appendTo($form);
}
$form.append("");
$(«body»).append($form);
$form.submit();
}
});
});
Листинг 7.
Теперь, когда запрос ушел на сервер, а браузер специалиста получил ответ, человек может с легкостью определить, есть ли уязвимость в конкретном месте веб приложения.
В статье было показано как можно создать простое средство анализа защищенности веб приложения на базе браузера. Показано как можно провести анализ на CSRF уязвимости и как можно упросить процесс самого анализа. Для дальнейшей автоматизации действий специалиста по безопасности, следует реализовать подобный функционал для запросов других типов.
Литература:
- Cross-Site Request Forgery (CSRF) // OWASP. URL: https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF) (дата обращения: 28.04.2017).
- Chrome Apps Architecturedeveloper.chrome.com // developer.chrome.com. URL: https://developer.chrome.com/apps/app_architecture (дата обращения: 28.04.2017).