Upgrade to Pro — share decks privately, control downloads, hide ads and more …

LibProtection: побеждая инъекции

LibProtection: побеждая инъекции

Слайды вебинара цикла "Практическая безопасность"

Vladimir Kochetkov

December 14, 2017
Tweet

More Decks by Vladimir Kochetkov

Other Decks in Programming

Transcript

  1. :~$ whoami Владимир Кочетков • Руководитель отдела исследований по анализу

    защищённости приложений Positive Technologies • Appsec- и CS-исследователь (формальные методы анализа и защиты приложений) • Организатор Positive Development User Group Контакты: about.me/vladimir.kochetkov [email protected]
  2. 3 Открытое сообщество разработчиков и IT- специалистов, которые стремятся создавать

    безопасные приложения Чат в Телеграме: https://t.me/ru_appsec Присоединяйтесь! Positive Development User Group
  3. Заголовок ptsecurity.com approof.ptsecurity.com github.com/libprotection LibProtection • Анализатор защищённости веб-приложений .NET,

    Java, PHP • Анализ конфигурации и уязвимых компонентов • Сигнатурный статический анализ • Поиск веб-шеллов и вредоносных сценариев • Сбор статистики по проекту • Альтернативная реализация форматных и интерполированных строк, встраивающих в приложение автоматическую защиту от атак инъекций • .NET 4.0+ (скоро: Kotlin, C++, Python, PHP, JavaScript) • SQL, HTML, JavaScript, URL и файловые пути (скоро: XML, CSS, XPATH, CMD, BASH)
  4. 5 «Параметризация и объектный подход решают!» «…не рассказал как правильно

    делать, а просто рассказывал про то, как костылями можно дырки закрывать» «…был задан правильный вопрос про то, что многие так уже не пишут, а используют объектный подход. Каких атак тогда опасаться?» Мифы об инъекциях (1/3)
  5. 6 • Интерпретируемый код • Структурированные данные • Код разметки

    • ID внешних ресурсов • Любые грамматики, с числом токенов > 1 Кто сказал, что речь только об SQL и HTML?
  6. 7 «ТАК уже давно никто не пишет!» «…достаточно банальные примеры,

    которые были бы актуальны несколько лет назад» «…в целом доклад теряет свой смысл, если код написан без использования устаревших подходов» «…[LibProtection] скорее для компаний, которые не заботятся о коде, живут в легаси- системах и не знают, что после .NET 2.0 выходили более новые версии, а .NET Core для них просто ругательство» Мифы об инъекциях (2/3)
  7. 8 Что же тогда атаковали хакеры в Q2.2017 (1/2) Статистика

    атак на веб-приложения II квартал 2017 года: ptsecurity.com/upload/corporate/ru-ru/analytics/WebApp-Vulnerabilities-2017-rus.pdf
  8. 9 Что же тогда атаковали хакеры в Q2.2017 (2/2) 84,6%

    Статистика атак на веб-приложения II квартал 2017 года: ptsecurity.com/upload/corporate/ru-ru/analytics/WebApp-Vulnerabilities-2017-rus.pdf
  9. 11 • Загрузка WSDL сервиса • Генерация исходного кода прокси

    (PrintClientProxy) • Компиляция прокси с помощью CSC • Создание экземпляра прокси и взаимодействие с ним Обработка связей с веб-сервисами в MS Office
  10. 12 01 sb.Length = 0; 02 sb.Append(indent2); 03 if (i

    == 0) 04 { 05 sb.Append("base.ConfigureProxy(this.GetType(), "); 06 sb.Append(WsdlParser.IsValidUrl((string)_connectURLs[i])); 07 sb.Append(");"); 08 } 09 else 10 { 11 // Only the first location is used, the rest are commented out in the proxy 12 sb.Append("//base.ConfigureProxy(this.GetType(), "); 13 sb.Append(WsdlParser.IsValidUrl((string)_connectURLs[i])); 14 sb.Append(");"); 15 } 16 textWriter.WriteLine(sb); PrintClientProxy
  11. 13 01 if (value == null) { return "\"\""; }

    02 vsb.Length= 0; 03 vsb.Append("@\""); 04 05 for (int i=0; i<value.Length; i++) 06 { 07 if (value[i] == '\"') vsb.Append("\"\""); 08 else vsb.Append(value[i]); 09 } 10 11 vsb.Append("\""); 12 return vsb.ToString(); IsValidUrl
  12. 14 В результате… FireEye Uncovers CVE-2017-8759: Zero-Day Used in the

    Wild to Distribute FINSPY: fireeye.com/blog/threat-research/2017/09/zero-day-used-to-distribute-finspy.html
  13. 15 01 if (!System.Runtime.Remoting.Configuration.AppSettings.AllowUnsanitizedWSDLUrls) 02 { 03 return WsdlParser.TransliterateString(value); 04

    } 05 06 if (value == null) { return "\"\""; } 07 vsb.Length= 0; 08 vsb.Append("@\""); 09 10 for (int i=0; i<value.Length; i++) 11 { 12 if (value[i] == '\"') vsb.Append("\"\""); 13 else vsb.Append(value[i]); 14 } 15 16 vsb.Append("\""); 17 return vsb.ToString(); Исправленный IsValidUrl
  14. 16 01 if (string.IsNullOrEmpty(str)) { return "\"\""; } 02 StringBuilder

    sb = new StringBuilder("\""); 03 foreach (char c in str) 04 { 05 if (char.IsControl(c)) { continue; } 06 if (char.IsLetterOrDigit(c)) 07 { 08 sb.Append(c); 09 } 10 else 11 { 12 sb.Append("\\u"); 13 sb.Append(Convert.ToInt32(c).ToString("X4")); 14 } 15 } 16 sb.Append("\""); 17 return sb.ToString(); TransliterateString
  15. Поиск и эксплуатация инъекций • Для всех распространённых грамматик существуют:

    • Техники слепого поиска и эксплуатации инъекций • «Out-of-band» техники • Инструменты автоматизации в том числе таких техник • «Это не смогут обнаружить», «это не будут атаковать» и т.п. — относятся к области анализа рисков и выходят далеко за пределы зоны ответственности разработчиков
  16. 19 «Враг знает систему» Следствия: • если уязвимость может быть

    обнаружена, она будет обнаружена; • если уязвимость может быть проэксплуатирована, она будет проэксплуатирована; • при эксплуатации уязвимости будет нанесён максимально возможный ущерб. Принцип Керкгоффса-Шеннона
  17. 20 • Инъекции — хорошо формализуемый класс уязвимостей • Существует

    формальный подход, как к разработке защищённого от инъекций кода, так и к защите существующего от атак на них Good news everyone!
  18. 22 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($"<img src='//host/1/{a}' onclick='f({b})'/>"); Граница окружения Модель уязвимого приложения (1/7)
  19. 23 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($"<img src='//host/1/{a}' onclick='f({b})'/>"); Точка входа a Граница окружения Модель уязвимого приложения (2/7)
  20. 24 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($"<img src='//host/1/{a}' onclick='f({b})'/>"); Точка входа a Точка входа b Граница окружения Модель уязвимого приложения (3/7)
  21. 25 Точка выхода fpvo (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($"<img src='//host/1/{a}' onclick='f({b})'/>"); Точка входа a Точка входа b Граница окружения Модель уязвимого приложения (4/7)
  22. 26 Точка выхода fpvo (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($"<img src='//host/1/{a}' onclick='f({b})'/>"); Точка входа a Точка входа b Граница окружения Модель уязвимого приложения (5/7)
  23. 27 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($"<img src='//host/1/{a}' onclick='f({b})'/>"); Точка входа a Точка входа b Точка выхода fpvo (ftransform (a, b)) Граница окружения Модель уязвимого приложения (6/7) Точка инъекции a
  24. 28 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($"<img src='//host/1/{a}' onclick='f({b})'/>"); Точка входа a Точка входа b Точка выхода fpvo (ftransform (a, b)) Граница окружения Модель уязвимого приложения (7/7) Точка инъекции a Точка инъекции b
  25. 29 Атаки инъекции направлены на внедрение в точки инъекции грамматических

    конструкций, не предусмотренных логикой приложения Суть атаки инъекции
  26. 30 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($"<img src='//host/1/{a}' onclick='f({b})'/>"); image.jpg Граница окружения Модель атаки (HTML/URL, нет инъекции) < img src = ' // host / 1 / image.jpg ' …
  27. 31 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($"<img src='//host/1/{a}' onclick='f({b})'/>"); ../image.jpg Граница окружения Модель атаки (HTML/URL, инъекция URL-пути) < img src = ' // host / 1 / .. / image.jpg ' …
  28. 32 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($"<img src='//host/1/{a}' onclick='f({b})'/>"); 'onerror='alert(0) Граница окружения Модель атаки (HTML/URL, инъекция HTML-атрибута) < img src = ' // host / 1 / ' onerror = ' alert ( 0 ) ' …
  29. 33 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($"<img src='//host/1/{a}' onclick='f({b})'/>"); '><script>alert(0)</script> Граница окружения Модель атаки (HTML/URL, инъекция HTML-тега) < img src = ' // host / 1 / ' > < script > alert(0) </ script >' …
  30. 34 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($"<img src='//host/1/{a}' onclick='f({b})'/>"); Граница окружения Модель атаки (HTML/JavaScript, нет инъекции) … onclick = ' f ( 0 ) ' /> 0
  31. 35 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($"<img src='//host/1/{a}' onclick='f({b})'/>"); Граница окружения Модель атаки (HTML/JavaScript, инъекция JavaScript-выражения #1) … onclick = ' f ( alert ( 0 ) ) ' /> alert(0)
  32. 36 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($"<img src='//host/1/{a}' onclick='f({b})'/>"); Граница окружения Модель атаки (HTML/JavaScript, инъекция JavaScript-выражения #2) … onclick = ' f ( 0 ) ; alert ( 0 ) ' /> 0); alert(0
  33. 37 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($"<img src='//host/1/{a}' onclick='f({b})'/>"); Граница окружения Модель атаки (HTML/JavaScript, инъекция HTML-атрибута) … onclick = ' f ( ' onclick = ' alert ( 0 ) ' /> ' onclick='alert(0
  34. 38 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($"<img src='//host/1/{a}' onclick='f({b})'/>"); Граница окружения Модель атаки (HTML/JavaScript, инъекция HTML-тега) … onclick = ' f ( ' > < script > alert ( 0 ) </ script > ) ' /> '><script>alert(0)</script>
  35. 39 • Нет атаки — 1 токен в точке инъекции

    • Есть атака — более 1 токена в точке инъекции Посчитаем токены
  36. 40 Приложение защищено от атак инъекций тогда, когда в результате

    лексического разбора любого возможного выходного потока данных, на каждую точку инъекции приходится не более одного токена Достаточный критерий защищённости от атак инъекций
  37. 41 Что если сама логика приложения подразумевает наличие более одного

    токена в какой-либо точке инъекции? Достаточный критерий не всегда применим
  38. 42 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($"<img src='//host/1/{a}' onclick='f({b})'/>"); Граница окружения Модель атаки (HTML/JavaScript, нет инъекции) … onclick = ' f ( { "f1" : "val1" , "f2" : "val2" } ) ' /> { "f1": "val1", "f2": "val2" }
  39. 43 Приложение защищено от атак инъекций тогда, когда в результате

    лексического разбора любого возможного потока выходных данных, множества токенов, приходящиеся на точки инъекции, являются авторизованными Необходимый критерий защищённости от атак инъекций
  40. 44 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($"<img src='//host/1/{a}/' onclick='f({b})'/>"); Ga = ANY Граница окружения Причина инъекции — несогласованность грамматик (1/3) Ga' = HTMLatt-value / URLname
  41. 45 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($"<img src='//host/1/{a}/' onclick='f({b})'/>"); Gb = ANY Граница окружения Причина инъекции — несогласованность грамматик (2/3) Gb' = HTMLatt-value / JSint-literal
  42. 46 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($"<img src='//host/1/{a}/' onclick='f({b})'/>"); Gb = ANY Граница окружения Причина инъекции — несогласованность грамматик (3/3) Gb' = HTMLatt-value / JSjson-object
  43. 48 Победить инъекции возможно, обеспечив выполнение одного из критериев через

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

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

    • Типизации • Валидации • Синтаксической • Семантической Подходы к согласованию грамматик входных данных Обеспечение необходимого или достаточного критериев В том числе: объектный подход и параметризация
  46. 52 01 var a = Request.Params["a"]; 02 03 var b

    = int.Parse(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($"<img src='//host/1/{a}/' onclick='f({b})'/>"); Граница окружения Согласование грамматик (типизация) Gb = int-literal Gb = HTMLatt-value / JSint-literal
  47. 53 Синтаксическая валидация — проверка входных данных на соответствие какой-либо

    грамматике: 01 var url_regex = 02 "^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?"; 03 04 if (!Regex.IsMatch(Request.Params["a"], url_regex)) 05 { 06 throw new ValidationException(); 07 } Синтаксическая валидация
  48. 54 01 var a = Request.Params["a"]; 02 03 var b

    = Request.Params["b"]; 04 05 if (!Regex.IsMatch("[^:@/?#\r\n]+", b ?? string.Empty)) 06 { 07 return; 08 } 09 10 if (b == null) 11 { 12 return; 13 } 14 15 Response.Write($"<img src='//host/1/{a}' onclick='f({b})'/>"); Ga = URLname Граница окружения Согласование грамматик (синтаксическая валидация) Ga' = HTMLatt-value / URLname
  49. 55 Семантическая валидация — проверка входных данных на корректность с

    точки зрения логики приложения: 01 var schema = JSchema.Parse("some JSON schema"); 02 var object = JObject.Parse(Request.Params["b"]); 03 04 if (!object.IsValid(schema)) 05 { 06 throw new ValidationException(); 07 } Семантическая валидация
  50. 56 Типизация и семантическая валидация не примитивных типов, может повлечь

    уязвимости к атакам других классов (SSRF, DoS, RCE и т.п.) Опасности типизации и семантической валидации
  51. 57 01 var a = Request.Params["a"]; 02 03 var b

    = ParseAndValidateJson(Request.Params["b"], schema); 04 05 if (a == null) 06 { 07 return; 08 } 09 10 if (b == null) 11 { 12 return; 13 } 14 15 Response.Write($"<img src='//host/1/{a}' onclick='f({b})'/>"); Граница окружения Согласование грамматик (семантическая валидация) Gb = JSONobject Gb = HTMLatt-value / JSONobject
  52. 58 Выходные данные должны согласовываться с грамматикой принимающей стороны за

    счёт санитизации Подходы к согласованию грамматик выходных данных Обеспечение достаточного критерия
  53. 59 Санитизация — преобразование строковых данных к синтаксису какого-либо токена

    заданной грамматики 01 Response.Write( 02 $"<a href='//host/1/{UrlEncode(Request.Params["a"])}'>…</a>" 03 ); Санитизация
  54. 60 В случае вложенных грамматик, например: G = JavaScriptcontext /

    URLcontext санитизацию необходимо проводить последовательно, в обратном порядке: JavaScriptEncodecontext (UrlEncodecontext (t)). Санитизация вложенных грамматик
  55. 61 01 var a = UrlEncode(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($"<img src='//host/1/{a}' onclick='f({b})'/>"); Ga = URLname Граница окружения Согласование грамматик (санитизация) Ga' = HTMLatt-value / URLname
  56. 62 • Выделить в приложении все точки входа данных; •

    Выделить все точки инъекции производных от них данных; • Провести типизацию и валидацию в точках входа с учётом требований бизнес-логики; • Провести санитизацию в точках инъекций, с учётом ожидаемых в них грамматик принимающей стороной; • Подтверждать авторизованность множества токенов в точках инъекций (опционально). Что сделать разработчику, чтобы победить инъекции
  57. 64 Реализовать в веб-приложении построение разметки для ссылок, безопасно обрабатывающее

    некорректные URL и генерирующее для ссылок на внешние ресурсы вывод диалога с предупреждением Проблема
  58. 65 public override void Process(TagHelperContext context, TagHelperOutput output) { var

    url = context.AllAttributes["href"].Value.ToString(); if (!Uri.IsWellFormedUriString(url, UriKind.RelativeOrAbsolute)) { throw new UriFormatException("Malformed URI"); } var uri = new Uri(url, UriKind.RelativeOrAbsolute); if (!uri.IsAbsoluteUri || RequestHost == uri.Host) { return; } var onclickHandler = $"return confirm('You are about visit an external link: {uri} Are you sure?')"; output.Attributes.SetAttribute("onclick", onclickHandler); } Решение (ASP.NET MVC): реализовать TagHelper для <a>
  59. 68 Причина уязвимости — вариативность грамматики URI (2/3) javascript://localhost/?a=\r\nalert(1) System.Uri

    javascript: Scheme // - (separator) localhost Domain / - (separator) ? - (separator) a=\r\nalert(1) Query-parameter
  60. 69 Причина уязвимости — вариативность грамматики URI (3/3) javascript://localhost/?a=\r\nalert(1) System.Uri

    Browser javascript: Scheme javascript: Scheme // - (separator) //localhost/?a= JS-comment localhost Domain \r\n Line-feed / - (separator) alert(1) JS-expression ? - (separator) a=\r\nalert(1) Query-parameter
  61. 70 01 public override void Process(TagHelperContext context, TagHelperOutput output) 02

    { 03 var url = context.AllAttributes["href"].Value.ToString(); 04 05 if (!Uri.IsWellFormedUriString(url, UriKind.RelativeOrAbsolute)) 06 { 07 throw new UriFormatException("Malformed URI"); 08 } 09 10 var uri = new Uri(url, UriKind.RelativeOrAbsolute); 11 12 if (!uri.IsAbsoluteUri || RequestHost == uri.Host) { return; } 13 14 if (!Regex.IsMatch(uri.Scheme, "https?|ftp")) 15 { 16 throw new UriFormatException("Invalid scheme"); 17 } 18 19 var onclickHandler = 20 $"return confirm('You are about visit an external link: {uri} Are you sure?')"; 21 22 output.Attributes.SetAttribute("onclick", onclickHandler); 23 } Устранение уязвимости
  62. 71 Какими будут URL, создаваемые с помощью new Uri("/path", <UriKind>)

    ? mono-project.com/docs/faq/known-issues/urikind-relativeorabsolute/ github.com/dotnet/corefx/issues/22098 Ещё немного о объектном подходе на примере System.Uri .ctor .NET 4.7, .NET Core 2.0, Mono 5.4 (Windows) .NET Core 2.0 (Linux) Mono 5.4 (Linux) new Uri("/path", UriKind.Absolute) Исключение Абсолютный Абсолютный new Uri("/path", UriKind.Relative) Относительный Исключение Относительный new Uri("/path", UriKind.RelativeOrAbsolute) Относительный Относительный Абсолютный
  63. 72 • Средства параметризации и объектного подхода: • всего лишь

    частный случай типизации в защите от инъекций; • не всегда существуют или применимы и не являются панацеей; • могут содержать неоднозначности, уязвимости и ошибки в своём коде; • часто требуют от разработчика доскональных знаний грамматик и деталей своей реализации. • Думать всё равно придётся  (даже в случае с LibProtection) Вся правда о «современных средствах разработки»
  64. 74 Вот если бы существовала библиотека, принимающая на себя рутину

    по защите приложения от атак инъекций... Мечтать не вредно
  65. 77 LibProtection — библиотека с открытым под MIT-лицензией кодом, позволяющая

    разработчикам: • полностью автоматизировать защиту от атак инъекций по достаточному критерию; • реализовывать защиту по необходимому критерию. libprotection.org playground.libprotection.org (ждём байпассов ) Что такое LibProtection (1/3)
  66. 78 Для защиты от атак в LibProtection реализованы: • автоматическая

    санитизация данных в точках инъекций там, где это возможно; • автоматическая валидация данных в точках инъекций по достаточному критерию (детектирование атаки) там, где невозможна санитизация; • возможность переопределения функций валидации и санитизации для обеспечения необходимого критерия. Что такое LibProtection (2/3)
  67. 79 Поддерживаемые языки: • .NET, C++, JVM (Q4 2017 –

    Q1 2018) • PHP, JavaScript, Python, Ruby (2018) Текущий статус .NET-версии: ранняя бета, C++ и JVM: в процессе портирования. Поддерживаемые грамматики: SQL, HTML, JavaScript, URL, файловые пути, CSS, XML, XPath, CMD, BASH Что такое LibProtection (3/3)
  68. 80 // Форматирование строки с автоматической санитизацией и валидацией string

    SafeString<T>.Format(FormattableString formattable) string SafeString<T>.Format(string format, params object[] args) // Try-версия Format bool SafeString<T>.TryFormat(FormattableString formattable, out formatted) bool SafeString<T>.TryFormat(string format, out formatted, params object[] args) T { Sql, Html, JavaScript, Css, Url, FilePath, Xml, Xpath } LibProtection API: методы
  69. 85 Как это работает (4/9) 'onerror='alert(0) ");alert(0) <img src='//host/1/{a}' onclick='f("{b}")'/>

    <img src='//host/1/'onerror='alert(0)' onclick='f("");alert(0)//")'/> < img src = ' // host / 1 / ' onerror = ' alert ( 0 ) ' onclick = ' f ( "" ) ; alert ( 0 ) //" ) ' />
  70. 86 Как это работает (5/9) 'onerror='alert(0) ");alert(0) <img src='//host/1/{a}' onclick='f("{b}")'/>

    <img src='//host/1/'onerror='alert(0)' onclick='f("");alert(0)//")'/> < img src = ' // host / 1 / ' onerror = ' alert ( 0 ) ' onclick = ' f ( "" ) ; alert ( 0 ) //" ) ' /> UrlEncode JavaScriptStringEncode
  71. 87 Как это работает (6/9) 'onerror='alert(0) ");alert(0) <img src='//host/1/{a}' onclick='f("{b}")'/>

    <img src='//host/1/'onerror='alert(0)' onclick='f("");alert(0)//")'/> < img src = ' // host / 1 / ' onerror = ' alert ( 0 ) ' onclick = ' f ( "" ) ; alert ( 0 ) //" ) ' /> UrlEncode JavaScriptStringEncode <img src='//host/1/{a}' onclick='f("{b}")'/>
  72. 88 Как это работает (7/9) 'onerror='alert(0) ");alert(0) <img src='//host/1/{a}' onclick='f("{b}")'/>

    <img src='//host/1/'onerror='alert(0)' onclick='f("");alert(0)//")'/> < img src = ' // host / 1 / ' onerror = ' alert ( 0 ) ' onclick = ' f ( "" ) ; alert ( 0 ) //" ) ' /> UrlEncode JavaScriptStringEncode <img src='//host/1/{a}' onclick='f("{b}")'/> <img src='//host/1/%27onerror%3D%27alert%280%29' onclick='f("\&quot;);alert(0)//")'/>
  73. 89 Как это работает (8/9) 'onerror='alert(0) ");alert(0) <img src='//host/1/{a}' onclick='f("{b}")'/>

    <img src='//host/1/'onerror='alert(0)' onclick='f("");alert(0)//")'/> < img src = ' // host / 1 / ' onerror = ' alert ( 0 ) ' onclick = ' f ( "" ) ; alert ( 0 ) //" ) ' /> UrlEncode JavaScriptStringEncode <img src='//host/1/{a}' onclick='f("{b}")'/> <img src='//host/1/%27onerror%3D%27alert%280%29' onclick='f("\&quot;);alert(0)//")'/> < img src = ' // host / 1 / %27onerror%3D%27alert%280%29 ' onclick = ' f ( "\&quot;);alert(0)//" ) ' />
  74. 90 Как это работает (9/9) 'onerror='alert(0) ");alert(0) <img src='//host/1/{a}' onclick='f("{b}")'/>

    <img src='//host/1/'onerror='alert(0)' onclick='f("");alert(0)//")'/> < img src = ' // host / 1 / ' onerror = ' alert ( 0 ) ' onclick = ' f ( "" ) ; alert ( 0 ) //" ) ' /> UrlEncode JavaScriptStringEncode <img src='//host/1/{a}' onclick='f("{b}")'/> <img src='//host/1/%27onerror%3D%27alert%280%29' onclick='f("\&quot;);alert(0)//")'/> < img src = ' // host / 1 / %27onerror%3D%27alert%280%29 ' onclick = ' f ( "\&quot;);alert(0)//" ) ' />
  75. 91 // Отключение валидации и санитизации :safe // Переопределение валидатора

    :validate(method-name) method-name Func<string,bool> // Переопределение санитизатора :sanitize(method-name) method-name Func<string, string> // Переключение режима валидации :weak, :normal, :strong LibProtection API: форматные модификаторы
  76. Режимы валидации • ValidationMode.Weak • Подсчёт токенов • Проверка категорий

    токенов • ValidationMode.Normal • Подсчёт токенов • Проверка категорий токенов • Контроль запрещённых токенов • ValidationMode.Strong (по умолчанию) • Контроль запрещённых токенов • Подсчёт токенов • Проверка категорий токенов
  77. 93 • SafeStringBuilder — защищённый аналог StringBuilder • SafeStringWriter —

    защищённый аналог TextWriter • язык описания шаблонов множества разрешённых токенов Планы на светлое будущее
  78. Области применения LibProtection • Быстрый патчинг уязвимого кода, использующего форматные

    и интерполированные строки • Штатная защита кода там, где форматные строки или интерполяция неизбежны Что, если скрестить LibProtection и технологии SAST или DAST? ;)
  79. 95 Незначительно замедляется обработка запросов, непосредственно приводящих приложение в точку

    выполнения потенциально опасной операции: Влияние на производительность Штатный трафик Атаки +1..3% +3..5%
  80. 96 Ещё одно решение задачи о форматировании тега 01 private

    static string BuildSafeLinkTag(string url, string text, string localhost) 02 { 03 var uri = new Uri(url, UriKind.RelativeOrAbsolute); 04 05 var clickHandler = uri.IsAbsoluteUri && localhost != uri.Host ? 06 $"return confirm('Are you sure you want to follow this link: {uri} ?')" : 07 "return true" 08 09 return SafeString.Format<Html>( 10 $"<a href='{uri}' onclick='{clickHandler:safe}'>{text}</a>" 11 ); 12 }