Формально об инъекциях. Модель инъекции. Критерий защищённости от атак инъекций

Содержание

Слайд 2

Руководитель отдела исследований по анализу защищённости приложений Positive Technologies AppSec- и

Руководитель отдела исследований по анализу защищённости приложений Positive Technologies
AppSec- и CS-исследователь

(формальные методы анализа и защиты кода) Организатор Positive Development User Group
https://about.me/vladimir.kochetkov
https://kochetkov.github.io/
vkochetkov@ptsecurity.com

:~$ whoami

Слайд 3

Открытое сообщество разработчиков и IT-специалистов, которые стремятся создавать безопасные приложения. https://t.me/ru_appsec Positive Development User Group

Открытое сообщество разработчиков и IT-специалистов, которые стремятся создавать безопасные приложения. https://t.me/ru_appsec

Positive Development

User Group
Слайд 4

Ещё один унылый доклад про параметризацию SQL-запросов? Intro (1/3)

Ещё один унылый доклад про параметризацию SQL-запросов?

Intro (1/3)

Слайд 5

Существует ли конечное множество правил разработки защищённых приложений? Intro (2/3)

Существует ли конечное множество правил разработки защищённых приложений?

Intro (2/3)

Слайд 6

Если ты хочешь построить корабль, не надо созывать людей, планировать, делить

Если ты хочешь построить корабль, не надо созывать людей, планировать, делить

работу, доставать инструменты. Надо заразить людей стремлением к бесконечному морю…

Intro (3/3)

Слайд 7

Инъекции – самый распространённый тип атак (1/2) https://www.ptsecurity.com/upload/corporate/ru-ru/analytics/WebApp-Vulnerabilities-2017-rus.pdf

Инъекции – самый распространённый тип атак (1/2)

https://www.ptsecurity.com/upload/corporate/ru-ru/analytics/WebApp-Vulnerabilities-2017-rus.pdf

Слайд 8

Инъекции – самый распространённый тип атак (2/2) 84,6% https://www.ptsecurity.com/upload/corporate/ru-ru/analytics/WebApp-Vulnerabilities-2017-rus.pdf

Инъекции – самый распространённый тип атак (2/2)

84,6%

https://www.ptsecurity.com/upload/corporate/ru-ru/analytics/WebApp-Vulnerabilities-2017-rus.pdf

Слайд 9

Формально об инъекциях

Формально об инъекциях

Слайд 10

01 var a = Request.Params["a"]; 02 03 var b = Request.Params["b"];

01 var a = Request.Params["a"];
02
03 var b = Request.Params["b"];
04 05 if (a

== null)
06 {
07 return;
08 }
09 10 if (b == null)
11 { 12 return; 13 }
14 15 Response.Write($"");

Граница окружения

Модель инъекции (1/7)

Слайд 11

01 var a = Request.Params["a"]; 02 03 var b = Request.Params["b"];

01 var a = Request.Params["a"];
02
03 var b = Request.Params["b"];
04 05 if (a

== null)
06 {
07 return;
08 }
09 10 if (b == null)
11 { 12 return; 13 }
14 15 Response.Write($"");

Точка входа a'

Граница окружения

Модель инъекции (2/7)

Слайд 12

01 var a = Request.Params["a"]; 02 03 var b = Request.Params["b"];

01 var a = Request.Params["a"];
02
03 var b = Request.Params["b"];
04 05 if (a

== null)
06 {
07 return;
08 }
09 10 if (b == null)
11 { 12 return; 13 }
14 15 Response.Write($"");

Точка входа a'

Точка входа b'

Граница окружения

Модель инъекции (3/7)

Слайд 13

Точка выхода c' = ftransform(a', b') 01 var a = Request.Params["a"];

Точка выхода
c' = ftransform(a', b')

01 var a = Request.Params["a"];
02
03 var

b = Request.Params["b"];
04 05 if (a == null)
06 {
07 return;
08 }
09 10 if (b == null)
11 { 12 return; 13 }
14 15 Response.Write($"");

Точка входа a'

Точка входа b'

Граница окружения

