Справочная информация

Уязвимость целочисленного переполнения возникает как результат некорректных операций над данными целого типа. Последствия целочисленного переполнения могут быть самыми разными — от некорректного результата до краха приложения. Данная уязвимость может быть использована для изменения значения критически важных данных — изменения размера буфера, значения индекса массива. При этом возникает возможность переполнения буфера. К возникновению данной уязвимости могут привести следующие операции:

  • совместное оперирование знаковыми и беззнаковыми целыми (например, сравнение знакового целого и беззнакового);

  • усечение целых (например, усечение32-битовогоцелого до16-битового);

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

Следующие особенности кода приложения свидетельствуют о потенциальной возможности уязвимости:

  • смешивание знаковых и беззнаковых целых в операциях вычисления и сравнения;

  • смешивание данных различных типов в операциях вычисления и сравнения;

  • сравнение переменных и литералов;

  • отсутствие проверки входных данных;

  • использование результата вычисления без его проверки.

В следующем примере сумма len1+len2 может переполниться таким образом, что len1 > len1 + len2

int foo(int fd) {
    size_t len1 = read_size(fd);
    size_t len2 = read_size(fd);
    char *buf = malloc(len1+len2);
    read_data(fd, buf, len1);
    read_data(fd, buf+len1, len2);
    // ...
}

Поэтому read_data может записать в буфер больше данных, чем доступно памяти в буфере, и затереть таким образом соседние объекты на куче.

Похожая проблема возникает при умножении и даже при неаккуратном прибавлении константного числа.

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

  • ввод отрицательных значений при запросе на ввод целых чисел;

  • ввод целых, соответствующих граничным значениям хранения данных в одном байте, двух байтах и т.д. — т.е. чисел 0, 7, 8, 254, 255, 16353, 16354;

  • ввод очень длинных строк (более 64 К);

  • ввод строк, длина которых равна типичным граничным значениям (32К, 32К-1, 64К-1, 64К);

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

Чтобы минимизировать вероятность возникновения данной уязвимости, следует придерживаться следующих правил:

  • для проверки текстов программ использовать инструментальные средства анализа, обладающие низкой вероятностью ошибок 2-города для уязвимостей данного типа;

  • везде, где возможно, использовать беззнаковые целые;

  • при выделении памяти использовать только беззнаковые целые;

  • при построении индексированных массивов использовать только беззнаковые целые;

  • проверять введенные пользователем числовые данные, разрешая только заведомо корректные данные;

  • при компиляции приложения устанавливать максимально подробный уровень сообщений компилятора.

Last updated