Разберите следующий фрагмент C: char buf[8]; strcpy(buf, "This is a long string"); — какие типы уязвимостей здесь присутствуют и как их устранить на уровне кода и на уровне проектных решений

8 Мая в 08:09
47 +1
0
Ответы
1
Коротко: здесь — классический выход за пределы буфера (buffer overflow) из‑за использования небезопасной функции `strcpy`. Последствия: перепись памяти на стеке (stack-based buffer overflow), возможное нарушение целостности данных, крах программы, выполнение произвольного кода или утечка информации (в зависимости от контекста).
Почему это происходит
- Буфер: buf size=8\text{buf size} = 8buf size=8.
- Строка `"This is a long string"` занимает string length=21\text{string length} = 21string length=21 символов + терминатор `\0` = 22 \ 22\ 22 байта.
- Переполнение: overflow bytes=22−8=14\text{overflow bytes} = 22 - 8 = 14overflow bytes=22−8=14.
Типы уязвимостей
- Stack-based buffer overflow (перезапись смежной стековой памяти, return address и т.д.).
- Отсутствие проверки границ / небезопасные API (`strcpy`).
- По сценарию — возможность ROP/кодовой инъекции, утечка данных (если смещаются указатели), DoS (крах программы).
Устранение на уровне кода (практические варианты)
1. Использовать ограничивающие функции и проверять длину:
- POSIX/BSD:
- `strlcpy(buf, src, sizeof(buf));` — копирует с обрезкой, проверяйте возврат (если возврат >= sizeof(buf) — усечение).
- Портируемо:
- `snprintf(buf, sizeof buf, "%s", src);` — безопасно по границам.
- C11 Annex K / MS:
- `strncpy_s` / `memcpy_s` с проверкой результата (там, где поддерживается).
2. Выделять динамически нужный размер:
- `char *buf = malloc(strlen(src) + 1); if (!buf) ...; strcpy(buf, src);`
- Или `asprintf(&buf, "%s", src);` (если доступно).
3. Явно проверять длину перед копированием:
- `if (strlen(src) + 1 > sizeof buf) /* обработать ошибку или усечь */;`
4. Предпочитать безопасные абстракции (в C++ — `std::string`).
5. Пример безопасного исправления:
- `char buf[8]; const char *src = "This is a long string"; snprintf(buf, sizeof buf, "%s", src); /* проверить усечение */`
Устранение на уровне проектных решений и окружения
- Компилятор и линковка:
- Включить стековые защиты: `-fstack-protector-strong` / `-fstack-protector-all`.
- Включить защиту времени выполнения: `-D_FORTIFY_SOURCE=2`.
- Включить оптимизации проверки: `-Wstringop-overflow`, `-Wformat-security`.
- Runtime/OS:
- Включить ASLR, NX (DEP), и, где возможно, Control-Flow Integrity (CFI).
- Тестирование и анализ:
- Статический анализ (Coverity, clang-tidy, cppcheck).
- Динамическое тестирование: AddressSanitizer (`-fsanitize=address`), UBSan, fuzzing (libFuzzer, AFL).
- Политики и процессы:
- Код-ревью, стандарты безопасного кодирования (CERT C, MISRA), автотесты на проверку границ.
- По возможности переход на языки с управляемой памятью (Rust, Go) или использование проверенных библиотек для строк.
- Архитектурные меры:
- Минимизировать размер привилегий, разделять компоненты, использовать sandboxing для сниженного ущерба при компрометации.
Итог: правильный код — либо гарантированная проверка длины и использование ограничивающих функций (или динамическое выделение), либо переход на безопасные абстракции; проектно — применять компиляторные и системные защиты, статический/динамический анализ и безопасные практики разработки.
8 Мая в 08:18
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир