Upload
positive-hack-days
View
515
Download
1
Embed Size (px)
Citation preview
Проблемы автоматической генерации эксплойтов по
исходному коду
Алексей Москвин
Сергей Плехов
Automatic Exploit Generation.
Техники обнаружения уязвимостей
Динамический анализ кода (DAST)
Фаззинг входящих параметров (Fuzz testing/Black Box)
Инструментация кода
Статический анализ кода (SAST)
Pattern matching
Анализ не самой программы, а какого-либо её представления (AST/CFG/PDG)
Гибридный анализ
Совмещение результатов полученных статическим и динамическим анализом.
Статический анализ кода
Необходимо иметь доступ к исходным кодам приложения
Позволяет не только искать уязвимости, но и проверять различные свойства программ
Преимущество: не нужно развернутого приложения
Большинство академических методов статического анализа, не позволяют анализировать большие приложения
Тяжело проверить полученные результаты
Динамический анализ кода.
Настройки конфигурации
Не нужно иметь доступ к исходным кодам приложения, но необходимо установленное приложение
Не зависит от языка, на котором написано приложение
Легко реализуется и легко проверить результаты анализа
Сложно оценить покрытие кода при проведении анализа
Можно уничтожить веб приложение
Гибридный анализ.
Необходимо иметь доступ как к исходным кодам приложения, так и развернутое приложение.
Есть возможность проверить полученные результаты, но необходимо скомбинировать результаты статического анализа и динамического.
При “плохой” реализации, возникают в полном объеме все минусы динамического анализа
Отчеты содержат большое количество результатов, не относящихся к уязвимостям.
Реализованные цели.
Производить анализ при отсутствии развернутого приложения.
Небольшое количество ложных срабатывании (false positive)
Автоматическая генерация эксплойтов!
Описание алгоритма.
По исходному коду строится промежуточное представление программы.
По промежуточному представлению создается абстрактная интерпретация программы.
По абстрактной интерпретации производятся символические вычисления.
Представления кода.
При анализе используем промежуточные представления исходного кода.
Генерация формулы.
По исходному коду собираем логическую формулу.
<?php // test.php if ($_GET['p'] == 'P@ssw0rd') { print base64_decode($_GET['text']); }
Входящие данные являются неизвестными значениями.
($_GET[‘p’] == ‘P@ssw0rd’) && (base64_decode($_GET['text']) == <script>alert('test');</script>)
Символические вычисления.
Exploit:
test.php?p=P@ssw0rd&text=PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg%3D%3D
Компоненты реализации.
Важные моменты анализа.
Анализ хода выполнения программы.
Частичное выполнение кода.
Специфика языков программирования.
Ход выполнения: тривиальный пример
<?phpprint $_GET['x'];
Ход выполнения: анализ Data Flow
<?php$x = $_GET[‘x’];// …print $x;
Ход выполнения: фильтрации
// фильтрация основного параметра<?php$x = $_GET['x'];if(preg_match('/[a-z]/', $x)) print $x; // фильтрация дополнительного параметра<?php$x = $_GET['x'];if(preg_match('/[a-z]/', $_GET['y'])) print $x;
Контекст вывода данных.
<?php// <script>alert('test');</script>print $_GET['name']; // "><script>alert('test');</script>print '<input type="button" id="'.$_GET['id'].'">';
Ход выполнения: ООП
<?php class ParamGetter { public function getParam($param) { return $_GET[$param]; }} $x = new ParamGetter();print $x->getParam('name');
Ход выполнения: пространство имен
<?php…use Modules/Params;$x = new ParamGetter();print $x->getParam('name');
Ход выполнения: глобальные переменные
<?php
$flag = False; function f() { global $flag; if ($flag) // меняется в функции g() print $_GET['x']; // false positive g();} function g() { // вызывается в трех местах global $flag; $flag = !$flag;} f(); g(); f(); g();
$flag
g()
print $_GET['x']
f() Main:Line 17
Main:Line 18
… … … комбинаторный взрыв
Ход выполнения: присваивание по ссылке
<?php function f($x, &$y) { $y = $x;} $x = $_GET['x'];$y = NULL; f($x, $y);print $y;
Ход выполнения: зависимости модулей
Файл не является точкой входа
<?php // module1.php$x = $_GET['x'];require('module2.php');?> <?php // module2.phpprint $x;?>
При поиске уязвимостей необходимо учитывать “естественный” ход
выполнения программы.
Специфика PHP (I)
Перезапись переменных
<?php
$name = 'x';${$name} = $_GET['x'];print $x;
Частичное выполнение: динамические пути
<?php $path = $_SERVER['DOCUMENT_ROOT'].'/my_lib'; require $path.'/my_funcs.php'; my_print($_GET['x']);
Частичное выполнение: сокращение перебора
<?php//...$allowed_tags = array('history'); $f = fread('footer.template'); $tags = array('name', 'title', 'job', 'address', 'phone' 'id'); foreach ($tags as $tag) if (in_array($tag, $allowed_tags)) $f = str_replace('<'.$tag.'>', $_POST[$tag], $f)
print $f;
Частичное выполнение: обфускация<?php $_F=__FILE__;$_X='Pz48IS0tIGI1ZzRuIGYyMnQ1ciAtLT4NCg0KPGQ0diBzdHlsNT0iY2w1MXI6YjJ0aDsiPjwvZDR2Pg0KPGQ0diBzdHlsNT0iY2w1MXI6YjJ0aDsiPjwvZDR2Pg0KDQo8ZDR2IDRkPSJmMjJ0NXJiZyI+DQo8ZDR2IDRkPSJmMjJ0NXIiPg0KDQoJPGQ0diA0ZD0iZjIydDVybDVmdCI+DQoJCTxoYT5SNWM1bnRseSBXcjR0dDVuPC9oYT4NCgkJCTwzbD4NCgkJCQk8P3BocCBnNXRfMXJjaDR2NXMoJ3Ayc3RieXAyc3QnLCA2MCk7ID8+DQoJCQk8LzNsPg0KCTwvZDR2Pg0KCQ0KCTxkNHYgNGQ9ImYyMnQ1cm00ZGRsNTYiPg0KCQk8aGE+TTJudGhseSBBcmNoNHY1czwvaGE+DQoJCQk8M2w+DQoJCQkJPD9waHAgd3BfZzV0XzFyY2g0djVzKCd0eXA1PW0ybnRobHknKTsgPz4NCgkJCTwvM2w+PGJyIC8+DQoJPC9kNHY+DQoJDQoJPGQ0diA0ZD0iZjIydDVybTRkZGw1YSI+DQoJCTxoYT5CbDJncjJsbDwvaGE+DQoJCQk8M2w+DQoJCQkJPD9waHAgZzV0X2w0bmtzKC02LCAnPGw0PicsICc8L2w0PicsICcgLSAnKTsgPz4NCgkJCTwvM2w+DQoJPC9kNHY+DQoJDQoJPGQ0diA0ZD0iZjIydDVycjRnaHQiPg0KCQk8aG8+DQoJICAgIEY0bmQgSXQ8L2hvPg0KCSAgIAkJPGYycm0gNGQ9InM1MXJjaGYycm00bmJsMmciIG01dGgyZD0iZzV0IiAxY3Q0Mm49Ijw/cGhwIDVjaDIgJF9TRVJWRVJbJ1BIUF9TRUxGJ107ID8+Ij4NCgkgICAJCTw0bnAzdCB0eXA1PSJ0NXh0IiB2MWwzNT0iVDIgczUxcmNoLCB0eXA1IDFuZCBoNHQgNW50NXIuLi4iIG4xbTU9InMiIDRkPSJzNG5ibDJnIiAybmYyYzNzPSI0ZiAodGg0cy52MWwzNSA9PSAnVDIgczUxcmNoLCB0eXA1IDFuZCBoNHQgNW50NXIuLi4nKSB7dGg0cy52MWwzNSA9ICcnO30iIDJuYmwzcj0iNGYgKHRoNHMudjFsMzUgPT0gJycpIHt0aDRzLnYxbDM1ID0gJ1QyIHM1MXJjaCwgdHlwNSAxbmQgaDR0IDVudDVyLi4uJzt9IiAvPg0KCQkJPC9mMnJtPg0KCQk8aG8+QWRtNG48L2hvPg0KCQkJPDNsPg0KCQkJCTw/cGhwIHdwX3I1ZzRzdDVyKCk7ID8+DQoJCQkJPGw0Pjw/cGhwIHdwX2wyZzRuMjN0KCk7ID8+PC9sND4NCgkJCQk8P3BocCB3cF9tNXQxKCk7ID8+DQoJCQkJPGw0PjwxIGhyNWY9Imh0dHA6Ly92MWw0ZDF0MnIud28uMnJnL2NoNWNrPzNyND1yNWY1cjVyIj5YSFRNTDwvMT48L2w0Pg0KCQkJPC8zbD4NCgkJCQ0KCQk8aG8+Q3I1ZDR0czwvaG8+DQoJCQk8cD48MSBocjVmPSJodHRwOi8vd3d3LjFmZjRsNDF0NWRyMWcybi5jMm0vZnI1NS10NW5uNHMtdzJyZHByNXNzLXRoNW01LW4zbWI1ci0ybjUvIj5UNW5uNHMgVzJyZHByNXNzIFRoNW01PC8xPjxiciAvPmJ5IDwxIGhyNWY9Imh0dHA6Ly93d3cuYjV0YjJuM3MuYzIuM2siPkZyNTUgQjV0cyBUNW5uNHM8LzE+PGJyIC8+UDJ3NXI1ZCBieSA8MSBocjVmPSJodHRwOi8vdzJyZHByNXNzLjJyZyI+VzJyZFByNXNzPC8xPi48L3A+DQoJPC9kNHY+DQoJCQ0KPC9kNHY+DQoNCjxkNHYgNGQ9ImYyMnQ1cmIydHQybSI+DQo8aG8+QzJweXI0Z2h0ICZjMnB5OyA8P3BocCBibDJnNG5mMignbjFtNScpOz8+IDw/cGhwIDVjaDIgZDF0NSgnWScpOz8+IEFsbCBSNGdodHMgUjVzNXJ2NWQuPC9obz4NCjwvZDR2Pg0KDQo8L2Q0dj4NCg0KPD9waHAgZDJfMWN0NDJuKCd3cF9mMjJ0NXInKTsgPz4NCg0KPC9iMmR5Pg0KPC9odG1sPg==';eval(base64_decode('JF9YPWJhc2U2NF9kZWNvZGUoJF9YKTskX1g9c3RydHIoJF9YLCcxMjM0NTZhb3VpZScsJ2FvdWllMTIzNDU2Jyk7JF9SPWVyZWdfcmVwbGFjZSgnX19GSUxFX18nLCInIi4kX0YuIiciLCRfWCk7ZXZhbCgkX1IpOyRfUj0wOyRfWD0wOw=='));?>
Частичное выполнение: деобфускация
Промежуточные вычисления сильно упрощают дальнейший анализ
Состояния системы и переменных.
<?php $id = isset($_GET['id']) ? $_GET['id'] : 'Your id';$name = isset($_GET['name']) ? $_GET['name'] : 'Your name';$title = isset($_GET['title']) ? $_GET['title'] : 'Your title';$job = isset($_GET['job']) ? $_GET['job'] : 'Your job';$phone = isset($_GET['phone']) ? $_GET['phone'] : 'Your phone'; // 2^5 = 32 возможных состояний системы// на самом деле надо проанализировать всего 2*5 = 10 возможных состояний переменныхprint $id;print $name; print $title;print $job;print $phone;
Все состояния системы<?php $id = isset($_GET['id']) ? $_GET['id'] : 'Your id';$name = isset($_GET['name']) ? $_GET['name'] : 'Your name';$title = isset($_GET['title']) ? $_GET['title'] : 'Your title';
print $id;print $name; print $title;
Компрессированное состояние
<?php $id = isset($_GET['id']) ? $_GET['id'] : 'Your id';$name = isset($_GET['name']) ? $_GET['name'] : 'Your name';$title = isset($_GET['title']) ? $_GET['title'] : 'Your title';
print $id;print $name; print $title;
Дополнительные сложности
• Циклы• Рекурсия• Файловая система
Циклы
// вычисляемые:• foreach (array('one', 'two', 'three') as $v) { ...}
// предполагаемые:• foreach($_GET['x'] as $v) { ... }
Рекурсия
function dump($x) { if (is_array($x)) { foreach($x as $v) dump($v); } else dump_const($x);}
// вычисляемая:dump(array('one', 'two', ['three']));
// предполагаемая:dump($_GET['x']);
Файловая система
// анализируемая• require 'langs/' . $_GET['lang'] . '.php';
// виртуальная• file_put_contents('cache.dat', $data); ... $data = file_get_contents('cache.dat');
// предполагаемая• if (file_exists('/tmp/tmp.dat'); ...
Дополнительные сложности 2
• Определение подключаемых модулей по результату запроса к базе данных
• Для компилируемых языков отсутствие части зависимостей не дает собрать проект
• Символьное решение методами SAT может работать очень долго: необходимы эвристики и ограничение по времени
• Можно решать уравнения не на множестве строк а на множестве регулярных выражений для них
• Всегда есть место для оптимизации
Другие виды уязвимостей
• Не все типы уязвимостей стоит ловить подобным методом (Pattern Matching, Fingerprinting, ошибки конфигурации)
• При расширении подхода становится возможным искать и более сложные инъекции (хранимые XSS, SQLi)
Second Chance
ApplicationServerBD
Inject Exploit
Trigger Exploit
Second Chance
if ($_GET['action'] == 'insert') { $user = $_GET['user']; $id = $_GET['id']; $sql = "UPDATE table1 SET user = '".
mysql_real_escape_string($user) . "' WHERE id = “ . intval($id) . ";"; mysql_query($sql);}else if ($_GET['action'] == 'select') { $sql = "SELECT * FROM table1 WHERE id = ". intval($id) . ";"; $res = mysql_query($sql); while ($row = mysql_fetch_array($res)) { echo $row['id'] + $row['user']; }}