Философия Application Security

Preview:

Citation preview

Философия Application Security

Владимир Кочетков/Positive Technologies/Application Inspector/Team Lead

CodeFreeze в Москве, 28.04.2016

3

:~$ whoami && whonotme• .NET-разработчик, руководитель группы разработки

анализаторов компилируемых приложений в Positive Technologies

• Участник Positive Development User Group

• Исследователь в области защищенности приложений

• Участник RSDN

• Оторванный от реальности теоретик

• Упоротый параноик

4

Ништяки

5

WTF “AppSec”?Application Security – предметная область обеспечения защищенности приложений на этапах:

― проектирования;

― разработки;

― развертывания;

― эксплуатации;

6

WTF “AppSec”?Application Security – предметная область обеспечения защищенности приложений на этапах:

― проектирования;

― разработки;

― развертывания;

― эксплуатации;

сегодняшняя тема

7

Agenda (чего НЕ будет)

8

Вопрос: почему квалифицированные разработчики допускают уязвимости?

9

Причины разработки уязвимого кода

― Низкая квалификация

― Человеческий фактор

― Отсутствие системного подхода

― Шаблонное мышление

10

AgendaЧто?

Теоретический минимум, необходимый для осознанной разработки защищенного кода;

разбор известных уязвимостей.

Зачем?Перестать следовать культу карго и шаблонному подходу к вопросам обеспечения защищенности.

11

Главный вопрос Жизни, Вселенной и всего остального…

12

…что такое "уязвимость"?

13

Что такое "уязвимость"?«Недостаток (слабость) программного (программно-технического) обеспечения средства или информационной системы в целом, который (которая) может быть использована для реализации угроз безопасности информации» - ГОСТ Р 56546-2015

14

Что такое "уязвимость"?«Недостаток (слабость) программного (программно-технического) обеспечения средства или информационной системы в целом, который (которая) может быть использована для реализации угроз безопасности информации» - ГОСТ Р 56546-2015 «В чем сила, брат?» (с)

15

Что такое "уязвимость"?«Недостаток (слабость) программного (программно-технического) обеспечения средства или информационной системы в целом, который (которая) может быть использована для реализации угроз безопасности информации» - ГОСТ Р 56546-2015 «В чем сила, брат?» (с)

«Набор входных данных, приводящий машину Тьюринга в запрещенную конфигурацию» - Theoretical Computer Science

16

Что такое "уязвимость"?«Недостаток (слабость) программного (программно-технического) обеспечения средства или информационной системы в целом, который (которая) может быть использована для реализации угроз безопасности информации» - ГОСТ Р 56546-2015 «В чем сила, брат?» (с)

«Набор входных данных, приводящий машину Тьюринга в запрещенную конфигурацию» - Theoretical Computer Science

17

Существующие определения не дают ни малейшего представления о технической сущности уязвимости

18

Правильный вопрос: в чем разница между защищенным и уязвимым кодом?

19

Внимание, белый ящик!var cmd = new SqlCommand("SELECT Value FROM Discounts WHERE CouponCode LIKE '" + Request["CouponCode"] + "'");var connection = new SqlConnection(connectionString);connection.Open();cmd.Connection = connection;var couponValue = cmd.ExecuteScalar();...

20

Внимание, белый ящик!var cmd = new SqlCommand("SELECT Value FROM Discounts WHERE CouponCode LIKE '" + Request["CouponCode"] + "'");var connection = new SqlConnection(connectionString);connection.Open();cmd.Connection = connection;var couponValue = cmd.ExecuteScalar();...

Атакующий имеет возможность нарушить целостность выходного потока данных (кода SQL-запроса), манипулируя потоком входных данных (параметром HTTP-запроса), приходящим в операцию выполнения SQL-кода.

21

Шаблон: чтобы избежать уязвимости к SQL-инъекции необходимо использовать параметризацию запросов

22