Модель инъекции (4/7)

Слайд 14

01 var a = Request.Params["a"]; 02 03 var b = Request.Params["b"];

01 var a = Request.Params["a"];
02
03 var b = Request.Params["b"];
04 05 if (a

== null)
06 {
07 return;
08 }
09 10 if (b == null)
11 { 12 return; 13 }
14 15 Response.Write($"");

Точка входа a'

Точка входа b'

Точка выхода
c' = ftransform(a', b')

Граница окружения

Модель инъекции (5/7)

fpvo(c')

Слайд 15

01 var a = Request.Params["a"]; 02 03 var b = Request.Params["b"];

01 var a = Request.Params["a"];
02
03 var b = Request.Params["b"];
04 05 if (a

== null)
06 {
07 return;
08 }
09 10 if (b == null)
11 { 12 return; 13 }
14 15 Response.Write($"");

Точка входа a'

Точка входа b'

Точка выхода
c' = ftransform(a', b')

Граница окружения

Модель инъекции (6/7)

fpvo(c')

Точка инъекции a'

Слайд 16

01 var a = Request.Params["a"]; 02 03 var b = Request.Params["b"];

01 var a = Request.Params["a"];
02
03 var b = Request.Params["b"];
04 05 if (a

== null)
06 {
07 return;
08 }
09 10 if (b == null)
11 { 12 return; 13 }
14 15 Response.Write($"");

Точка входа a'

Точка входа b'

Точка выхода
c' = ftransform(a', b')

Граница окружения

Модель инъекции (7/7)

fpvo(c')

Точка инъекции a'

Точка инъекции b'

Слайд 17

Приложение защищено от атак инъекций тогда, когда в результате лексического разбора

Приложение защищено от атак инъекций тогда, когда в результате лексического разбора

любого возможного c', количество токенов, приходящихся на точки инъекции, является константой:

2 токена

Достаточный критерий защищённости от атак инъекций

Слайд 18

Приложение защищено от атак инъекций тогда, когда в результате лексического разбора

Приложение защищено от атак инъекций тогда, когда в результате лексического разбора

любого возможного c', множества токенов, приходящихся на точки инъекции, являются авторизованными.

Необходимый критерий защищённости от атак инъекций

Слайд 19

../2/a.jpg 'onerror='…;// '> … Что может атакующий? (1/2)

../2/a.jpg 'onerror='…;// '>

Слайд 20

… 0);… 0)'onload='… 0)'> … Что может атакующий? (2/2)

… 0);… 0)'onload='… 0)'>

Слайд 21

01 var a = Request.Params["a"]; 02 03 var b = Request.Params["b"];

01 var a = Request.Params["a"];
02
03 var b = Request.Params["b"];
04 05 if (a

== null)
06 {
07 return;
08 }
09 10 if (b == null)
11 { 12 return; 13 }
14 15 Response.Write($"");

Ga' = ANY

Граница окружения

Причина инъекции – несогласованность грамматик (1/2)

Ga' = URLname → HTMLattvalue

Слайд 22

01 var a = Request.Params["a"]; 02 03 var b = Request.Params["b"];

01 var a = Request.Params["a"];
02
03 var b = Request.Params["b"];
04 05 if (a

== null)
06 {
07 return;
08 }
09 10 if (b == null)
11 { 12 return; 13 }
14 15 Response.Write($"");

Ga' = ANY

Gb' = ANY

Граница окружения

Причина инъекции – несогласованность грамматик (2/2)

Ga' = URLname → HTMLattvalue

Gb' = JSliteral → HTMLattvalue

Слайд 23

Интерпретируемый код Структурированные данные Код разметки ID внешних ресурсов Любые грамматики,

Интерпретируемый код
Структурированные данные
Код разметки
ID внешних ресурсов
Любые грамматики, с числом токенов >

1

Инъекция возможна в любые нетривиальные грамматики

Слайд 24

Как защититься?

Как защититься?

Слайд 25

Входные данные должны согласовываться с бизнес-логикой приложения за счёт: Типизации Валидации

