"Средний человек не хочет быть свободным, он просто хочет быть в безопасности". - H. Л. Менкен
Я пытаюсь написать очень безопасный C. Ниже я перечисляю некоторые методы, которые я использую и спрашиваю, они такие же безопасные, как я считаю. Пожалуйста, не стесняйтесь оторвать мой код/предубеждения в клочья. Любой ответ, который находит даже самую тривиальную уязвимость или учит меня новой идее, будет высоко оценен.
Чтение из потока:
В соответствии с учебником по программированию GNU C getline:
Функция getline будет автоматически увеличить блок памяти по мере необходимости, через realloc функции, поэтому никогда не бывает недостатка пространства - одна из причин, почему getline - это так безопасно. [..] Обратите внимание, что getline может безопасно обрабатывать вашу линию ввода, нет вопрос, как долго это длится.
Я предполагаю, что getline должен под всеми входами, предотвратить переполнение буфера, возникающее при чтении с поток.
- Является ли мое предположение правильным? Существуют ли входы и/или схемы распределения, при которых это может привести к эксплойту? Например, если первый символ из потока - это странный символ управления, возможно 0x08 BACKSPACE (ctl-H).
- Проделана ли какая-либо работа, чтобы математически доказать, что getline является безопасным?
Malloc возвращает Null при сбое:
Если malloc обнаруживает ошибку, malloc возвращает указатель NULL. Это представляет угрозу безопасности, поскольку все еще можно применить арифметику указателя к указателю NULL (0x0), таким образом wikipedia рекомендует
/* Allocate space for an array with ten elements of type int. */
int *ptr = (int*)malloc(10 * sizeof (int));
if (ptr == NULL) {
/* Memory could not be allocated, the program should handle
the error here as appropriate. */
}
Безопасный sscanf:
При использовании sscanf Я привык выделять строки, которые нужно удалить, до размера строка ввода, надеюсь, избегает возможности перерасхода. Например:
const char *inputStr = "a01234b4567c";
const char *formatStr = "a%[0-9]b%[0-9]c":
char *str1[strlen(inputStr)];
char *str2[strlen(inputStr)];
sscanf(inputStr, formatStr, str1, str2);
Поскольку str1 и str2 - это размер вводаStr, и не больше символов, чем strlen (inputStr), можно читать из inputStr, это кажется невозможным, если задано все возможные значения для вводаStr, чтобы вызвать буфер переполнение?
- Правильно ли я? Есть ли странные угловые случаи, о которых я не думал?
- Есть ли лучшие способы написать это? Библиотеки, которые уже решили это?
Общие вопросы:
Пока я опубликовал большое количество вопросов, я не ожидаю, что кто-нибудь ответит на все из них. Вопросы более ориентированы на те ответы, которые я ищу. Я действительно хочу научиться защищенному умению C.
- Какие еще безопасные C-идиомы существуют?
- Какие угловые случаи мне нужны, чтобы всегда проверять?
- Как я могу написать модульные тесты для обеспечения соблюдения этих правил?
- Как я могу применять ограничения в тестируемости или доказуемо правильно?
- Любая рекомендуемая статическая/динамическая аналитическая техника или инструменты для C?
- Какими безопасными методами вы придерживаетесь, и как вы их оправдываете себе и другим?
Ресурсы:
Многие из ресурсов были заимствованы из ответов.
- Защищенное программирование для Linux и Unix HOWTO Дэвида Уилера
- Защищенное программирование C - SUN Microsystems
- Небезопасное программирование по примеру
- Добавить больше NOPS - блог, посвященный этим проблемам.
- Инициатива безопасного кодирования CERT
- flawfinder - инструмент статического анализа
- Использование Thm Provers для доказательства безопасности от Yannick Moy
- libsafe