Хакинг: искусство эксплойта, 2-е издание

Хакинг: искусство эксплойта, 2-е издание
Автор: Джон Эриксон
Год: 2010
ISBN: 978-5-93286-158-5
Страниц: 510
Язык: Русский
Формат: PDF
Размер: 10 Мб

Download

Хакинг – это искусство творческого решения задач, подразумевающее нестандартный подход к сложным проблемам и использование уязвимостей программ. Часто бывает трудно разобраться в методах хакинга, потому что для этого нужны широкие и глубокие знания.
Автор не учит применять известные эксплойты, а объясняет их работу и внутреннюю сущность. Вначале читатель знакомится с основами программирования на C, ассемблере и языке командной оболочки, учится исследовать регистры процессора. А усвоив материал, можно приступать к хакингу – перезаписывать память с помощью переполнения буфера, получать доступ к удаленному серверу, скрывая свое присутствие, и перехватывать соединения TCP. Изучив эти методы, можно взламывать зашифрованный трафик беспроводных сетей, успешно преодолевая системы защиты и обнаружения вторжений.
Книга дает полное представление о программировании, машинной архитектуре, сетевых соединениях и хакерских приемах. С этими знаниями ваши возможности ограничены только воображением.

+

Программирование

Теперь, когда ваше представление о программировании стало более конкретным, следует познакомиться с некоторыми другими важными аспектами языка С. Ассемблер и процессоры появились раньше языков программирования высокого уровня, и за это время в программировании возникло много новых идей. Подобно тому как некоторое знакомство с латынью может заметно помочь более глубокому пониманию английского языка, представление о низкоуровневом программировании может облегчить понимание программирования на языках более высокого уровня. Переходя к следующему разделу, не забывайте, что код С может что-либо сделать лишь после того, как будет скомпилирован в машинные команды.

Опираясь на основы

После того как вы разберетесь с основными понятиями программирования на С, все остальное достаточно легко. Основу мощи С составляет использование функций. Если убрать функции из любой предыдущей программы, останутся только очень простые операторы.

Доступ к файлам

В С применяются два основных способа работы с файлами: через дескрипторы файла и файловые потоки. Дескрипторы файла используются группой функций низкоуровневого ввода/вывода, а файловые потоки (filestreams) представляют собой буферизованный ввод/вывод более высокого уровня, построенный на функциях низкого уровня. Некоторые считают, что программировать с применением функций файловых потоков проще, однако дескрипторы файла обеспечивают большую непосредственность. В данной книге нас будут интересовать функции низкоуровневого ввода/вывода, использующие дескрипторы файла.

Штрих-код на обороте этой книги представляет некоторое число. Каждой книге, которая есть в магазине, соответствует свое число, по этому числу кассир получает сведения о книге из базы данных. Аналогичным образом дескриптор файла – это число, с помощью которого можно обращаться к открытым файлам. Есть четыре стандартные функции, использующие дескрипторы файла: open(), close(), read() и write(). Все они в случае возникновения ошибки возвращают —1. Функция ореп() открывает файл для чтения и/или записи и возвращает дескриптор файла. Этот дескриптор является целым числом, соответствующим только одному открытому файлу. Дескриптор файла передается как аргумент другим функциям в качестве указателя на открытый файл. У функции close() дескриптор файла – единственный аргумент. Для функций read() и write() аргументами являются дескриптор файла, указатель на данные, которые нужно считать или записать, и количество байт, которые нужно записать или считать по этому адресу. Аргументы функции ореп() – указатель на имя файла, который нужно открыть, и ряд флагов, описывающих метод доступа к файлу…

Эксплойты

Общая технология эксплойта

Ошибки на единицу или возникающие при трансляции Unicode относятся к числу тех, которые трудно заметить в момент написания кода, но впоследствии их распознает любой программист. Однако есть несколько распространенных ошибок, на которых основаны далеко не столь очевидные эксплойты. Влияние этих ошибок на безопасность не всегда заметно, и соответствующие проблемы с защитой распространены по всему коду. Поскольку одни и те же ошибки совершаются в разных местах, для них были разработаны обобщенные методы эксплойтов, которыми можно воспользоваться в различных ситуациях.

Переполнение буфера

Подробно код этого эксплойта обсуждается ниже, а общий его смысл в том, чтобы сгенерировать командную строку, которая вызовет программу notesearch, передав ей аргумент в одиночных кавычках. Для этого применяются функции работы со строками: strlen() для получения длины строки (чтобы установить указатель на буфер) и strcat() для дописывания в конец одиночной кавычки. Наконец, командная строка выполняется с помощью функции system. Буфер, помещаемый между кавычками, это главная часть эксплойта. Все остальное служит лишь средством доставки этой отравленной пилюли. Посмотрите, что можно сделать при контроле над аварийным завершением.

Эксперименты с BASH

Поскольку хакинг в значительной мере состоит из эксплойтов и экспериментов, очень важно иметь возможность быстро опробовать те или иные вещи. Оболочка BASH и Perl есть на большинстве машин, они предоставляют все необходимое для проведения опытов с эксплойтами.

Perl – интерпретируемый язык программирования, команда print которого очень удобна для создания длинных последовательностей символов. Perl позволяет организовать выполнение инструкций в командной строке с помощью ключа -е:

Переполнения в других сегментах

Помимо переполнений в стеке возможны переполнения буфера в других сегментах – кучи и bss. Как и в auth_overflow.c, если важные переменные расположены в памяти после буфера, который может переполниться, появляется возможность изменить порядок выполнения программы. Это не зависит от того, в каком сегменте располагаются переменные, однако возможности управления программой при этом весьма ограничены. Для того чтобы найти такие критические точки и максимально их использовать, нужны опыт и творческий подход. Этот тип переполнений менее стандартизирован, чем переполнения в стеке, но они могут оказаться не менее эффективными.