Внимание, белый ящик!var cmd = new SqlCommand("SELECT Value FROM Discounts WHERE CouponCode LIKE @CouponCode");cmd.Parameters.AddWithValue("@CouponCode ", Request["CouponCode"]);var connection = new SqlConnection(connectionString);connection.Open();cmd.Connection = connection;var couponValue = cmd.ExecuteScalar();...

23

Внимание, белый ящик!var cmd = new SqlCommand("SELECT Value FROM Discounts WHERE CouponCode LIKE @CouponCode");cmd.Parameters.AddWithValue("@CouponCode ", Request["CouponCode"]);var connection = new SqlConnection(connectionString);connection.Open();cmd.Connection = connection;var couponValue = cmd.ExecuteScalar();...

Атакующий имеет возможность нарушить целостность выходного потока данных (параметра SQL-запроса), манипулируя потоком входных данных (параметром HTTP-запроса), приходящим в операцию выполнения SQL-кода, что может привести к нарушению правил предметной области приложения.

24

Внимание, белый ящик!var fieldName = Request["field"] ?? "Id"; var minValue = int.Parse(Request["min"] ?? "0"); var maxValue = int.Parse(Request["max"] ?? "0");

var queryTemplate = string.Format( "SELECT Id, Nickname, Rating, MessageCount, TopicCount FROM Users WHERE {0} >= @minValue AND {0} <= @maxValue ORDER BY {0}", fieldName.Replace("'", string.Empty). Replace(" ", string.Empty). Replace("\\", string.Empty). Replace(",", string.Empty). Replace("(", string.Empty). Replace(")", string.Empty),);

var selectCommand = string.Format(queryTemplate, debugStr);

var cmd = new SqlCommand(selectCommand, dataConnection);

cmd.Parameters.Add(new SqlParameter("@minValue", minValue));cmd.Parameters.Add(new SqlParameter("@maxValue", maxValue));

/users/filter.aspx?field={fieldName}&min={minBalue}&max={maxValue}

Users

Id

Nickname

Rating

MessageCount

TopicCountPassword

25

Внимание, белый ящик!var fieldName = Request["field"] ?? "Id"; var minValue = int.Parse(Request["min"] ?? "0"); var maxValue = int.Parse(Request["max"] ?? "0");

var queryTemplate = string.Format( "SELECT Id, Nickname, Rating, MessageCount, TopicCount FROM Users WHERE {0} >= @minValue AND {0} <= @maxValue ORDER BY {0}", fieldName.Replace("'", string.Empty). Replace(" ", string.Empty). Replace("\\", string.Empty). Replace(",", string.Empty). Replace("(", string.Empty). Replace(")", string.Empty),);

var selectCommand = string.Format(queryTemplate, debugStr);

var cmd = new SqlCommand(selectCommand, dataConnection);

cmd.Parameters.Add(new SqlParameter("@minValue", minValue));cmd.Parameters.Add(new SqlParameter("@maxValue", maxValue));

/users/filter.aspx?field=password&min=a&max=a

Users

Id

Nickname

Rating

MessageCount

TopicCountPassword

26

Внимание, белый ящик!var fieldName = Request["field"] ?? "Id"; var minValue = int.Parse(Request["min"] ?? "0"); var maxValue = int.Parse(Request["max"] ?? "0");

var queryTemplate = string.Format( "SELECT Id, Nickname, Rating, MessageCount, TopicCount FROM Users WHERE {0} >= @minValue AND {0} <= @maxValue ORDER BY {0}", fieldName.Replace("'", string.Empty). Replace(" ", string.Empty). Replace("\\", string.Empty). Replace(",", string.Empty). Replace("(", string.Empty). Replace(")", string.Empty),);

var selectCommand = string.Format(queryTemplate, debugStr);

var cmd = new SqlCommand(selectCommand, dataConnection);

cmd.Parameters.Add(new SqlParameter("@minValue", minValue));cmd.Parameters.Add(new SqlParameter("@maxValue", maxValue));

/users/filter.aspx?field=password&min=a&max=a

Users

Id

Nickname

Rating

MessageCount

TopicCountPassword

Атакующий имеет возможность нарушить конфиденциальность хранящегося потока данных, манипулируя потоком входных данных (параметром HTTP-запроса), приводящим к нарушению правил предметной области приложения.

27

Какой из фрагментов кода уязвим?1)

[Authorize(Roles = "Foo")]public ActionResult SomeAction(){ ... return View();}

2)

[Authorize(Roles = "Bar, Qux")]public ActionResult SomeAction(){ ... return View();}

28

Какой из фрагментов кода уязвим?1)

[Authorize(Roles = "Foo")]public ActionResult SomeAction(){ ... return View();}

2)

[Authorize(Roles = "Bar, Qux")]public ActionResult SomeAction(){ ... return View();}

Невозможно оценить защищенность кода, не владея всеми предметными областями приложения (в данном случае, правилами предметной области контроля доступа).

29

Критерии уязвимости кода определяются множеством предметных областей приложения

Предметные областиВторостепенные:

― защищенность;― отказоустойчивость;― опыт взаимодействия,― производительность.

Основные:

― интернет-торговля;― онлайн-банкинг;― бухучет;― … (тысячи их).

Каждое приложение реализует модели как основной предметной области, так и множество моделей второстепенных предметных областей

31

Application Security – второстепенная предметная область

32

{Предметная область} Application Security

33

Предметная область – множество сущностей, их инвариантов и отношений

34

Сущность– абстракция объекта в некотором контексте, обладающая следующими характеристиками:

• свойство – значимый атрибут абстрагируемого сущностью объекта;

• состояние– множество текущих значений всех свойств сущности;

• инвариант– множество допустимых состояний сущности.

Отношение – утверждение, определяющее взаимосвязь изменения состояний сущностей.

35

Пример: логистикаСущность: точки на карте города

• свойство: координаты – пара значений «широта-долгота»;• инвариант: координаты принадлежат перекресткам города или

строениям.

Сущность: маршрут• свойство: путь - упорядоченное множество точек на карте города;• инвариант: путь непрерывен, проходит по улицам города в

соответствии с ПДД;• отношение: оптимальность – длина пути минимальна для заданных

начальной и конечной точек.

Сущности: точка загрузки, точка доставки• свойство: точка на карте города;• инвариант: координаты принадлежат строениям.

36

Задача коммивояжёраВ терминах предметной области логистики:

построить оптимальный маршрут из точки загрузки, проходящий через все точки доставки по одному разу и возвращающийся в точку загрузки.

37

Задача коммивояжёраВ терминах предметной области логистики:

построить оптимальный маршрут из точки загрузки, проходящий через все точки доставки по одному разу и возвращающийся в точку загрузки.

В терминах предметной области теории графов:

Найти гамильтонов цикл минимального веса в полном (дополненном ребрами бесконечной длины) взвешенном графе.

38

goto fail;

39

Место действия: SSL/TLS библиотека SecureTransport -> sslKeyExchange.c

40

Процесс согласования соединения SSL/TLSSSLProcessHandshakeRecord() -> SSLProcessHandshakeMessage() -> SSLProcessClientHello() -> SSLProcessServerHello() -> SSLProcessCertificate() -> SSLProcessServerKeyExchange() -> SSLDecodeSignedServerKeyExchange() -> SSLDecodeXXKeyParams() IF TLS 1.2 -> SSLVerifySignedServerKeyExchangeTls12() OTHERWISE -> SSLVerifySignedServerKeyExchange()

41

sslKeyExchange.c:SSLVerifySignedServerKeyExchange. . .hashOut.data = hashes + SSL_MD5_DIGEST_LEN;hashOut.length = SSL_SHA1_DIGEST_LEN;if ((err = SSLFreeBuffer(&hashCtx)) != 0) goto fail;if ((err = ReadyHash(&SSLHashSHA1, &hashCtx)) != 0) goto fail;if ((err = SSLHashSHA1.update(&hashCtx, &clientRandom)) != 0) goto fail;if ((err = SSLHashSHA1.update(&hashCtx, &serverRandom)) != 0) goto fail;if ((err = SSLHashSHA1.update(&hashCtx, &signedParams)) != 0) goto fail; goto fail;if ((err = SSLHashSHA1.final(&hashCtx, &hashOut)) != 0) goto fail;

