Подтвердить что ты не робот

Является ли ошибка в сердцебиении проявлением классического использования переполнения буфера в C?

В одной из наших первых лекций CS по безопасности мы прошли через проблему C, не проверяя предполагаемые длины буфера, и некоторые примеры различных способов использования этой уязвимости.

В этом случае похоже, что это был случай операции злонамеренного чтения, где приложение просто считывало, однако, много байтов памяти

  • Правильно ли я утверждаю, что ошибка Heartbleed является проявлением проблемы проверки длины буфера C?

  • Почему вредоносное использование не вызвало ошибку сегментации при попытке прочитать другую память приложения?

  • Было бы просто обнулить память перед ее записью (а затем и после ее чтения), вызвав ошибку сегментации? Или это зависит от операционной системы? Или между каким-либо другим фактором окружающей среды?

  • По-видимому, использование ошибки не может быть идентифицировано. Это потому, что функция heartbeat не регистрируется при вызове? В противном случае, возможно, какой-либо запрос для строки ~ 64k может быть вредоносным?

4b9b3361

Ответ 1

Правильно ли я утверждаю, что ошибка Heartbleed является проявлением проблемы проверки длины буфера C?

Да.

Является ли ошибка с сердечным приступом проявлением классического эксплойта переполнения буфера в C?

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

Поврежденный дефект по контрасту не перезаписывает буфер и не выполняет произвольный код, он просто считывает за пределы кода, который, скорее всего, будет иметь чувствительные данные в памяти.

Почему вредоносное использование не вызвало ошибку сегментации при попытке прочитать другую память приложения?

Он не пытался читать другую память приложения. Эксплуатация считывает память текущего процесса, а не другого процесса.

Почему вредоносное использование не вызвало ошибку сегментации при попытке считывать память за пределы буфера?

Это дубликат этого вопроса:

Почему это не дает ошибку нарушения сегментации?

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

Dereferencing null является segfault просто потому, что операционная система никогда не делает страницу, содержащую нулевой указатель, действительной страницей.

В более общем плане: компилятор и среда выполнения не требуются для обеспечения того, чтобы поведение undefined приводило к segfault; UB может привести к какому-либо поведению, и в том числе ничего не делать. Для получения дополнительной информации по этому вопросу см.:

Можно ли получить доступ к локальной папке за пределами ее области?

Как я, жалуюсь, что UB всегда должен быть эквивалентом segfault в критическом критически важном коде, а также некоторыми указателями на обсуждение статического анализа уязвимости, см. сегодняшнюю статью в блоге:

http://ericlippert.com/2014/04/15/heartbleed-and-static-analysis/

Было бы просто обнулить память перед ее записью (а затем и после ее считывания), вызвав ошибку сегментации?

Вряд ли. Если чтение за пределами границ не вызывает segfault, то выходить за рамки вряд ли. Возможно, что страница памяти доступна только для чтения, но в этом случае она кажется маловероятной.

Конечно, более поздние последствия обнуления всех видов памяти, которые вам не нужны, - это seg faults во всем шоу. Если есть указатель на эту обнуленную память, которую вы позже разыщите, это разыменование нулевого значения, которое приведет к segfault.

Это зависит от операционной системы?

Вопрос неясен. Позвольте мне перефразировать его.

Существуют ли разные операционные системы и разные библиотеки времени выполнения C/С++, которые предоставляют разные стратегии для распределения виртуальной памяти, выделения кучной памяти и идентификации, когда доступ к памяти выходит за границы?

Да; разные вещи разные.

Или между каким-либо другим фактором окружающей среды?

Такие как?

По-видимому, эксплуатация ошибки не может быть идентифицирована. Это потому, что функция heartbeat не регистрируется при вызове?

Правильно.

Конечно, любой запрос для строки ~ 64k может быть вредоносным?

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

Ответ 2

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

Для ясного объяснения, этот XKCD комикс трудно улучшить:

enter image description here