Входные данные должны согласовываться с бизнес-логикой приложения за счёт:
Типизации
Валидации
Синтаксической
Семантической

Подходы к согласованию

грамматик входных данных
Слайд 26

Типизация – приведение строковых данных к конкретному типу: var typed_url = Url.Parse(Request.Params["url"]) Типизация

Типизация – приведение строковых данных к конкретному типу:
var typed_url = Url.Parse(Request.Params["url"])

Типизация

Слайд 27

Синтаксическая валидация – проверка строковых данных на соответствие какой-либо грамматике: 01

Синтаксическая валидация – проверка строковых данных на соответствие какой-либо грамматике:
01 var

url_regex = 02 "^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?"; 03 04 if (!Regex.IsMatch(Request.Params["url"], url_regex)) 05 { 06 throw new ValidationException(); 07 }

Синтаксическая валидация

Слайд 28

Семантическая валидация – проверка строковых данных на корректность с точки зрения

Семантическая валидация – проверка строковых данных на корректность с точки зрения

логики приложения:
01 var request = WebRequest.Create(Request.Params["url"]) 02 { Method = "HEAD" }; 03 04 if (request.GetResponse().StatusCode != HttpStatusCode.OK) 05 { 06 throw new ValidationException(); 07 }

Семантическая валидация

Слайд 29

Выходные данные должны согласовываться с грамматикой принимающей стороны за счёт санитизации

Выходные данные должны согласовываться с грамматикой принимающей стороны за счёт санитизации

Подходы

к согласованию грамматик выходных данных
Слайд 30

Санитизация – преобразование строковых данных к синтаксису какого-либо токена заданной грамматики

Санитизация – преобразование строковых данных к синтаксису какого-либо токена заданной грамматики
01

var parm_text = Request.Params["parm"]; 02 03 var parm_1 = HtmlEncode(UrlEncode(parm_text)); 04 var parm_2 = HtmlEncode(parm_text); 05 06 Response.Write( 07 $"{parm_2}" 08 );

Санитизация

Слайд 31

В случае вложенных грамматик, например: Gt = JavaScript → HTML, t

В случае вложенных грамматик, например: Gt = JavaScript → HTML, t

∈ De санитизацию необходимо проводить последовательно, в обратном порядке: EncodeHtml(EncodeJavaScript(t)), с учётом синтаксических контекстов обоих грамматик.

Санитизация вложенных грамматик

Слайд 32

Входные данные – как можно ближе к точке их входа, с

Входные данные – как можно ближе к точке их входа, с

учётом:
принципа необходимости и достаточности их грамматик;
приоритетности подходов:
типизация;
семантическая валидация;
синтаксическая валидация.
Выходные данных – как можно ближе к точке их выхода, с учётом:
грамматики принимающей стороны;
возможной вариативности их грамматик в различных точках выполнения;
минимального (в идеале – нулевого) влияния согласования на прочие ветки потока вычисления.

Точки согласования грамматик (1/2)

Слайд 33

