3. Заголовок
def analyze(code, data):
if not vulnerable(code, data):
# given configuration is secure
else:
# given configuration is vulnerable
АНАЛИЗАТОР КОДА (ПРИМЕР 1/6)
4. Заголовок
def analyze(code, data):
if not vulnerable(code, data):
# given configuration is secure
vulnerable_function_call()
else:
# given configuration is vulnerable
АНАЛИЗАТОР КОДА (ПРИМЕР 2/6)
5. Заголовок
analyzer_code =
"""
def analyze(code, data):
if not vulnerable(code, data):
# given configuration is secure
vulnerable_function_call()
else:
# given configuration is vulnerable
"""
АНАЛИЗАТОР КОДА (ПРИМЕР 3/6)
6. Заголовок
analyzer_code =
"""
def analyze(code, data):
if not vulnerable(code, data):
# given configuration is secure
vulnerable_function_call()
else:
# given configuration is vulnerable
"""
eval(analyzer_code)
АНАЛИЗАТОР КОДА (ПРИМЕР 4/6)
7. Заголовок
analyzer_code =
"""
def analyze(code, data):
if not vulnerable(code, data):
# given configuration is secure
vulnerable_function_call()
else:
# given configuration is vulnerable
"""
eval(analyzer_code)
analyze(analyzer_code, analyzer_code)
АНАЛИЗАТОР КОДА (ПРИМЕР 5/6)
8. Заголовок
analyzer_code =
"""
def analyze(code, data):
if not vulnerable(code, data):
# given configuration is secure
vulnerable_function_call()
else:
# given configuration is vulnerable
"""
eval(analyzer_code)
analyze(analyzer_code, analyzer_code)
¯_(ツ)_/¯
АНАЛИЗАТОР КОДА (ПРИМЕР 6/6)
9. Заголовок
n = … # n
def analyze(code, data):
while n:
sleep(n)
n -= 1
if not vulnerable(code, data):
# given configuration is secure
vulnerable_function_call()
else:
# given configuration is vulnerable
И сколько таких «частных» случаев теперь возможно?
ЧАСТНЫЙ СЛУЧАЙ?
11. Заголовок
Проблема анализа защищённости решаема для программ:
• эквивалентных конечным автоматам (за PTIME)
• сводимых к конечным автоматам за счёт накладывания
ограничений на размеры доступной памяти, размерность
переменных, количество итераций циклов и т.п. (за EXPTIME)
Все существующие анализаторы используют подходы,
основанные на аппроксимации модели исследуемого кода.
Любой статанализатор легко «обламывается» не более, чем 3
строчками кода
СТАТАНАЛИЗАТОРЫ – ИНДУСТРИЯ ОБМАНА?
12. Заголовок
Интерпретация кода в рамках семантической модели,
отличающейся от модели формального языка. Основной
инструмент аппроксимации кода.
Абстрактная интерпретация
13. Заголовок
Построим свою собственную арифметику со знаком и
формулами:
(+a) = (+)
(-a) = (-)
(-a) * (+b) = (-)
(-a) / (+b) = (-)
(-a) + (+b) =
a ≤ b ⇒ (+),
a > b ⇒ (-)
И применим её:
-42 / 8 * 100500 + x =
x ≥ -527625 ⇒ (+),
x < -527625 ⇒ (-)
Абстрактная интерпретация на пальцах
14. Заголовок
Применяется для доказательства факта зависимости потоков
данных различных типов.
Частный случай – доказательство зависимости выходных данных
от входных aka taint-анализ.
Анализ зависимостей кода
15. ЗаголовокTaint-анализ (1/9)
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);
}
16. ЗаголовокTaint-анализ (2/9)
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);
}
17. ЗаголовокTaint-анализ (3/9)
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);
}
18. ЗаголовокTaint-анализ (4/9)
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);
}
19. ЗаголовокTaint-анализ (5/9)
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);
}
20. ЗаголовокTaint-анализ (6/9)
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);
}
21. ЗаголовокTaint-анализ (7/9)
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);
}
22. ЗаголовокTaint-анализ (8/9)
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);
}
23. ЗаголовокTaint-анализ (9/9)
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);
}
24. Заголовок
• Невозможно автоматизировать верификацию результатов.
• Не учитываются условия достижимости опасной операции.
• Семантика трансформирующих операций определяется
исключительно базой знаний.
• Подход применим только к классам уязвимостей к атакам,
основанным на передаче в опасную операцию конкретных
значений аргументов.
Недостатки taint-анализа
25. Заголовок
• Символическое выполнение – абстрактная интерпретация кода
в рамках семантической модели потоков вычисления.
Roberto Baldoni, Emilio Coppa, Daniele Cono D'Elia, Camil
Demetrescu, Irene Finocchi, «A Survey of Symbolic Execution
Techniques»
(https://arxiv.org/abs/1610.00502)
• Конкретное выполнение – выполнение отдельных фрагментов
кода в заданном контексте.
Символическое и конкретное выполнение
26. Заголовок
2x^2 + 4 = 12
2x^2 = 12 - 4
2x^2 = 12 - 4
x^2 = (12 - 4) / 2
x = sqrt((12 - 4) / 2)
x = sqrt((8) / 2)
x = sqrt(4)
x = 2
Символическое и конкретное выполнение (пример)
28. Заголовок
Сущность абстрактной интерпретации, включающая:
• область видимости переменных (условные множества их
достижимых значений);
• условие достижимости;
• ссылку на вышележащий контекст;
• стратегию взаимодействия с областями видимости
вышележащих контекстов.
Контексты символического выполнения
29. Заголовок
int main(int z) {
int a = 10;
if (z > 5)
{
a = z - 5;
}
else
{
a = z + 5;
}
return a;
}
Контексты (1/8)
{}
30. Заголовок
int main(int z) {
int a = 10;
if (z > 5)
{
a = z - 5;
}
else
{
a = z + 5;
}
return a;
}
Контексты (2/8)
true ⇒ {
true ⇒ z,
}
31. Заголовок
int main(int z) {
int a = 10;
if (z > 5)
{
a = z - 5;
}
else
{
a = z + 5;
}
return a;
}
Контексты (3/8)
true ⇒ {
true ⇒ z,
true ⇒ a = 10
}
32. Заголовок
int main(int z) {
int a = 10;
if (z > 5)
{
a = z - 5;
}
else
{
a = z + 5;
}
return a;
}
Контексты (4/8)
z > 5 ⇒ {
true ⇒ z,
z > 5 ⇒ a = z - 5
}
33. Заголовок
int main(int z) {
int a = 10;
if (z > 5)
{
a = z - 5;
}
else
{
a = z + 5;
}
return a;
}
Контексты (5/8)
z ≤ 5 ⇒ {
true ⇒ z,
z ≤ 5 ⇒ a = z + 5
}
34. Заголовок
int main(int z) {
int a = 10;
if (z > 5)
{
a = z - 5;
}
else
{
a = z + 5;
}
return a;
}
Контексты (6/8)
true ⇒ {
true ⇒ z,
z > 5 ⇒ a = z - 5
z ≤ 5 ⇒ a = z + 5
}
35. Заголовок
int main(int z) {
int a = 10;
if (z > 5)
{
a = z - 5;
}
else
{
a = z + 5;
}
return a;
}
Контексты (7/8)
true ⇒ {
true ⇒ z,
z > 5 ⇒ a = z - 5
z ≤ 5 ⇒ a = z + 5
}
36. Заголовок
int main(int z) {
int a = 10;
if (z > 5)
{
a = z - 5;
}
else
{
a = z + 5;
}
return a;
}
Контексты (8/8)
true ⇒ {
true ⇒ z,
z > 5 ⇒ a = z - 5
z ≤ 5 ⇒ a = z + 5
}
38. Заголовок
Кондиционал – опциональное множество всех возможных
значений переменной
Кондиционализация – замена неизвестных переменных в
формуле их кондиционалами:
true { return a
true z,
z > 5 a = z - 5
z ≤ 5 a = z + 5
}
return true { true z, z > 5 z – 5, z ≤ 5 z + 5 }
Кондиционализация
39. Заголовок
Разложение формулы, содержащей кондиционалы, на N формул,
не содержащих кондиционалы с аггрегированием условий для
каждой из них:
return true { true z, z > 5 z – 5, z ≤ 5 z + 5 }
return z > 5 { z – 5 }
return z ≤ 5 { z + 5 }
Опционализация
40. Заголовок
Marek Trtík, PHD Thesis: «Symbolic Execution and Program
Loops»
(https://is.muni.cz/th/329313/fi_d/trtik_phdThesis.pdf)
Циклы / рекурсия?
41. Заголовок
Учебный проект с реализацией абстрактного интерпретатора
подможества языка C (http://jamesvanboxtel.com/projects/minic-
compiler/minic.pdf)
https://github.com/PositiveTechnologies/mantaray
Mantaray
42. Заголовок
• Single-pass режим интерпретации.
• Межпроцедурный анализ с поддержкой глобального состояния.
• Упрощение формул достижимости SMT-солвером.
• Технический долг:
• циклы;
• указатели;
• детектирование NPD и инъекций;
Mantaray: особенности