Типичное переполнение в куче

Программа notetaker из главы 2 (0x200) также уязвима для переполнения буфера. В ней есть два буфера, размещаемых в куче, и первый аргумент командной строки копируется в первый буфер. При этом может возникнуть переполнение.

Сокеты

Сокет – это стандартный способ организации обмена данными в сети с помощью операционной системы. Сокет можно представить в виде конечной точки соединения – вроде гнезда на ручном телефонном коммутаторе. При этом для программиста сокеты лишь абстракция всех технических деталей описанной выше модели OSI. Программист пользуется сокетами для передачи или приема данных по сети. Эти данные передаются на сеансовом уровне (5) (см. рис. 4.1) над нижними уровнями (заботу о которых берет на себя операционная система), обеспечивающими маршрутизацию. Есть несколько типов сокетов, которые определяют структуру транспортного уровня (4). Чаще всего применяются сокеты потоков и сокеты дейтаграмм.

Сокеты потоков предоставляют надежную двустороннюю связь, которую можно сравнить с телефонным соединением. Одна из сторон инициирует соединение с другой, и после того как соединение установлено, обе стороны могут общаться между собой. При этом вы сразу получаете подтверждение того, что сказанное вами достигло адресата. Сокеты потоков используют стандартный протокол связи Transmission Control Protocol (TCP), соответствующий транспортному уровню (4) модели OSI. В компьютерных сетях данные обычно передаются блоками, которые называют пакетами. TCP спроектирован так, чтобы данные поступали без ошибок и в правильном порядке, подобно тому как в телефонном разговоре слова поступают адресату в том порядке, в котором вы их произносите. Веб-серверы, почтовые серверы и клиенты тех и других используют для связи TCP и сокеты потоков.

Другой распространенный тип сокетов – сокеты дейтаграмм. Связь через сокеты дейтаграмм больше напоминает отправку письма, чем телефонный разговор. Соединение является односторонним и ненадежным. Отправляя по почте несколько писем, вы не уверены, что они придут в том же порядке, да и вообще достигнут адресата. Почтовая служба, однако, достаточно надежна в сравнении с Интернетом. В сокетах дейтаграмм на транспортном уровне (4) используется другой стандартный протокол – UDP, а не TCP. UDP (User Datagram Protocol – протокол дейтаграмм пользователя) служит для создания индивидуальных пользовательских протоколов. Это очень простой и облегченный протокол, у него очень мало средств защиты. Он не обеспечивает реальное соединение, а только предоставляет элементарный способ отправить данные из одной точки в другую. Сокеты дейтаграмм требуют очень низких накладных расходов на протокол, но и возможности протокола весьма ограниченны. Если программе требуется подтверждение того, что пакет получен адресатом, в коде принимающей программы должна быть предусмотрена отправка пакета-подтверждения. В некоторых ситуациях потеря пакета допустима.

Сокеты дейтаграмм и UDP часто используются в сетевых играх и потоковом вещании, где разработчики могут организовать связь так, как им нужно, не расходуя дополнительные ресурсы на TCP.

Анализ сетевых пакетов (сниффинг)

На канальном уровне пролегает различие между коммутируемыми и некоммутируемыми сетями. В некоммутируемой сети (unswitched network) пакеты Ethernet проходят через каждое имеющееся в сети устройство в предположении, что любое устройство будет рассматривать только адресованные ему пакеты. Однако довольно легко задать для устройства неразборчивый режим {promiscuous mode), в котором оно будет принимать все пакеты независимо от их адресата. Большинство программ перехвата пакетов, таких как tcpdump, по умолчанию переводят прослушиваемое ими устройство в неразборчивый режим. Неразборчивый режим можно установить с помощью команды ifconfig, как показывает следующий листинг.

Отказ в обслуживании

Один из простейших видов сетевых атак – отказ в обслуживании (DoS – Denial of Service).
При DoS-атаке не крадется информация, а просто нарушается доступность службы или ресурса. Есть два главных вида DoS-атак: в одном случае служба аварийно завершается, в другом не справляется с чрезмерной нагрузкой.

DoS-атаки, приводящие к аварийному завершению сервисов, ближе к программным, чем к сетевым эксплойтам. Часто эти атаки основаны на уязвимостях реализации, предлагаемой конкретным производителем. Неудачный эксплойт на основе переполнения буфера обычно приводит к аварийному завершению атакуемой программы вместо выполнения ею внедренного шелл-кода. Если эта программа выполняется на сервере, служба оказывается недоступной для всех клиентов. Вызывающие аварийное завершение DoS-атаки обычно привязаны к конкретным версиям конкретных программ. Поскольку стек сетевых протоколов обрабатывается операционной системой, авария в таком коде выводит из строя ядро и вызывает отказ всей машины. Многие из подобных уязвимостей в большинстве современных операционных систем устранены, но все же полезно рассмотреть, как такие приемы могут применяться в различных ситуациях.

Взлом паролей

Обычно пароли не хранят в виде обычного текста. Файл, содержащий в открытом виде все пароли, был бы слишком заманчивой целью, поэтому здесь применяется однонаправленная хеш-функция. Самая известная из этих функций основана на DES и называется crypt(), ниже приведена ее страница руководства.

Эта однонаправленная хеш-функция принимает на входе открытый пароль и значение salt (привязка), а выводит значение хеша, которому предшествует введенное значение salt. Хеш-значение математически необратимо, то есть одного его недостаточно, чтобы определить исходный пароль. Напишем простую программу, чтобы поэкспериментировать с этой функцией и лучше разобраться в ее работе.