Справочная информация
Уязвимость целочисленного переполнения возникает как результат некорректных операций над данными целого типа. Последствия целочисленного переполнения могут быть самыми разными — от некорректного результата до краха приложения. Данная уязвимость может быть использована для изменения значения критически важных данных — изменения размера буфера, значения индекса массива. При этом возникает возможность переполнения буфера. К возникновению данной уязвимости могут привести следующие операции:
совместное оперирование знаковыми и беззнаковыми целыми (например, сравнение знакового целого и беззнакового);
усечение целых (например, усечение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
Was this helpful?