Массачусетский Институт Технологий.
Курс лекций №6.858. «Безопасность компьютерных систем».
Николай Зельдович, Джеймс Микенс.
2014 год Безопасность компьютерных систем — это курс, посвященный проектированию и внедрению безопасных компьютерных систем.
Лекции охватывают модели угроз, атаки, ставящие под угрозу безопасность, а также методы обеспечения безопасности, основанные на последних научных работах.
Темы включают безопасность операционной системы (ОС), возможности, управление информационными потоками, языковую безопасность, сетевые протоколы, аппаратную безопасность и безопасность веб-приложений.
Лекция 1: «Введение: модели угроз» Часть 1 / Часть 2 / Часть 3 Лекция 2: «Контроль хакерских атак» Часть 1 / Часть 2 / Часть 3 Лекция 3: «Переполнение буфера: эксплойты и защита» Часть 1 / Часть 2 / Часть 3 Лекция 4: «Разделение привилегий» Часть 1 / Часть 2 / Часть 3 Лекция 5: «Откуда берутся ошибки системы безопасности» Часть 1 / Часть 2 Лекция 6: «Возможности» Часть 1 / Часть 2 / Часть 3 Лекция 7: «Нативная клиентская песочница» Часть 1 / Часть 2 / Часть 3 Лекция 8: «Модель сетевой безопасности» Часть 1 / Часть 2 / Часть 3 Лекция 9: «Безопасность веб-приложений» Часть 1 / Часть 2 / Часть 3 Лекция 10: Символическое исполнение Часть 1 / Часть 2 / Часть 3 Лекция 11: «Язык ур/веб-программирования» Часть 1 / Часть 2 / Часть 3 Лекция 12: «Сетевая безопасность» Часть 1 / Часть 2 / Часть 3 Лекция 13: «Сетевые протоколы» Часть 1 / Часть 2 / Часть 3 Лекция 14: «SSL и HTTPS» Часть 1 / Часть 2 / Часть 3 Лекция 15: «Медицинское программное обеспечение» Часть 1 / Часть 2 / Часть 3 Лекция 16: Атаки по побочным каналам Часть 1 / Часть 2 / Часть 3 Лекция 17: Аутентификация пользователя Часть 1 / Часть 2 / Часть 3 Лекция 18: «Частный просмотр Интернета» Часть 1 / Часть 2 / Часть 3 Лекция 19: «Анонимные сети» Часть 1 / Часть 2 / Часть 3 Лекция 20: «Безопасность мобильного телефона» Часть 1 / Часть 2 / Часть 3 Лекция 21: Отслеживание данных Часть 1 / Часть 2 / Часть 3 Студент: Итак, идеальным решением была бы архитектурная поддержка? Профессор: Да, для этого тоже есть методы.
Однако это немного сложнее, потому что, как вы можете видеть, мы выделили состояние искажения рядом с самой переменной.
Итак, если вы подумаете о поддержке, предоставляемой самим аппаратным обеспечением, изменить схему аппаратного обеспечения может быть очень сложно, поскольку все встроено в кремний.
Но если это возможно на высоком уровне в виртуальной машине Dalvic, можно представить, что можно будет размещать переменные вместе и заражать их также и на аппаратном уровне.
Так что, если вы измените макет в кремнии, вы, вероятно, сможете добиться этой цели.
Студент: и что TaintDroid делает с информацией, основанной на разрешениях ветки git, разрешениях ветки? Профессор: мы доберемся до этого через секунду, так что просто держите эту мысль, пока мы не доберемся до нее.
Студент: Мне любопытно, может ли здесь произойти переполнение буфера, потому что эти вещи — переменные и их инфекции — складываются вместе? Профессор: Это хороший вопрос.
Можно было бы надеяться, что в таком языке, как Java, нет переполнения буфера.
А вот в случае с C может случиться что-то катастрофическое, ведь если вы каким-то образом вызвали переполнение буфера, а затем перезаписали taint-теги для переменных, то в стеках будут установлены нулевые значения и данные будут свободно «утекать» в сеть.
Студент: Я думаю, все это можно предсказать? Профессор: совершенно верно.
Проблему переполнения буфера можно решить с помощью канареек — индикаторов стека, ведь если у вас есть эти данные в стеке, вы не хотите делать их неперезаписываемыми или не хотите, чтобы уже перезаписанные значения были взломали как-то.
Так что вы абсолютно правы — можно просто предотвратить переполнение буфера.
Короче говоря, на этом низком уровне x86/ARM можно обеспечить отслеживание вредоносных данных, хотя это может быть немного дорого и сложно реализовать правильно.
Вы можете спросить, почему мы вообще отслеживаем заражения, вместо того, чтобы наблюдать, как программа пытается отправить что-то по сети, просто сканируя данные, которые кажутся нам конфиденциальными.
Это кажется довольно простым, потому что тогда нам не нужно динамически отслеживать все, что делает программа.
Проблема в том, что это будет работать только на эвристическом уровне.
Фактически, если злоумышленник узнает, что вы действуете таким образом, он легко сможет вас взломать.
Если вы просто сидите и пытаетесь получить номера социального страхования, злоумышленник может просто использовать кодировку Base 64 или сделать какую-нибудь другую глупость, например, сжатие.
Обход этого типа фильтра достаточно тривиален, поэтому на практике его совершенно недостаточно для обеспечения безопасности.
Теперь давайте вернемся к вашему вопросу о том, как мы можем отслеживать потоки, проходящие через ветки.
Это приведет нас к теме под названием «Неявные потоки».
Неявный поток обычно возникает, когда у вас есть загрязненное значение, которое повлияет на способ назначения другой переменной, даже если эта неявная переменная потока не назначает переменные напрямую.
Позвольте мне привести вам конкретный пример.
Допустим, у вас есть оператор if, который проверит ваш IMEI и скажет: «Если он больше 42, я назначу x=0, в противном случае я назначу x=1».
Что интересно, сначала мы смотрим на конфиденциальные данные IMEI и сравниваем их с некоторым числом, но затем, когда мы назначаем x, мы не назначаем ничего, что могло бы быть получено непосредственно из этих конфиденциальных данных.
Это пример одного из неявных потоков.
Значение x действительно зависит от приведенного выше сравнения, но противник, если он умен, может построить свой код таким образом, что в нем не будет прямой связи.
Обратите внимание, что даже здесь вместо того, чтобы просто присваивать x = 0, x=1, вы можете просто поставить команду на отправку чего-либо по сети, то есть вы можете сообщить по сети, что x = 0 или x=1. или что-то вроде того.
Это пример одного из таких неявных потоков, которым не может управлять такая система, как TaintDroid. Это называется неявным потоком, в отличие от явного потока, такого как оператор присваивания.
Так что разработчики знают об этой проблеме.
Если я правильно понял, меня спросили, что было бы, если бы у нас была какая-то машинная функция, которая делала что-то похожее на приведенный выше пример, и поэтому системе TaintDroid это знать не обязательно, потому что TaintDroid не сможет заглянуть в этот машинный код и увидеть вещи такого рода.
Кстати, разработчики утверждают, что будут управлять этим с помощью машинно-специфичных методов, которые определяются самой виртуальной машиной, и рассмотрят способ реализации этого метода.
Например, мы берем эти два числа и затем возвращаем их среднее значение.
В этом случае система TaintDroid будет доверять функциям машины, поэтому нам нужно выяснить, какой должна быть соответствующая политика заражения вредоносным ПО.
Однако вы правы в том, что если что-то подобное было спрятано внутри машинного кода и по каким-то причинам не проверялось открыто, то ручные политики, которые придумали авторы TaintDroid, могут не отловить этот неявный поток.
Фактически, это может привести к утечке информации.
Более того, может быть даже прямой поток, который не заметили авторы TaintDroid, а у нас может быть еще более прямая утечка.
Студент: так что на практике это кажется очень опасным, не так ли? Потому что вы можете буквально стереть все зараженные значения, просто взглянув на последние 3 строки.
Профессор: у нас было несколько классов, которые изучали, как неявные потоки делают эти вещи.
Есть несколько способов это исправить.
Один из способов предотвратить подобные вещи — назначить компьютеру вредоносный тег, по сути заразив его с помощью теста Branch. Идея состоит в том, что мы можем с человеческой точки зрения посмотреть на этот код и сказать, что здесь есть неявный поток, потому что нам пришлось покопаться в конфиденциальных данных, чтобы добраться сюда.
Так что же это означает на уровне реализации? Это означает, что для того, чтобы попасть сюда, на компьютере должно быть что-то, зараженное конфиденциальными данными.
То есть можно сказать, что мы получили эти данные потому, что ПК был установлен здесь - x=0 - или здесь - x=1. В общем, можно представить, что система проведет некий анализ и выяснит, что в этом месте неявные потоки ПК вообще не заражен, тогда она подхватывает заражение по IMEI, а в этом месте, где x=0, ПК уже заражен.
В конечном итоге произойдет следующее: если x — это переменная, которая изначально отображается без искажений, мы скажем: «Хорошо, в этом месте x = 0 мы получаем заражение от компьютера, который был фактически заражен выше, в IMEI».
Здесь есть некоторые тонкости, но в целом видно, как ПК устанавливает себя, а затем пытается распространить инфекцию целевым операторам.
Ясно? Если вы хотите узнать больше, мы можем поговорить на эту тему, потому что я провел много исследований по этому поводу.
Однако система, которую я только что описал, снова может оказаться слишком консервативной.
Представьте, что вместо x = 1 здесь, как и выше, тоже x = 0. В этом случае нет смысла заражать x чем-то, связанным с IMEI, потому что никакая информация из этих веток не может утечь.
Но если вы используете компьютерную схему заражения ПК, вы можете переоценить количество поврежденных переменных x. Есть некоторые тонкости, которые вы можете предпринять, чтобы попытаться обойти некоторые из этих проблем, но это будет немного сложнее.
Студент: когда вы выходите из оператора if, вы также выходите из Branch и очищаетесь от инфекции? Профессор: как правило да, как только набор переменных закончится, ПК будет очищен от заражения.
Заражение устанавливается только в пределах этих ветвей от х до х.
Причина в том, что когда вы заходите сюда, вы делаете это независимо от того, какой был IMEI.
Мы говорили о том, что отслеживание заражений на этом очень низком уровне полезно, хотя и довольно дорого, поскольку оно действительно позволит вам увидеть, каков срок жизни ваших данных.
Пару лекций назад мы говорили о том, что зачастую ключевые данные живут в памяти гораздо дольше, чем вы думаете.
Можно себе представить, что хотя отслеживание заражений на уровне x86 или ARM обходится довольно дорого, вы можете использовать это для аудита своей системы.
Например, можно заразить некий секретный ключ, который ввёл пользователь, и отслеживать, где и как он перемещается по системе.
Это автономный анализ, который не влияет на пользователей, поэтому вполне нормально, что он может работать медленно.
Подобный анализ поможет выяснить, что, например, эти данные попадают в буфер клавиатуры, эти данные уходят на внешний сервер, эти данные уходят куда-то еще.
Так что, даже если это медленный процесс, он все равно может быть очень полезным.
Как я уже говорил, полезным свойством TaintDroid является то, что он ограничивает «вселенную» источников заражения и стоков зараженной информации.
Но как разработчик вам, вероятно, понадобится более детальный контроль над флагами заражения, с которыми взаимодействует ваша программа.
Итак, как программист, вы захотите сделать следующее.
Итак, вы объявляете некое целое число такого типа и называете его X, а затем связываете с ним метку.
Значение этой метки заключается в том, что Алиса является владельцем информации, которую она разрешает просматривать Бобу, или информация помечена для просмотра Бобом.
TaintDroid не позволяет вам этого делать, поскольку он по сути контролирует эту вселенную тегов, но как программист вы можете захотеть это сделать.
Предположим, что ваша программа имеет каналы ввода и вывода, и они также помечены.
Это ярлыки, которые вы выбрали как программист, а не сама система пытается сказать, что такие вещи предопределены.
Допустим, для входных каналов вы устанавливаете значения чтения, которые получают метку канала.
Это очень похоже на то, как работает TaintDroid — если считываются значения GPS-датчика, они помечаются тегом taint канала GPS, но теперь вы как программист выбираете эти метки.
В этом случае метка выходного канала должна совпадать со значением метки, которое мы записали.
Здесь можно представить и другие политики, но основная идея заключается в том, что существуют менеджеры программ, которые позволяют разработчику выбирать, какие метки могут быть и какова их семантика.
Это потребует от программиста большой работы, в результате которой появится возможность выполнять статическую проверку.
Под статическим я подразумеваю проверку, которая выполняется во время компиляции и может «отловить» многие типы ошибок информационного потока.
Итак, если вы тщательно пометите все сетевые каналы и каналы экрана с соответствующими разрешениями, а затем аккуратно разместите свои данные, которые показаны на доске в качестве примера, то во время компиляции компилятор сможет сказать вам: «Эй, если вы запустите эту программу, то у вас может произойти утечка информации, потому что часть данных пройдет через ненадежный канал».
На высоком уровне статическая проверка сможет обнаружить многие из этих ошибок, поскольку комментарии типа int {Alice Bob} x немного похожи на типы.
Точно так же, как компиляторы могут обнаруживать ошибки типов на языке типов, они могут аналогичным образом обрабатывать код, написанный на вышеуказанном языке, говоря, что если вы запустите эту программу, это может стать проблемой.
Значит нужно поправить работу тегов, возможно нужно что-то рассекретить и так далее.
Таким образом, в зависимости от языка эти метки могут ассоциироваться с людьми, портами ввода-вывода и тому подобным.
TaintDroid позволяет ознакомиться с принципами работы информационных потоков и утечками информации, однако существуют более сложные системы с более выраженной семантикой управления этими процессами.
Обратите внимание: когда мы говорим о статической проверке, мы предпочитаем выявлять как можно больше сбоев и ошибок, используя статистическую проверку, а не динамическую проверку.
Для этого есть очень деликатная причина.
Допустим, мы отложим все статические проверки до запуска программы, что мы, конечно, можем сделать.
Проблема в том, что неудача или успех этих проверок представляет собой неявный канал.
Таким образом, злоумышленник может предоставить программе некоторую информацию, а затем проверить, не привело ли это к сбою программы.
В случае сбоя хакер может сказать: «Да, мы прошли некоторую проверку динамического потока информации, поэтому должна быть какая-то тайна относительно значений, которые влияют на процесс расчета».
Поэтому вам следует попытаться сделать эти проверки как можно более статичными.
Если вам нужна дополнительная информация об этих вещах, вам следует посетить Jif. Это очень мощная система, создавшая методы расчета меток.
Вы можете начать с этого и двигаться дальше в этом направлении.
Мой коллега профессор Зельдович сделал много хорошего в этой области, поэтому вы можете поговорить с ним на эту тему.
Интересно, что возможности TaintDroid по просмотру и описанию меток весьма ограничены.
Есть системы, которые позволяют делать более мощные вещи.
Наконец, я хотел бы поговорить о том, что мы можем сделать, если хотим отслеживать потоки информации с помощью традиционных программ или программ, написанных на C или C++, которые не поддерживают все эти возможности во время работы кода.
Существует очень умная система под названием TightLip, и некоторые авторы этой же статьи рассматривают, как мы можем отслеживать утечки информации в системе, где мы вообще не хотим ничего менять в самом приложении.
Основная идея заключается в том, что существует концепция процессов-двойников, или «двойников процессов».
Система TightLip по умолчанию использует двойника процесса.
Первое, что он делает, — это периодически сканирует файловую систему пользователя в поисках конфиденциальных типов файлов.
Это может быть что-то вроде файлов электронной почты, текстовых документов и т. д. Для каждого из этих файлов система создает «очищенную» его версию.
То есть в файле электронной почты информация «кому» или «откуда» будет заменена строкой той же длины, содержащей фиктивные данные, например пробелы.
Это выполняется как фоновый процесс.
Второе, что делает TightLip при запуске процесса, — это определяет, пытается ли этот процесс получить доступ к конфиденциальному файлу.
Если такой доступ имеет место, TightLip создает дубликат этого процесса.
Этот дубликат выглядит точно так же, как исходный процесс, который пытается коснуться конфиденциальных данных, но фундаментальное отличие состоит в том, что дубликат, я назову его DG, считывает очищенные данные.
Представьте, что запущен процесс, который пытается получить доступ к вашему файлу электронной почты.
Система порождает новый процесс, doppelganger, точно такой же, как и исходный, но теперь он считывает очищенные данные вместо реальных конфиденциальных данных.
По сути, TightLip запускает оба этих процесса параллельно и наблюдает за ними, чтобы увидеть, что они делают. Если оба процесса выполняют одни и те же системные вызовы с одинаковыми аргументами, то, по-видимому, эти системные вызовы не зависят от конфиденциальных данных.
Другими словами, если я запускаю процесс, который пытается открыть какой-то конфиденциальный файл, я даю ему очищенную версию файла и позволяю ему выполнять свою работу, и если дублирующий процесс делает то же самое, что и обычный процесс, тогда предположительно, конфиденциальные данные вообще не влияют.
По сути, TightLip позволит этим процессам запускаться, а затем проверять наличие системных вызовов.
Однако может случиться так, что в некоторых случаях системные вызовы будут другими.
Например, дубликат начнет делать что-то, чего исходный процесс никогда бы не сделал, например сетевой вызов.
Точно так же, как и в случае с TaintDroid, когда этот двойник пытается совершить сетевой вызов, мы говорим: «Да, нам, наверное, следует прекратить то, что сейчас происходит, и что-то с этим сделать».
Итак, если системные вызовы разные и двойник выполняет сетевой вызов, то мы либо поднимем тревогу, чтобы привлечь внимание пользователя, либо что-то еще.
Как и в случае с TaintDroid, существуют определенные политики, которые вы можете добавить к конкретной системе, которую собираетесь использовать.
Здесь есть интересный момент – так или иначе, на этот процесс – двойник – повлияли возвращенные конфиденциальные данные.
Это означает, что если пользователь не думал, что конкретный процесс будет извлекать конфиденциальные данные, теперь он может проверить программу, чтобы выяснить, почему эта программа намеревалась отправить эти данные по сети.
Студент : Я думаю, что если вы нажмете на что-то вроде файла Word, вы должны знать, что процесс-двойник обнулит именно этот тип файла.
Профессор: да, это хороший вопрос.
Итак, я собирался обсудить некоторые ограничения, и одно из них — это.
Необходимо иметь скраберы для каждого типа файлов.
Вы не можете просто взять программу очистки электронной почты и использовать ее в Word. Потому что если эти скраберы что-то упускают из-за того, что не умеют редактировать определенные типы файлов, то система может не суметь отследить место утечки конфиденциальных данных.
Так что в этом вы абсолютно правы.
Студент: Я так понимаю, процесс должен сначала проверить все данные, прежде чем запускать дубль? В противном случае он может просто отправить в сеть необработанные данные.
Профессор: Нет, это не так.
Двойник может попытаться просмотреть что-то вроде адреса электронной почты, прежде чем попытаться его отправить, но процесс-двойник не должен знать, что он получил эти странные очищенные данные.
Это возвращает нас к проблеме, о которой мы только что говорили.
Если ваш скруббер не «очищает» вещи семантически разумным способом, двойник потерпит неудачу, потому что он ожидал предмета определенного формата, который он не мог получить.
Но на высоком уровне идея состоит в том, что мы пытаемся обманом заставить двойника сделать все как обычно, но только с данными, отличающимися от исходной версии, и посмотреть, возникнет ли это несоответствие.
Единственным недостатком является то, что TightLip по сути помещает скрубберы в TCB, и если они не работают должным образом, процесс-двойник может дать сбой, и мы не сможем обнаружить некоторые нарушения.
Но самое лучшее в этом то, что он работает с устаревшими системами.
Поэтому нам не нужно ничего менять в работе приложения.
Нам просто нужно внести некоторые незначительные изменения в ядро ОС, чтобы иметь возможность отслеживать системные вызовы, а затем продолжить работу.
Это очень полезная функция TightLip. В этом случае системные издержки — это лишь затраты на запуск дополнительного процесса, который не слишком нагружает современную операционную систему.
Это просто удобный способ ограниченного отслеживания вредоносных данных без внесения серьезных изменений в среду выполнения или приложения.
Студент: Запускаем ли мы оба процесса параллельно или ждем завершения каждого из них? Запускаем ли мы оба процесса, а затем проверяем подлинность системных вызовов после их завершения? Профессор: Это хороший вопрос! Пока процесс-двойник DG выполняет на локальном компьютере то, что ОС может контролировать и удерживать, он выполняется параллельно исходному процессу.
Но как только двойник попытается повлиять на внешнее состояние, например, попытается подключиться к сети, или сделать что-то, о чем ядро не знает, в этот момент следует остановить его и объявить проверку успешной.
Всем хорошего Дня Благодарения, увидимся на следующей неделе.
Доступна полная версия курса Здесь .
Спасибо, что остаетесь с нами.
Вам нравятся наши статьи? Хотите увидеть больше интересных материалов? Поддержите нас, разместив заказ или порекомендовав друзьям, Скидка 30% для пользователей Хабра на уникальный аналог серверов начального уровня, который мы придумали для вас: Вся правда о VPS (KVM) E5-2650 v4 (6 Cores) 10GB DDR4 240GB SSD 1Gbps от 20$ или как правильно расшарить сервер? (доступны варианты с RAID1 и RAID10, до 24 ядер и до 40 ГБ DDR4).
VPS (KVM) E5-2650 v4 (6 ядер) 10 ГБ DDR4 240 ГБ SSD 1 Гбит/с бесплатно до января при оплате на срок от шести месяцев и более вы можете заказать здесь .
Dell R730xd в 2 раза дешевле? Только здесь 2 x Intel Dodeca-Core Xeon E5-2650v4 128 ГБ DDR4 6x480 ГБ SSD 1 Гбит/с 100 ТВ от 249 долларов США в Нидерландах и США! Прочтите об этом Как построить корпоративную инфраструктуру класса, используя серверы Dell R730xd E5-2650 v4 стоимостью 9000 евро за копейки? Теги: #информационная безопасность #программирование #ИТ-инфраструктура #Анализ и проектирование систем #отслеживание данных #отслеживание данных #отслеживание данных
-
Google Хочет Читать Ваш Спам
19 Oct, 24 -
Рисование В Google Документах
19 Oct, 24 -
Единый Вход (Sso): Openam + Mod_Auth_Mellon
19 Oct, 24 -
Печать Фотографий Через Интернет
19 Oct, 24 -
Ipod Shuffle – Наконец-То Полезен
19 Oct, 24