err = sslRawVerify(...);. . .fail:. . .

42

Лишний безусловный переход на метку `fail` приводил к нарушению правил предметной области протокола SSL/TLS

43

Предметная область {Application} Security

44

«Трясина Тьюринга» - не только об эзотерических языках

45

Применимость теоремы Райса к реальным системам – такая же теоретизация, как и идея описывать приложение в виде конечного автомата

46

Приложение можно рассматривать, как поток управления, обрабатывающий множество потоков данных

47

Потоки управленияvar name = Request.Params["name"];var key1 = Request.Params["key1"];var parm = Request.Params["parm"];

var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);

string str1;if (name + "in" == "admin"){ if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; }

Response.Write(str1);}

48

Потоки управленияvar name = Request.Params["name"];var key1 = Request.Params["key1"];var parm = Request.Params["parm"];

var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);

string str1;if (name + "in" == "admin"){ if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; }

Response.Write(str1);}

49

Потоки управленияvar name = Request.Params["name"];var key1 = Request.Params["key1"];var parm = Request.Params["parm"];

var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);

string str1;if (name + "in" == "admin"){ if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; }

Response.Write(str1);}

50

Потоки управленияvar name = Request.Params["name"];var key1 = Request.Params["key1"];var parm = Request.Params["parm"];

var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);

string str1;if (name + "in" == "admin"){ if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; }

Response.Write(str1);}

51

Потоки управленияvar name = Request.Params["name"];var key1 = Request.Params["key1"];var parm = Request.Params["parm"];

var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);

string str1;if (name + "in" == "admin"){ if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; }

Response.Write(str1);}

52

Потоки управленияvar name = Request.Params["name"];var key1 = Request.Params["key1"];var parm = Request.Params["parm"];

var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);

string str1;if (name + "in" == "admin"){ if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; }

Response.Write(str1);}

53

Потоки управленияvar name = Request.Params["name"];var key1 = Request.Params["key1"];var parm = Request.Params["parm"];

var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);

string str1;if (name + "in" == "admin"){ if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; }

Response.Write(str1);}

54

Потоки управленияvar name = Request.Params["name"];var key1 = Request.Params["key1"];var parm = Request.Params["parm"];

var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);

string str1;if (name + "in" == "admin"){ if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; }

Response.Write(str1);}

55

Потоки управленияvar name = Request.Params["name"];var key1 = Request.Params["key1"];var parm = Request.Params["parm"];

var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);

string str1;if (name + "in" == "admin"){ if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; }

Response.Write(str1);}

56

Потоки управленияvar name = Request.Params["name"];var key1 = Request.Params["key1"];var parm = Request.Params["parm"];

var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);

string str1;if (name + "in" == "admin"){ if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; }

Response.Write(str1);}

57

Потоки управленияvar name = Request.Params["name"];var key1 = Request.Params["key1"];var parm = Request.Params["parm"];

var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);

string str1;if (name + "in" == "admin"){ if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; }

Response.Write(str1);}

58

Потоки управленияvar name = Request.Params["name"];var key1 = Request.Params["key1"];var parm = Request.Params["parm"];

var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);

string str1;if (name + "in" == "admin"){ if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; }

Response.Write(str1);}

59

Потоки управленияvar name = Request.Params["name"];var key1 = Request.Params["key1"];var parm = Request.Params["parm"];

var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);

string str1;if (name + "in" == "admin"){ if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; }

Response.Write(str1);}

60

Потоки управленияvar name = Request.Params["name"];var key1 = Request.Params["key1"];var parm = Request.Params["parm"];

var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);

string str1;if (name + "in" == "admin"){ if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; }

Response.Write(str1);}

61

Потоки управленияvar name = Request.Params["name"];var key1 = Request.Params["key1"];var parm = Request.Params["parm"];

