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

Формальное моделирование уязвимостей

Формальное моделирование уязвимостей

Слайды доклада с митапа IT Sec Pro Course

Vladimir Kochetkov

February 09, 2018
Tweet

More Decks by Vladimir Kochetkov

Other Decks in Science

Transcript

  1. :~$ whoami • Руководитель отдела исследований по анализу защищённости приложений

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

    безопасные приложения Чат в Telegram: https://t.me/ru_appsec Присоединяйтесь! Positive Development User Group
  3. Зачем AppSec'у формальные модели • Теоретические исследования • Поиск уязвимостей

    (ручной и автоматизированный) • Генерация эксплоитов или патчей • Защита приложения времени выполнения
  4. Виды моделей (1/2) • Предметной области (логические) • Управление доступом

    • Защищённость приложения • Бизнес-логика • Верификация • Вычислительные • Алгоритмические • Машины Тьюринга, Поста • Лямбда-исчисление • Нормальные алгорифмы Маркова • Темпоральные • Сети Петри • Потоки управления • Потоки данных • Потоки вычисления
  5. Виды моделей (2/2) • Предметной области (логические) • Управление доступом

    • Защищённость приложения • Бизнес-логика • Верификация • Вычислительные • Алгоритмические • Машины Тьюринга (МТ), Поста • Лямбда-исчисление • Нормальные алгорифмы Маркова • Темпоральные • Сети Петри • Потоки управления • Потоки данных • Потоки вычисления
  6. Применимость абстрактных моделей на практике Построение прикладной модели на основе

    каких-либо свойств абстрактной позволяет, в некоторой степени, доказывать её свойства на основе уже имеющихся теорем и утверждений.
  7. Машина Тьюринга (1/2) Математическая абстракция, представляющая универсальную вычислительную машину. Машина

    Тьюринга состоит из: • бесконечной ячеистой ленты; • управляющего устройства с конечным числом состояний; • таблицы переходов между состояниями. На каждой итерации может: • изменить текущую ячейку; • перейти в другое состояние; • переместиться на соседнюю ячейку.
  8. Машина Тьюринга (2/2) Семерка M=(Q,Γ,b,Σ,δ,q0,F) где: Q - конечное непустое

    множество состояний; Γ - конечное непустое множество символов алфавита; b∈Γ - пустой символ; Σ⊆Γ∖b - множество входных символов; q0∈Q - начальное состояние; F⊆Q - множество финальных состояний; δ:Q∖F×Γ → Q×Γ×{L,R} - функция перехода, где: L - сдвиг по ленте влево R - сдвиг по ленте вправо
  9. Реализация фильтрующей функции на МТ (1/18) _ # A B

    q0 halt q1 # • q2 # • q3 A → q1 B → q1 q2 _ → q3 # ← q2 A ← q2 B ← q2 q3 _ → q0 _ • q3 _ → q3 _ → q4 q4 B • q2 # → q4 A → q4 B → q4 A B
  10. Реализация фильтрующей функции на МТ (2/18) (q1 A) ⇒ (A

    → q1) _ # A B q0 halt q1 # • q2 # • q3 A → q1 B → q1 q2 _ → q3 # ← q2 A ← q2 B ← q2 q3 _ → q0 _ • q3 _ → q3 _ → q4 q4 B • q2 # → q4 A → q4 B → q4 A B
  11. Реализация фильтрующей функции на МТ (3/18) (q1 A) ⇒ (A

    → q1) (q1 B) ⇒ (B → q1) _ # A B q0 halt q1 # • q2 # • q3 A → q1 B → q1 q2 _ → q3 # ← q2 A ← q2 B ← q2 q3 _ → q0 _ • q3 _ → q3 _ → q4 q4 B • q2 # → q4 A → q4 B → q4 A B
  12. Реализация фильтрующей функции на МТ (4/18) (q1 A) ⇒ (A

    → q1) (q1 B) ⇒ (B → q1) (q1 _) ⇒ (# • q2) _ # A B q0 halt q1 # • q2 # • q3 A → q1 B → q1 q2 _ → q3 # ← q2 A ← q2 B ← q2 q3 _ → q0 _ • q3 _ → q3 _ → q4 q4 B • q2 # → q4 A → q4 B → q4 A B #
  13. Реализация фильтрующей функции на МТ (5/18) (q1 A) ⇒ (A

    → q1) (q1 B) ⇒ (B → q1) (q1 _) ⇒ (# • q2) (q2 #) ⇒ (# ← q2) _ # A B q0 halt q1 # • q2 # • q3 A → q1 B → q1 q2 _ → q3 # ← q2 A ← q2 B ← q2 q3 _ → q0 _ • q3 _ → q3 _ → q4 q4 B • q2 # → q4 A → q4 B → q4 A B #
  14. Реализация фильтрующей функции на МТ (6/18) (q1 A) ⇒ (A

    → q1) (q1 B) ⇒ (B → q1) (q1 _) ⇒ (# • q2) (q2 #) ⇒ (# ← q2) (q2 B) ⇒ (B ← q2) _ # A B q0 halt q1 # • q2 # • q3 A → q1 B → q1 q2 _ → q3 # ← q2 A ← q2 B ← q2 q3 _ → q0 _ • q3 _ → q3 _ → q4 q4 B • q2 # → q4 A → q4 B → q4 A B #
  15. Реализация фильтрующей функции на МТ (7/18) (q1 A) ⇒ (A

    → q1) (q1 B) ⇒ (B → q1) (q1 _) ⇒ (# • q2) (q2 #) ⇒ (# ← q2) (q2 B) ⇒ (B ← q2) (q2 A) ⇒ (A ← q2) _ # A B q0 halt q1 # • q2 # • q3 A → q1 B → q1 q2 _ → q3 # ← q2 A ← q2 B ← q2 q3 _ → q0 _ • q3 _ → q3 _ → q4 q4 B • q2 # → q4 A → q4 B → q4 A B #
  16. Реализация фильтрующей функции на МТ (8/18) (q1 A) ⇒ (A

    → q1) (q1 B) ⇒ (B → q1) (q1 _) ⇒ (# • q2) (q2 #) ⇒ (# ← q2) (q2 B) ⇒ (B ← q2) (q2 A) ⇒ (A ← q2) (q2 _) ⇒ (_ → q3) _ # A B q0 halt q1 # • q2 # • q3 A → q1 B → q1 q2 _ → q3 # ← q2 A ← q2 B ← q2 q3 _ → q0 _ • q3 _ → q3 _ → q4 q4 B • q2 # → q4 A → q4 B → q4 A B #
  17. Реализация фильтрующей функции на МТ (9/18) (q1 A) ⇒ (A

    → q1) (q1 B) ⇒ (B → q1) (q1 _) ⇒ (# • q2) (q2 #) ⇒ (# ← q2) (q2 B) ⇒ (B ← q2) (q2 A) ⇒ (A ← q2) (q2 _) ⇒ (_ → q3) (q3 A) ⇒ (_ → q3) _ # A B q0 halt q1 # • q2 # • q3 A → q1 B → q1 q2 _ → q3 # ← q2 A ← q2 B ← q2 q3 _ → q0 _ • q3 _ → q3 _ → q4 q4 B • q2 # → q4 A → q4 B → q4 A B #
  18. Реализация фильтрующей функции на МТ (10/18) (q1 A) ⇒ (A

    → q1) (q1 B) ⇒ (B → q1) (q1 _) ⇒ (# • q2) (q2 #) ⇒ (# ← q2) (q2 B) ⇒ (B ← q2) (q2 A) ⇒ (A ← q2) (q2 _) ⇒ (_ → q3) (q3 A) ⇒ (_ → q3) (q3 B) ⇒ (_ → q4) _ # A B q0 halt q1 # • q2 # • q3 A → q1 B → q1 q2 _ → q3 # ← q2 A ← q2 B ← q2 q3 _ → q0 _ • q3 _ → q3 _ → q4 q4 B • q2 # → q4 A → q4 B → q4 B #
  19. Реализация фильтрующей функции на МТ (11/18) (q1 A) ⇒ (A

    → q1) (q1 B) ⇒ (B → q1) (q1 _) ⇒ (# • q2) (q2 #) ⇒ (# ← q2) (q2 B) ⇒ (B ← q2) (q2 A) ⇒ (A ← q2) (q2 _) ⇒ (_ → q3) (q3 A) ⇒ (_ → q3) (q3 B) ⇒ (_ → q4) (q4 #) ⇒ (# → q4) _ # A B q0 halt q1 # • q2 # • q3 A → q1 B → q1 q2 _ → q3 # ← q2 A ← q2 B ← q2 q3 _ → q0 _ • q3 _ → q3 _ → q4 q4 B • q2 # → q4 A → q4 B → q4 #
  20. Реализация фильтрующей функции на МТ (12/18) (q1 A) ⇒ (A

    → q1) (q1 B) ⇒ (B → q1) (q1 _) ⇒ (# • q2) (q2 #) ⇒ (# ← q2) (q2 B) ⇒ (B ← q2) (q2 A) ⇒ (A ← q2) (q2 _) ⇒ (_ → q3) (q3 A) ⇒ (_ → q3) (q3 B) ⇒ (_ → q4) (q4 #) ⇒ (# → q4) (q4 _) ⇒ (B • q2) _ # A B q0 halt q1 # • q2 # • q3 A → q1 B → q1 q2 _ → q3 # ← q2 A ← q2 B ← q2 q3 _ → q0 _ • q3 _ → q3 _ → q4 q4 B • q2 # → q4 A → q4 B → q4 #
  21. Реализация фильтрующей функции на МТ (13/18) (q1 A) ⇒ (A

    → q1) (q1 B) ⇒ (B → q1) (q1 _) ⇒ (# • q2) (q2 #) ⇒ (# ← q2) (q2 B) ⇒ (B ← q2) (q2 A) ⇒ (A ← q2) (q2 _) ⇒ (_ → q3) (q3 A) ⇒ (_ → q3) (q3 B) ⇒ (_ → q4) (q4 #) ⇒ (# → q4) (q4 _) ⇒ (B • q2) (q2 B) ⇒ (B ← q2) _ # A B q0 halt q1 # • q2 # • q3 A → q1 B → q1 q2 _ → q3 # ← q2 A ← q2 B ← q2 q3 _ → q0 _ • q3 _ → q3 _ → q4 q4 B • q2 # → q4 A → q4 B → q4 # B
  22. Реализация фильтрующей функции на МТ (14/18) (q1 A) ⇒ (A

    → q1) (q1 B) ⇒ (B → q1) (q1 _) ⇒ (# • q2) (q2 #) ⇒ (# ← q2) (q2 B) ⇒ (B ← q2) (q2 A) ⇒ (A ← q2) (q2 _) ⇒ (_ → q3) (q3 A) ⇒ (_ → q3) (q3 B) ⇒ (_ → q4) (q4 #) ⇒ (# → q4) (q4 _) ⇒ (B • q2) (q2 B) ⇒ (B ← q2) (q2 #) ⇒ (# ← q2) _ # A B q0 halt q1 # • q2 # • q3 A → q1 B → q1 q2 _ → q3 # ← q2 A ← q2 B ← q2 q3 _ → q0 _ • q3 _ → q3 _ → q4 q4 B • q2 # → q4 A → q4 B → q4 # B
  23. Реализация фильтрующей функции на МТ (15/18) (q1 A) ⇒ (A

    → q1) (q1 B) ⇒ (B → q1) (q1 _) ⇒ (# • q2) (q2 #) ⇒ (# ← q2) (q2 B) ⇒ (B ← q2) (q2 A) ⇒ (A ← q2) (q2 _) ⇒ (_ → q3) (q3 A) ⇒ (_ → q3) (q3 B) ⇒ (_ → q4) (q4 #) ⇒ (# → q4) (q4 _) ⇒ (B • q2) (q2 B) ⇒ (B ← q2) (q2 #) ⇒ (# ← q2) (q2 _) ⇒ (_ → q3) _ # A B q0 halt q1 # • q2 # • q3 A → q1 B → q1 q2 _ → q3 # ← q2 A ← q2 B ← q2 q3 _ → q0 _ • q3 _ → q3 _ → q4 q4 B • q2 # → q4 A → q4 B → q4 # B
  24. Реализация фильтрующей функции на МТ (16/18) (q1 A) ⇒ (A

    → q1) (q1 B) ⇒ (B → q1) (q1 _) ⇒ (# • q2) (q2 #) ⇒ (# ← q2) (q2 B) ⇒ (B ← q2) (q2 A) ⇒ (A ← q2) (q2 _) ⇒ (_ → q3) (q3 A) ⇒ (_ → q3) (q3 B) ⇒ (_ → q4) (q4 #) ⇒ (# → q4) (q4 _) ⇒ (B • q2) (q2 B) ⇒ (B ← q2) (q2 #) ⇒ (# ← q2) (q2 _) ⇒ (_ → q3) (q3 #) ⇒ (_ • q3) _ # A B q0 halt q1 # • q2 # • q3 A → q1 B → q1 q2 _ → q3 # ← q2 A ← q2 B ← q2 q3 _ → q0 _ • q3 _ → q3 _ → q4 q4 B • q2 # → q4 A → q4 B → q4 # B
  25. Реализация фильтрующей функции на МТ (17/18) (q1 A) ⇒ (A

    → q1) (q1 B) ⇒ (B → q1) (q1 _) ⇒ (# • q2) (q2 #) ⇒ (# ← q2) (q2 B) ⇒ (B ← q2) (q2 A) ⇒ (A ← q2) (q2 _) ⇒ (_ → q3) (q3 A) ⇒ (_ → q3) (q3 B) ⇒ (_ → q4) (q4 #) ⇒ (# → q4) (q4 _) ⇒ (B • q2) (q2 B) ⇒ (B ← q2) (q2 #) ⇒ (# ← q2) (q2 _) ⇒ (_ → q3) (q3 #) ⇒ (_ • q3) (q3 _) ⇒ (_ → q0) _ # A B q0 halt q1 # • q2 # • q3 A → q1 B → q1 q2 _ → q3 # ← q2 A ← q2 B ← q2 q3 _ → q0 _ • q3 _ → q3 _ → q4 q4 B • q2 # → q4 A → q4 B → q4 B
  26. Реализация фильтрующей функции на МТ (18/18) (q1 A) ⇒ (A

    → q1) (q1 B) ⇒ (B → q1) (q1 _) ⇒ (# • q2) (q2 #) ⇒ (# ← q2) (q2 B) ⇒ (B ← q2) (q2 A) ⇒ (A ← q2) (q2 _) ⇒ (_ → q3) (q3 A) ⇒ (_ → q3) (q3 B) ⇒ (_ → q4) (q4 #) ⇒ (# → q4) (q4 _) ⇒ (B • q2) (q2 B) ⇒ (B ← q2) (q2 #) ⇒ (# ← q2) (q2 _) ⇒ (_ → q3) (q3 #) ⇒ (_ • q3) (q3 _) ⇒ (_ → q0) halt _ # A B q0 halt q1 # • q2 # • q3 A → q1 B → q1 q2 _ → q3 # ← q2 A ← q2 B ← q2 q3 _ → q0 _ • q3 _ → q3 _ → q4 q4 B • q2 # → q4 A → q4 B → q4 B
  27. Модель потока вычисления (q1 A) ⇒ (A → q1) ⇒

    q1 {AB} (q1 B) ⇒ (B → q1) ⇒ q1 {AB } (q1 _) ⇒ (# • q2) ⇒ q2 {AB#} (q2 #) ⇒ (# ← q2) ⇒ q2 {AB#} (q2 B) ⇒ (B ← q2) ⇒ q2 {AB#} (q2 A) ⇒ (A ← q2) ⇒ q2 { AB#} (q2 _) ⇒ (_ → q3) ⇒ q3 {AB#} (q3 A) ⇒ (_ → q3) ⇒ q3 {B#} (q3 B) ⇒ (_ → q4) ⇒ q4 {#} (q4 #) ⇒ (# → q4) ⇒ q4 {# } (q4 _) ⇒ (B • q2) ⇒ q2 {#B} (q2 B) ⇒ (B ← q2) ⇒ q2 {#B} (q2 #) ⇒ (# ← q2) ⇒ q2 { #B} (q2 _) ⇒ (_ → q3) ⇒ q3 {#B} (q3 #) ⇒ (_ • q3) ⇒ q3 { B} (q3 _) ⇒ (_ → q0) ⇒ q0 {B} Поток вычисления (предикат ⇒ побочные эффекты ⇒ состояние)
  28. Поиск уязвимостей на потоке вычисления МТ (2/5) halt _ #

    A B q0 halt q1 # • q2 # • q3 A → q1 B → q1 q2 _ → q3 # ← q2 A ← q2 B ← q2 q3 _ → q0 _ • q3 _ → q3 _ → q4 q4 B • q2 # → q4 A → q4 B → q4 A B
  29. Поиск уязвимостей на потоке вычисления МТ (3/5) (q3 _) ⇒

    (_ → q0) halt _ # A B q0 halt q1 # • q2 # • q3 A → q1 B → q1 q2 _ → q3 # ← q2 A ← q2 B ← q2 q3 _ → q0 _ • q3 _ → q3 _ → q4 q4 B • q2 # → q4 A → q4 B → q4 A B
  30. Поиск уязвимостей на потоке вычисления МТ (4/5) (q1 #) ⇒

    (# • q3) (q3 _) ⇒ (_ → q0) halt _ # A B q0 halt q1 # • q2 # • q3 A → q1 B → q1 q2 _ → q3 # ← q2 A ← q2 B ← q2 q3 _ → q0 _ • q3 _ → q3 _ → q4 q4 B • q2 # → q4 A → q4 B → q4 # A B
  31. Поиск уязвимостей на потоке вычисления МТ (5/5) (q1 #) ⇒

    (# • q3) (q3 _) ⇒ (_ → q0) halt _ # A B q0 halt q1 # • q2 # • q3 A → q1 B → q1 q2 _ → q3 # ← q2 A ← q2 B ← q2 q3 _ → q0 _ • q3 _ → q3 _ → q4 q4 B • q2 # → q4 A → q4 B → q4 # A B Эксплоит
  32. Проблемы подхода • Утверждать о получении результата анализа возможно только

    после остановки анализатора • Лента МТ бесконечна ⇒ бесконечно множество неуязвимых конфигураций программы • При анализе веток неуязвимых конфигураций, анализатор никогда не достигнет начального состояния • Анализатор никогда не остановится, если программа неуязвима
  33. Применимость абстрактных моделей (1/2) In practice, models built on these

    foundations are bound to be nearly useless for generalized, real-world software engineering… Michal Zalewski, "The Tangled Web"
  34. Применимость абстрактных моделей (2/2) In practice, models built on these

    foundations are bound to be nearly useless for generalized, real-world software engineering… Michal Zalewski, "The Tangled Web" В любой непонятной ситуации – аппроксимируй модель!
  35. Поток вычисления реальных приложений Поток вычисления описывает предикативную последовательность смены

    конфигураций МТ в процессе вычисления алгоритма Для МТ конфигурацию составляют: • позиция считывателя на ленте; • содержимое ленты; • активное состояние. Для реального приложения, полным аналогом конфигурации МТ является состояние всех потоков данных, доступных в каждой точке потока управления.
  36. Построение потока вычисления реального приложения (1/10) 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); if (name + "in" == "admin") { string str1; if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  37. Построение потока вычисления реального приложения (2/10) Response.Write(str1) 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); if (name + "in" == "admin") { string str1; if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  38. Построение потока вычисления реального приложения (3/10) Response.Write({ key1 == "validkey"

    ⇒ Encoding.UTF8.GetString(data), }) 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); if (name + "in" == "admin") { string str1; if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  39. Построение потока вычисления реального приложения (4/10) Response.Write({ key1 == "validkey"

    ⇒ Encoding.UTF8.GetString(data), key1 != "validkey" ⇒ "Wrong key!" }) 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); if (name + "in" == "admin") { string str1; if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  40. Построение потока вычисления реального приложения (5/10) name + "in" ==

    "admin" ⇒ Response.Write({ key1 == "validkey" ⇒ Encoding.UTF8.GetString(data), key1 != "validkey" ⇒ "Wrong key!" }) 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); if (name + "in" == "admin") { string str1; if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  41. Построение потока вычисления реального приложения (6/10) name + "in" ==

    "admin" ⇒ Response.Write({ key1 == "validkey" ⇒ Encoding.UTF8.GetString({ string.IsNullOrEmpty(parm) ⇒ new char[0] }), key1 != "validkey" ⇒ "Wrong key!" }) 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); if (name + "in" == "admin") { string str1; if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  42. Построение потока вычисления реального приложения (7/10) name + "in" ==

    "admin" ⇒ Response.Write({ key1 == "validkey" ⇒ Encoding.UTF8.GetString({ string.IsNullOrEmpty(parm) ⇒ new char[0], !string.IsNullOrEmpty(parm) ⇒ Convert.FromBase64String(parm) }), key1 != "validkey" ⇒ "Wrong key!" }) 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); if (name + "in" == "admin") { string str1; if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  43. Построение потока вычисления реального приложения (8/10) name + "in" ==

    "admin" ⇒ Response.Write({ key1 == "validkey" ⇒ Encoding.UTF8.GetString({ string.IsNullOrEmpty( Request.Params["parm"] ) ⇒ new char[0], !string.IsNullOrEmpty( Request.Params["parm"] ) ⇒ Convert.FromBase64String( Request.Params["parm"] ) }), key1 != "validkey" ⇒ "Wrong key!" }) 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); if (name + "in" == "admin") { string str1; if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  44. Построение потока вычисления реального приложения (9/10) name + "in" ==

    "admin" ⇒ Response.Write({ Request.Params["key1"] == "validkey" ⇒ Encoding.UTF8.GetString({ string.IsNullOrEmpty( Request.Params["parm"] ) ⇒ new char[0], !string.IsNullOrEmpty( Request.Params["parm"] ) ⇒ Convert.FromBase64String( Request.Params["parm"] ) }), Request.Params["key1"] != "validkey" ⇒ "Wrong key!" }) 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); if (name + "in" == "admin") { string str1; if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  45. Построение потока вычисления реального приложения (10/10) Request.Params["name"] + "in" ==

    "admin" ⇒ Response.Write({ Request.Params["key1"] == "validkey" ⇒ Encoding.UTF8.GetString({ string.IsNullOrEmpty( Request.Params["parm"] ) ⇒ new char[0], !string.IsNullOrEmpty( Request.Params["parm"] ) ⇒ Convert.FromBase64String( Request.Params["parm"] ) }), Request.Params["key1"] != "validkey" ⇒ "Wrong key!" }) 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); if (name + "in" == "admin") { string str1; if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  46. Построение полного потока вычисления (1/10) ε ⇒ { name ∈

    {ε ⇒ Request.Params["name"]} } 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); if (name + "in" == "admin") { string str1; if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  47. Построение полного потока вычисления (2/10) ε ⇒ { name ∈

    {ε ⇒ Request.Params["name"]} key1 ∈ {ε ⇒ Request.Params["key1"]} } 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); if (name + "in" == "admin") { string str1; if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  48. Построение полного потока вычисления (3/10) ε ⇒ { name ∈

    {ε ⇒ Request.Params["name"]} key1 ∈ {ε ⇒ Request.Params["key1"]} parm ∈ {ε ⇒ Request.Params["parm"]} } 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); if (name + "in" == "admin") { string str1; if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  49. Построение полного потока вычисления (4/10) ε ⇒ { name ∈

    {ε ⇒ Request.Params["name"]} key1 ∈ {ε ⇒ Request.Params["key1"]} parm ∈ {ε ⇒ Request.Params["parm"]} data ∈ { string.IsNullOrEmpty(parm) ⇒ new char[0], !string.IsNullOrEmpty(parm) ⇒ Convert.FromBase64String(parm) } } 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); if (name + "in" == "admin") { string str1; if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  50. Построение полного потока вычисления (5/10) (name + "in" == "admin")

    ⇒ { name ∈ {ε ⇒ Request.Params["name"]} key1 ∈ {ε ⇒ Request.Params["key1"]} parm ∈ {ε ⇒ Request.Params["parm"]} data ∈ { string.IsNullOrEmpty(parm) ⇒ new char[0], !string.IsNullOrEmpty(parm) ⇒ Convert.FromBase64String(parm) } } 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); if (name + "in" == "admin") { string str1; if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  51. Построение полного потока вычисления (6/10) (name + "in" == "admin")

    ⇒ { name ∈ {ε ⇒ Request.Params["name"]} key1 ∈ {ε ⇒ Request.Params["key1"]} parm ∈ {ε ⇒ Request.Params["parm"]} data ∈ { string.IsNullOrEmpty(parm) ⇒ new char[0], !string.IsNullOrEmpty(parm) ⇒ Convert.FromBase64String(parm) } str1 ∈ { (name + "in" == "admin") ⇒ null} } 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); if (name + "in" == "admin") { string str1; if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  52. Построение полного потока вычисления (7/10) (name + "in" == "admin")

    && (key1 == "validkey") ⇒ { name ∈ {ε ⇒ Request.Params["name"]} key1 ∈ {ε ⇒ Request.Params["key1"]} parm ∈ {ε ⇒ Request.Params["parm"]} data ∈ { string.IsNullOrEmpty(parm) ⇒ new char[0], !string.IsNullOrEmpty(parm) ⇒ Convert.FromBase64String(parm) } str1 ∈ { (name + "in" == "admin") ⇒ null} } 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); if (name + "in" == "admin") { string str1; if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  53. Построение полного потока вычисления (8/10) (name + "in" == "admin")

    && (key1 == "validkey") ⇒ { name ∈ {ε ⇒ Request.Params["name"]} key1 ∈ {ε ⇒ Request.Params["key1"]} parm ∈ {ε ⇒ Request.Params["parm"]} data ∈ { string.IsNullOrEmpty(parm) ⇒ new char[0], !string.IsNullOrEmpty(parm) ⇒ Convert.FromBase64String(parm) } str1 ∈ { (name + "in" == "admin") ⇒ null, (name + "in" == "admin") && (key1 == "validkey") ⇒ Encoding.UTF8.GetString(data) } } 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); if (name + "in" == "admin") { string str1; if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  54. Построение полного потока вычисления (9/10) (name + "in" == "admin")

    && (key1 != "validkey") ⇒ { name ∈ {ε ⇒ Request.Params["name"]} key1 ∈ {ε ⇒ Request.Params["key1"]} parm ∈ {ε ⇒ Request.Params["parm"]} data ∈ { string.IsNullOrEmpty(parm) ⇒ new char[0], !string.IsNullOrEmpty(parm) ⇒ Convert.FromBase64String(parm) } str1 ∈ { (name + "in" == "admin") ⇒ null, (name + "in" == "admin") && (key1 == "validkey") ⇒ Encoding.UTF8.GetString(data), (name + "in" == "admin") && (key1 != "validkey") ⇒ "Wrong key!" } } 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); if (name + "in" == "admin") { string str1; if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  55. Построение полного потока вычисления (10/10) (name + "in" == "admin")

    ⇒ { name ∈ {ε ⇒ Request.Params["name"]} key1 ∈ {ε ⇒ Request.Params["key1"]} parm ∈ {ε ⇒ Request.Params["parm"]} data ∈ { string.IsNullOrEmpty(parm) ⇒ new char[0], !string.IsNullOrEmpty(parm) ⇒ Convert.FromBase64String(parm) } str1 ∈ { (name + "in" == "admin") && (key1 == "validkey") ⇒ Encoding.UTF8.GetString(data), (name + "in" == "admin") && (key1 != "validkey") ⇒ "Wrong key!" } Response.Write(str1) } 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); if (name + "in" == "admin") { string str1; if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  56. Модель потока вычисления приложения • Приложение рассматривается, как множество точек

    выполнения, связанных между собой в соответствии с графом потока управления • Каждая точка хранит информацию о предикативных состояниях всех доступных в ней переменных • Предикативное состояние описывается парой элементов: 1. Предикатом, описывающим формулу достижимости состояния 2. Формулой, определяющей множество значений, соответствующее описываемому состоянию • Формулы конструируются путём подстановки фрагментов кода при абстрактной интерпретации в семантике символьных вычислений • Формальная форма описания модели – граф потока вычисления
  57. Возможности модели потока вычисления • Модель потока вычисления позволяет: •

    разрешать элементы множества значений входных данных по заданному состоянию; • определять состояние по заданному множеству значений входных данных • Для моделирования уязвимостей по ней требуется конкретизация понятия "уязвимое состояние" в зависимости от рассматриваемого класса атак • Один из возможных подходов к конкретизации заключается в сопоставлении аргументов опасных операций со множествами значений возможных эксплоитов
  58. Бесконтекстный поиск уязвимостей (1/13) Request.Params["name"] + "in" == "admin" ⇒

    Response.Write({ Request.Params["key1"] == "validkey" ⇒ Encoding.UTF8.GetString({ string.IsNullOrEmpty(Request.Params["parm"]) ⇒ new char[0], !string.IsNullOrEmpty(Request.Params["parm"]) ⇒ Convert.FromBase64String(Request.Params["parm"]) }), Request.Params["key1"] != "validkey" ⇒ "Wrong key!" })
  59. Бесконтекстный поиск уязвимостей (2/13) Request.Params["name"] + "in" == "admin" ⇒

    Response.Write({ Request.Params["key1"] == "validkey" ⇒ Encoding.UTF8.GetString({ string.IsNullOrEmpty(Request.Params["parm"]) ⇒ new char[0], !string.IsNullOrEmpty(Request.Params["parm"]) ⇒ Convert.FromBase64String(Request.Params["parm"]) }), Request.Params["key1"] != "validkey" ⇒ "Wrong key!" })
  60. Бесконтекстный поиск уязвимостей (3/13) Request.Params["name"] + "in" == "admin" ⇒

    Response.Write({ Request.Params["key1"] == "validkey" ⇒ Encoding.UTF8.GetString({ !string.IsNullOrEmpty(Request.Params["parm"]) ⇒ Convert.FromBase64String(Request.Params["parm"]) }), Request.Params["key1"] != "validkey" ⇒ "Wrong key!" })
  61. Бесконтекстный поиск уязвимостей (4/13) Request.Params["name"] + "in" == "admin" ⇒

    Response.Write({ Request.Params["key1"] == "validkey" ⇒ Encoding.UTF8.GetString({ !string.IsNullOrEmpty(Request.Params["parm"]) ⇒ Convert.FromBase64String(Request.Params["parm"]) }), Request.Params["key1"] != "validkey" ⇒ "Wrong key!" })
  62. Бесконтекстный поиск уязвимостей (5/13) Request.Params["name"] + "in" == "admin" ⇒

    Response.Write({ Request.Params["key1"] == "validkey" ⇒ Encoding.UTF8.GetString({ !string.IsNullOrEmpty(Request.Params["parm"]) ⇒ Convert.FromBase64String(Request.Params["parm"]) }) })
  63. Бесконтекстный поиск уязвимостей (6/13) Request.Params["name"] + "in" == "admin" ⇒

    Response.Write({ Request.Params["key1"] == "validkey" ⇒ Encoding.UTF8.GetString({ !string.IsNullOrEmpty(Request.Params["parm"]) ⇒ Convert.FromBase64String(Request.Params["parm"]) }) })
  64. Бесконтекстный поиск уязвимостей (7/13) Request.Params["name"] + "in" == "admin" &&

    Request.Params["key1"] == "validkey" && !string.IsNullOrEmpty(Request.Params["parm"]) ⇒ Response.Write( Encoding.UTF8.GetString( Convert.FromBase64String(Request.Params["parm"]) ) )
  65. Бесконтекстный поиск уязвимостей (8/13) Request.Params["name"] + "in" == "admin" &&

    Request.Params["key1"] == "validkey" && !string.IsNullOrEmpty(Request.Params["parm"]) ⇒ Response.Write( Encoding.UTF8.GetString( Convert.FromBase64String(Request.Params["parm"]) ) )
  66. Бесконтекстный поиск уязвимостей (9/13) Request.Params["name"] + "in" == "admin" &&

    Request.Params["key1"] == "validkey" && Encoding.UTF8.GetString( Convert.FromBase64String(Request.Params["parm"]) ) ⊇ "<script>alert(0)</script>" ⇒ Response.Write( Encoding.UTF8.GetString( Convert.FromBase64String(Request.Params["parm"]) ) )
  67. Бесконтекстный поиск уязвимостей (10/13) Request.Params["name"] + "in" == "admin" &&

    Request.Params["key1"] == "validkey" && Encoding.UTF8.GetString( Convert.FromBase64String(Request.Params["parm"]) ) ⊇ "<script>alert(0)</script>" ⇒ Response.Write( Encoding.UTF8.GetString( Convert.FromBase64String(Request.Params["parm"]) ) )
  68. Бесконтекстный поиск уязвимостей (11/13) Request.Params["name"] + "in" == "admin" &&

    Request.Params["key1"] == "validkey" && Convert.FromBase64String(Request.Params["parm"]) ⊇ Encoding.UTF8.GetBytes("<script>alert(0)</script>") ⇒ Response.Write( Encoding.UTF8.GetString( Convert.FromBase64String(Request.Params["parm"]) ) )
  69. Бесконтекстный поиск уязвимостей (12/13) Request.Params["name"] + "in" == "admin" &&

    Request.Params["key1"] == "validkey" && Request.Params["parm"] = Convert.ToBase64String( Encoding.UTF8.GetBytes("<script>alert(0)</script>") ) ⇒ Response.Write( Encoding.UTF8.GetString( Convert.FromBase64String(Request.Params["parm"]) ) )
  70. Бесконтекстный поиск уязвимостей (13/13) Request.Params["name"] = "adm" Request.Params["key1"] = "validkey"

    Request.Params["parm"] = "PHNjcmlwdD5hbGVydCgwKTwvc2NyaXB0Pg==" ⇒ Response.Write( Encoding.UTF8.GetString( Convert.FromBase64String(Request.Params["parm"]) ) )
  71. Дальнейшее развитие модели • Точность модели можно увеличить за счёт

    перехода от конечных множеств возможных эксплоитов к бесконечным • Для этого необходимо определить критерии состояния защищённости в рамках исследуемого класса уязвимостей
  72. 78 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)
  73. 79 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)
  74. 80 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)
  75. 81 Точка выхода 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)
  76. 82 Точка выхода 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)
  77. 83 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
  78. 84 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
  79. Точка инъекции Фрагмент формулы состояния достижимой точки потока вычисления, множество

    значений которого зависит от входных данных: ε ⇒ Response.Write( "<img src='//host/1/" + { Request.Params["a"] != null ⇒ Request.Params["a"] } + "' onclick='f(" + { Request.Params["b"] != null ⇒ Request.Params["b"] } ")'/>" )
  80. 86 Атаки инъекции направлены на внедрение в точки инъекции грамматических

    конструкций, не предусмотренных логикой приложения Суть атаки инъекции
  81. 87 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 ' …
  82. 88 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 ' …
  83. 89 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 ) ' …
  84. 90 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 >' …
  85. 91 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
  86. 92 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)
  87. 93 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
  88. 94 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
  89. 95 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>
  90. 96 • Нет атаки — 1 токен в точке инъекции

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

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

    токена в какой-либо точке инъекции? Достаточный критерий не всегда применим
  93. 99 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" }
  94. 100 Приложение защищено от атак инъекций тогда, когда в результате

    лексического разбора любого возможного потока выходных данных, множества токенов, приходящиеся на точки инъекции, являются авторизованными Необходимый критерий защищённости от атак инъекций
  95. Как скрестить WAF и статанализатор? • Статанализатор строит полную модель

    потока вычисления приложения и передаёт её WAF'у • WAF, при обработке каждого HTTP-запроса, подставляет его параметры в формулы модели, вычисляет значения её состояний и анализирует их по необходимому или достаточному критерию
  96. Детектирование атак (1/6) http://host/path?name=adm&key1=validkey&parm=PHNjcmlwdD5hbGVydCgwKTwv c2NyaXB0Pg== Request.Params["name"] + "in" == "admin"

    ⇒ Response.Write({ Request.Params["key1"] == "validkey" ⇒ Encoding.UTF8.GetString({ string.IsNullOrEmpty(Request.Params["parm"]) ⇒ new char[0], !string.IsNullOrEmpty(Request.Params["parm"]) ⇒ Convert.FromBase64String(Request.Params["parm"]) }), Request.Params["key1"] != "validkey" ⇒ "Wrong key!" })
  97. Детектирование атак (2/6) http://host/path?name=adm&key1=validkey&parm=PHNjcmlwdD5hbGVydCgwKTwv c2NyaXB0Pg== "adm" + "in" == "admin"

    ⇒ Response.Write({ "validkey" == "validkey" ⇒ Encoding.UTF8.GetString({ string.IsNullOrEmpty("PHNj…") ⇒ new char[0], !string.IsNullOrEmpty("PHNj…") ⇒ Convert.FromBase64String("PHNj…") }), "validkey" != "validkey" ⇒ "Wrong key!" })
  98. Детектирование атак (3/6) http://host/path?name=adm&key1=validkey&parm=PHNjcmlwdD5hbGVydCgwKTwv c2NyaXB0Pg== true ⇒ Response.Write({ true ⇒

    Encoding.UTF8.GetString({ false ⇒ new char[0], true ⇒ Convert.FromBase64String("PHNj…") }), false ⇒ "Wrong key!" })
  99. 111 LibProtection — библиотека с открытым под MIT-лицензией кодом, использующая

    рассмотренную модель и позволяющая разработчикам: • полностью автоматизировать защиту от атак инъекций по достаточному критерию; • реализовывать защиту по необходимому критерию. libprotection.org playground.libprotection.org (ждём байпассов ☺) Что такое LibProtection
  100. 116 Как это работает (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 ) //" ) ' />
  101. 117 Как это работает (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
  102. 118 Как это работает (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}")'/>
  103. 119 Как это работает (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)//")'/>
  104. 120 Как это работает (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)//" ) ' />
  105. 121 Как это работает (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)//" ) ' />
  106. Области применения LibProtection • Быстрый патчинг уязвимого кода, использующего форматные

    и интерполированные строки • Штатная защита кода там, где форматные строки или интерполяция неизбежны Что, если скрестить LibProtection и статанализатор? ;)