Из этих правил есть два исключения: Параметризация (типизация данных в точке

Из этих правил есть два исключения:
Параметризация (типизация данных в точке выхода)
Использование

встраиваемых средств RASP (санитизация и валидация в точке выхода)

Точки согласования грамматик (2/2)

Слайд 34

01 var a = HtmlEncode(UrlEncode(Request.Params["a"])); 02 03 var b = int.Parse(Request.Params["b"]).ToString();

01 var a = HtmlEncode(UrlEncode(Request.Params["a"]));
02
03 var b = int.Parse(Request.Params["b"]).ToString();
04 05 if (a

== null)
06 {
07 return;
08 }
09 10 if (b == null)
11 { 12 return; 13 }
14 15 Response.Write($"");

Ga' = URLname → HTMLattvalue

Граница окружения

Согласованные грамматики (1/2)

Ga' = URLname → HTMLattvalue

Слайд 35

01 var a = HtmlEncode(UrlEncode(Request.Params["a"])); 02 03 var b = int.Parse(Request.Params["b"]).ToString();

01 var a = HtmlEncode(UrlEncode(Request.Params["a"]));
02
03 var b = int.Parse(Request.Params["b"]).ToString();
04 05 if (a

== null)
06 {
07 return;
08 }
09 10 if (b == null)
11 { 12 return; 13 }
14 15 Response.Write($"");

Ga' = URLname → HTMLattvalue

Граница окружения

Согласованные грамматики (1/2)

Ga' = URLname → HTMLattvalue

Gb' = Literalinteger

Gb' = JSliteral → HTMLattvalue

Слайд 36

А если бы существовала библиотека, принимающая на себя всю рутину по

А если бы существовала библиотека, принимающая на себя всю рутину по

защите приложения от атак инъекций?

Мечтать – не вредно (1/2)

Слайд 37

01 Response.Write( 02 SafeFormat.Html( 03 $" " 04 )); Например, вот так? (2/2)


01 Response.Write(
02 SafeFormat.Html(
03 $""
04 ));

Например, вот так? (2/2)

Слайд 38

Как протестировать?

Как протестировать?

Слайд 39

Векторы от пентестеров и багхантеров – не использовать! http://host/entry_point/?name=%2f..%2fWeb.Config File.Delete($"\\temp_data\\{name}"); Использовать

Векторы от пентестеров и багхантеров – не использовать!
http://host/entry_point/?name=%2f..%2fWeb.Config
File.Delete($"\\temp_data\\{name}");
Использовать набор векторов атаки,

приводящих к ошибке парсинга:
"\..\filename?", “" и т.п.
Каждый вектор – отдельный тест-кейс на отсутствие исключений при передаче модулю в качестве входных данных

Подход на базе ошибок разбора

Слайд 40

Используется любой набор векторов атаки и токенизатор соответствующей грамматики Перед каждой

Используется любой набор векторов атаки и токенизатор соответствующей грамматики
Перед каждой PVF

устанавливается утверждение на количество токенов в её аргументе:
01 var pvfArgument = $"\\temp_data\\{name}";
02 Debug.Assert(Tokenize(pvfArgument).Count() == 4);
03 File.Delete(pvfArgument);
Каждый вектор – тест-кейс на отсутствие нарушения утверждений.

Подход на базе токенизации

Слайд 41

А если бы существовала библиотека, принимающая на себя всю рутину по

А если бы существовала библиотека, принимающая на себя всю рутину по

тестированию защищённости от атак инъекций ?

Мечтать – не вредно (2/2)

Слайд 42

01 var pvfArgument = $"\\temp_data\\{name}"; 02 DebugFormat.Path(pvfArgument); 03 File.Delete(pvfArgument); Например, вот так? (1/2)

01 var pvfArgument = $"\\temp_data\\{name}";
02 DebugFormat.Path(pvfArgument);
03 File.Delete(pvfArgument);

Например, вот так? (1/2)

Слайд 43

LibProtection

LibProtection

Слайд 44

LibProtection – библиотека с открытым кодом (под MIT-лицензией), позволяющая разработчикам встраивать

LibProtection – библиотека с открытым кодом (под MIT-лицензией), позволяющая разработчикам встраивать

в приложение автоматизированную защиту от атак инъекций.

Что такое LibProtection? (1/4)

Слайд 45

Для защиты от атак в LibProtection реализованы: автоматическая санитизация входных данных

Для защиты от атак в LibProtection реализованы:
автоматическая санитизация входных данных там,

где это возможно;
автоматическая валидация входных данных относительно выходной грамматики (детектирование атаки) там, где невозможна санитизация.

Что такое LibProtection? (2/4)

Слайд 46

Детектирование осуществляется по формальным признакам: факт атаки не предполагается, а доказывается. Что такое LibProtection? (3/4)

Детектирование осуществляется по формальным признакам: факт атаки не предполагается, а доказывается.

Что

такое LibProtection? (3/4)
Слайд 47

Поддерживаемые языки: .NET, C++ (Q4 2017) PHP, JVM (H1 2018) Python,

Поддерживаемые языки:
.NET, C++ (Q4 2017)
PHP, JVM (H1 2018)
Python, Ruby (H2 2018)
Поддерживаемые

грамматики: SQL (Microsoft SQL Server, Oracle, Database, Oracle MySQL), HTML, EcmaScript, CSS, URL, Path, XML

Что такое LibProtection? (4/4)

Слайд 48

01 Response.Write( 02 SafeFormat.Html( 03 $" " 04 )); Защита от инъекций с помощью LibProtection


01 Response.Write(
02 SafeFormat.Html(
03 $""
04 ));

Защита от инъекций с помощью

LibProtection
Слайд 49

Как это работает? (1/10) 'onerror='…;// 0

Как это работает? (1/10)

'onerror='…;// 0

Слайд 50

Как это работает? (2/10) 'onerror='…;// 0

Как это работает? (2/10)

'onerror='…;// 0


Слайд 51

Как это работает? (3/10) 'onerror='…;// 0

Как это работает? (3/10)

'onerror='…;// 0


= '//host/1/' onerror = '…;//.jpg' onclick = 'f(0)' />
Слайд 52

Как это работает? (4/10) 'onerror='…;// 0 4 (атака) 1 (ок)

Как это работает? (4/10)

'onerror='…;// 0


= '//host/1/' onerror = '…;//.jpg' onclick = 'f(0)' />
4 (атака) 1 (ок)
Слайд 53

Как это работает? (5/10) 4 (атака)

Как это работает? (5/10)

= 'f(0)' />
4 (атака)
Слайд 54

Как это работает? (6/10) 4 (атака) Ga1 = URL/HTML

Как это работает? (6/10)

= 'f(0)' />
4 (атака)
Ga1 = URL/HTML
Слайд 55

Как это работает? (7/10) 4 (атака) Ga1 = URL/HTML WU.HtmlEncode(WU.UrlEncode("'onerror='…;//"))

Как это работает? (7/10)

= 'f(0)' />
4 (атака)
Ga1 = URL/HTML
WU.HtmlEncode(WU.UrlEncode("'onerror='…;//"))
Слайд 56

Как это работает? (8/10) 4 (атака) Ga1 = URL/HTML WU.HtmlEncode(WU.UrlEncode("'onerror='…;//"))

Как это работает? (8/10)

= 'f(0)' />
4 (атака)
Ga1 = URL/HTML
WU.HtmlEncode(WU.UrlEncode("'onerror='…;//"))

Слайд 57

Как это работает? (9/10) 4 (атака) Ga1 = URL/HTML WU.HtmlEncode(WU.UrlEncode("'onerror='…;//"))

Как это работает? (9/10)

= 'f(0)' />
4 (атака)
Ga1 = URL/HTML
WU.HtmlEncode(WU.UrlEncode("'onerror='…;//"))


Слайд 58

Как это работает? (10/10) 4 (атака) Ga1 = URL/HTML WU.HtmlEncode(WU.UrlEncode("'onerror='…;//")) OK!

Как это работает? (10/10)

= 'f(0)' />
4 (атака)
Ga1 = URL/HTML
WU.HtmlEncode(WU.UrlEncode("'onerror='…;//"))


OK!
Слайд 59

// Grammar ∈ { Sql, Html, EcmaScript, Css, Url, Path, Xml

// Grammar ∈ { Sql, Html, EcmaScript, Css, Url, Path, Xml

}
string SafeFormat.Grammar(FormattableString formattable) string SafeFormat.Grammar(string format, params object[] args)
bool TrySafeFormat.Grammar(FormattableString formattable, out formatted) bool TrySafeFormat.Grammar(string format, out formatted, params object[] args)
string DebugFormat.Grammar(FormattableString formattable) string DebugFormat.Grammar(string format, params object[] args)

LibProtection API: методы

Слайд 60

По умолчанию, LibProtection рассматривает все переменные, как опасные значения. Это поведение

По умолчанию, LibProtection рассматривает все переменные, как опасные значения. Это поведение

можно переопределить с помощью форматных модификаторов:
:safe
:validate(method-name) method-name ∈ Func
:sanitize(method-name) method-name ∈ Func

LibProtection API: форматные модификаторы