var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);

string str1;if (name + "in" == "admin"){ if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; }

Response.Write(str1);}

62

Потоки управления всегда являются производными от потоков данных

63

Heartbleed

64

Место действия: библиотека OpenSSL -> ssl/t1_lib.c -> tls1_process_heartbeat()

65

tls1_process_heartbeat()3972 /* Read type and payload length first */3973 hbtype = *p++;3974 n2s(p, payload);3975 pl = p;. . .3984 unsigned char *buffer, *bp;3985 int r;3986 3987 /* Allocate memory for the response, size is 1 bytes3988 * message type, plus 2 bytes payload length, plus3989 * payload, plus padding3990 */3991 buffer = OPENSSL_malloc(1 + 2 + payload + padding);3992 bp = buffer;. . .3994 /* Enter response type, length and copy payload */3995 *bp++ = TLS1_HB_RESPONSE;3996 s2n(payload, bp);3997 memcpy(bp, pl, payload);

66

Атакующий имел возможность, манипулируя потоком входных данных, нарушить целостность выходного потока данных …

67

…, включая в него содержимое до 64Kb кучи SSL-сервера непосредственно за payload

68

69

Потоки данныхvar name = Request.Params["name"];var key1 = Request.Params["key1"];var parm = Request.Params["parm"];

var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);

string str1;if (name + "in" == "admin"){ if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; }

Response.Write(str1);}

70

Потоки данныхvar name = Request.Params["name"];var key1 = Request.Params["key1"];var parm = Request.Params["parm"];

var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);

string str1;if (name + "in" == "admin"){ if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; }

Response.Write(str1);}

71

Потоки данныхvar name = Request.Params["name"];var key1 = Request.Params["key1"];var parm = Request.Params["parm"];

var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);

string str1;if (name + "in" == "admin"){ if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; }

Response.Write(str1);}

72

Потоки данныхvar name = Request.Params["name"];var key1 = Request.Params["key1"];var parm = Request.Params["parm"];

var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);

string str1;if (name + "in" == "admin"){ if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; }

Response.Write(str1);}

73

Потоки данныхvar name = Request.Params["name"];var key1 = Request.Params["key1"];var parm = Request.Params["parm"];

var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);

string str1;if (name + "in" == "admin"){ if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; }

Response.Write(str1);}

74

Потоки данныхvar name = Request.Params["name"];var key1 = Request.Params["key1"];var parm = Request.Params["parm"];

var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);

string str1;if (name + "in" == "admin"){ if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; }

Response.Write(str1);}

75

Потоки данныхvar name = Request.Params["name"];var key1 = Request.Params["key1"];var parm = Request.Params["parm"];

var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);

string str1;if (name + "in" == "admin"){ if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; }

Response.Write(str1);}

76

Потоки данныхvar name = Request.Params["name"];var key1 = Request.Params["key1"];var parm = Request.Params["parm"];

var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);

string str1;if (name + "in" == "admin"){ if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; }

Response.Write(str1);}

77

Потоки данныхvar name = Request.Params["name"];var key1 = Request.Params["key1"];var parm = Request.Params["parm"];

var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);

string str1;if (name + "in" == "admin"){ if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; }

Response.Write(str1);}

78

Потоки данныхvar name = Request.Params["name"];var key1 = Request.Params["key1"];var parm = Request.Params["parm"];

var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);

string str1;if (name + "in" == "admin"){ if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; }

Response.Write(str1);}

79

Потоки данныхvar name = Request.Params["name"];var key1 = Request.Params["key1"];var parm = Request.Params["parm"];

var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);

string str1;if (name + "in" == "admin"){ if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; }

Response.Write(str1);}

str1 ∈ {Encoding.UTF8.GetString(Convert.FromBse64String(Request.Params["parm"])),"Wrong Key!"}

80

Множества значений всех потоков данных в конкретной точке потока выполнения определяют состояние приложения

81

Граф переходов между состояниями приложения определяет все возможные потоки вычисления

82

Граф потоков вычисления является семантически-эквивалентной моделью приложения

83

Предметная область Application {Security}

84

Театр начинается с вешалки, а уязвимость – с недостатка

85

Недостаток- неэффективная реализация моделей предметных областей приложения и контролей инвариантов их сущностей

Примеры контролей Application Security:

• предварительная обработка потоков данных;• подтверждение аутентичности потоков вычисления;• проверка прав доступа к потокам данных;• обеспечение соответствия потока вычисления модели

функциональной предметной области;• …

86

Угроза- обусловленная недостатком возможность нарушить состояние защищенности потока вычисления, лишив его одного из свойств:

• конфиденциальности;• целостности;• доступности;• авторизованности;• аутентичности;• аппелируемости;• подотчетности;• достоверности;• <нужное вписать>

87

КонфиденциальностьСвойство-состояния потока вычисления, при котором доступ к нему осуществляется только сущностями, имеющими на это право.

88

ЦелостностьСвойство-состояние потока вычисления, при котором изменения в нем осуществляются только сущностями, имеющими на это право.

89

ДоступностьСвойство-состояние потока вычисления, при котором доступ к нему могут осуществить все сущности, имеющие на это право.

90

АвторизованностьСвойство-состояние потока вычисления, при котором его источниками являются только сущности, имеющие на это право.

91

АутентичностьСвойство-состояние потока вычисления, при котором подтверждена подлинность его источника.

92

АппелируемостьСвойство-состояние потока вычисления, при котором его источник не может отказаться от того, что он является таковым.

93

Уязвимость – состояние приложения, в котором возможна реализация угрозы

94

Невозможность реализации угрозы в каждой точке потока вычисления* является инвариантом защищенности приложения

* …пересекающего границу доверия

95

Уязвимость бизнес-логики–состояние реализации угрозы через нарушение правил основной предметной области приложения

96

То, что может сделать с потоками вычисления атакующий, нарушив инварианты сущностей предметных областей, называется угрозой (threat)

То, где и благодаря чему он может это сделать, называется уязвимостью (vulnerability), обусловленной недостатком (weakness)

То, как он может это сделать, называется атакой (attack)

То, с какой вероятностью у него это удастся и какие последствия может повлечь, называется риском (risk)

Иными словами…

97

То, что не позволяет атакующему провести атаку, обеспечивает защищенность (security)

98

То, что минимизирует риск, обеспечивает безопасность (safety)

99

Акцентировать внимание необходимо на причинах*, а не на следствиях**!

* недостатки** уязвимости, атаки или риски

100

Причинно-следственные связи

Недостаток Угроза

Уязвимость Атака

Риск

Незащищенность

Небезопасность

101

Промежуточные итогиРазработка защищенного кода сводится к реализации контроля инвариантов всех сущностей основной предметной области и области защищенности приложения

Анализ защищенности кода сводится к оценке эффективности реализованных контролей

Ни то, ни другое – невозможно без досконального изучения основной предметной области и области защищенности приложения

КлассификацияКлассификация уязвимостей возможна по:

― предметной области; // защищенность приложения― недостатку; // неэффективная предварительная

обработка потоков данных― потоку вычисления; // интерпретация потока данных в

поток выполнения― угрозе; // нарушение целостности

// уязвимость к атакам инъекций (в зависимости от интерпретатора потока данных: XSS, SQLi, XMLi, XPATHi, Path Traversal, LINQi, XXE и т.п.)

103

Формальные признаки уязвимостей к инъекциямДано: потенциально уязвимая операция (точка потока выполнения) PVO(text): операция прямой или косвенной интерпретации текста text на формальном языке.

Пусть text = transform(argument), где argument – поток данных множества аргументов точки входа EP, а transform – функция промежуточных преобразований.

Тогда приложение уязвимо к атаке инъекции в точке PVO, если существует и достижимо хотя бы одно множество vector таких значений элементов EP, при которых происходит изменение структуры синтаксического дерева текста text, не предусмотренное правилами прочих предметных областей приложения.

