Как можно использовать целочисленное переполнение? - PullRequest
21 голосов
/ 26 мая 2010

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

Ответы [ 5 ]

17 голосов
/ 26 мая 2010

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

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

Подробнее о переполнении целых чисел в ssh: http://www.kb.cert.org/vuls/id/945216

Подробнее о переполнении целых чисел: http://projects.webappsec.org/w/page/13246946/Integer%20Overflows

11 голосов
/ 26 мая 2010

Я использовал APL / 370 в конце 60-х на IBM 360/40. APL - это язык, в котором практически все является многомерным массивом, и есть удивительные операторы для манипулирования массивами, включая изменение формы от N измерений до M измерений и т. Д.

Неудивительно, что массив из N измерений имел границы индекса 1..k с различным положительным k для каждой оси .. и юридически k всегда было меньше 2 ^ 31 (положительные значения в 32 немного подписал машинное слово). Теперь массив из N измерений имеет место, назначенное в памяти. Попытки получить доступ к слоту массива с использованием индекса, слишком большого для оси, проверяются по верхней границе массива с помощью APL. И, конечно, это относится к массиву из N измерений, где N == 1.

APL не проверял, не сделали ли вы что-то невероятно глупое с оператором RHO (изменение формы массива). APL допускает не более 64 измерений. Таким образом, вы можете создать массив размером 1-64, и APL сделает это, если все размеры массива будут меньше 2 ^ 31. Или вы можете попытаться создать массив размером 65 . В этом случае APL дурачился и неожиданно возвращал массив из 64 измерений, , но не смог проверить размеры оси. (Это действительно там, где произошло «переполнение целых чисел»). Это означало, что вы можете создать массив с размерами осей 2 ^ 31 или более ... но интерпретируемые как целые числа со знаком, они трактуются как отрицательные числа.

Правильное заклинание оператора RHO, примененное к такому массиву, может уменьшить размерность до 1, с верхней границей, получить это «-1». Назовите эту матрицу "червоточиной" (вы поймете, почему в данный момент). Такой массив червоточин имеет место в памяти, как и любой другой массив. Но все обращения к массиву проверяются по верхней границе ... но проверка привязки к массиву оказалась выполненной с помощью unsigned сравнения по APL. Таким образом, вы можете получить доступ к WORMHOLE [1], WORMHOLE [2], ... WORMHOLE [2 ^ 32-2] без возражений. По сути, вы можете получить доступ ко всей памяти машины.

В APL также была операция присвоения массива, в которой вы могли заполнить массив значением. WORMHOLE [] <- 0 обнуляет <em>все памяти.

Я сделал это только один раз, поскольку он стер память, содержащую мое рабочее пространство APL, интерпретатор APL и, очевидно, критическую часть APL, которая включала разделение времени (в те дни он не был защищен от пользователей) ... терминал номер перешел из своего обычного состояния с механически очень шумным (у нас было 2741 терминалов Selectric APL) в беззвучный режим примерно через 2 секунды. Сквозь стекло в компьютерную комнату я видел оператора, пораженного огнем 370, когда они все погасли. Много бега вокруг последовало.

Хотя в то время это было забавно, я держал рот на замке.

С некоторой осторожностью, очевидно, можно было вмешаться в ОС произвольным образом.

4 голосов
/ 26 мая 2010

Зависит от того, как используется переменная. Если вы никогда не принимаете никаких решений безопасности, основанных на целых числах, которые вы добавили с входными целыми числами (когда злоумышленник может спровоцировать переполнение), тогда я не могу думать о том, как у вас могут возникнуть проблемы (но такие вещи могут быть тонкими).

Опять же, я видел много такого кода, который не проверяет пользовательский ввод (хотя этот пример придуман):

int pricePerWidgetInCents = 3199;
int numberOfWidgetsToBuy = int.Parse(/* some user input string */);
int totalCostOfWidgetsSoldInCents = pricePerWidgetInCents * numberOfWidgetsToBuy; // KA-BOOM!

// potentially much later
int orderSubtotal = whatever + totalCostOfWidgetInCents;

Все до предела, пока вы не продадите 671 299 виджетов за - 21 474 817,95 долларов США. Босс может быть расстроен.

3 голосов
/ 01 июня 2010

Я просто хотел подвести итог всему, что я узнал о моем первоначальном вопросе.

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

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

Надеюсь, это поможет.

3 голосов
/ 26 мая 2010

Распространенным случаем может быть код, который предотвращает переполнение буфера, запрашивая количество вводимых данных, а затем пытаясь применить это ограничение. Рассмотрим ситуацию, когда я утверждаю, что предоставляю 2 ^ 30 + 10 целых чисел. Принимающая система выделяет буфер 4 * (2 ^ 30 + 10) = 40 байт (!). Поскольку выделение памяти прошло успешно, я могу продолжить. Проверка буфера ввода не остановит меня, когда я отправлю свой 11-й вход, так как 11 <2 ^ 30 + 10. И все же я переполню фактически выделенный буфер. </p>

...