104

Для защиты от атак инъекций в любой язык необходимо и достаточно обеспечить для transform инвариант «vector – пустое множество»

105

Shellshock

106

Место действия: интерпретатор BASH

107

BASH использует окружение и для хранения переменных состояния, и для передачи дочерним процессам текущих определений функций

108

env var_fn='() { <your function> }'

109

Ошибка разбора и импорта определения функции приводила к выполнению кода, следующего за определением функции прямо во время импорта

110

env var_fn='() { <your function> }; <attacker code here>'

111

Переменные состояния часто являются производными потоков входных данных

112

env var_fn='() { ignore this;}; echo vulnerable' bash -c /bin/true

113

Проще перечислить, какие системы/сервисы не были подвержены Shellshock

КлассификацияКлассификация уязвимостей возможна по:

― предметной области; // защищенность приложения― недостатку; // неэффективное подтверждение

аутентичности источника потока вычисления― потоку вычисления; // интерпретация HTTP-запроса,

приводящего к изменению состояния приложения― угрозе; // нарушение аутентичности

// уязвимость к атакам CSRF

КлассификацияКлассификация уязвимостей возможна по:

― предметной области; // онлайн-торговля― недостатку; // неэффективный контроль

использования погашенных купонов на скидку― потоку вычисления; // транзакция оплаты заказа― угрозе; // нарушение авторизованности

// уязвимость к атакам на бизнес-логику (повторное использование купонов на скидку)

КлассификацияКлассификация уязвимостей возможна по:

― предметной области; // защищенность приложения― недостатку; // неэффективный контроль операций

прямой записи пользовательских потоков данных или их производных в память

― потоку вычисления; // интерпретация внутренних данных на стеке или куче

― угрозе; // нарушение целостности

// уязвимость к атакам переполнения буфера

117

GHOST

118

Место действия: GNU C Library (glibc) -> nss/digits_dots.c -> __nss_hostname_digits_dots()

119

nss/digits_dots.c 36 __nss_hostname_digits_dots (const char *name, struct hostent *resbuf, 37 char **buffer, size_t *buffer_size, 38 size_t buflen, struct hostent **result, 39 enum nss_status *status, int af, int *h_errnop). . . 85 size_needed = (sizeof (*host_addr) 86 + sizeof (*h_addr_ptrs) + strlen (name) + 1);. . .101 *buffer_size = size_needed;102 new_buf = (char *) realloc (*buffer, *buffer_size);. . .121 host_addr = (host_addr_t *) *buffer;122 h_addr_ptrs = (host_addr_list_t *)123 ((char *) host_addr + sizeof (*host_addr));124 h_alias_ptr = (char **) ((char *) h_addr_ptrs + sizeof (*h_addr_ptrs));125 hostname = (char *) h_alias_ptr + sizeof (*h_alias_ptr);. . .157 resbuf->h_name = strcpy (hostname, name);

120

Манипулируя потоком входных данных, атакующий имел возможность нарушить целостность потоков данных на стеке или в куче приложения

121

Дополнительные условия― hostname должен состоять из цифр и точек;

― первый символ hostname должен быть цифрой;

― последний символ hostname не должен быть точкой;

― hostname должен быть достаточной длины, чтобы вызвать переполнение;

― hostname должен успешно разбираться как IPv4 адрес функцией inet_aton();

122

С учетом всех ограничений, был разработан экплоит, для Exim, позволяющий обойти механизмы защиты ASLR и PIE и выполнить произвольный код в системе https://www.qualys.com/2015/01/27/cve-2015-0235/exim_ghost_bof.rb

123

Резюмируя: как разрабатывать защищенные приложения, не сходя при этом с ума?

124

125

Перестать следовать шаблонам

Обеспечить адекватный контроль всех инвариантов Application Security и предметной области приложения

Вопросы?

Владимир Кочетков

vkochetkov@ptsecurity.com@kochetkov_v

/Positive Technologies/Application Inspector/Team Lead

Recommended