Безопасное кодирование - Secure coding
Безопасное кодирование - это практика разработки компьютерного программного обеспечения таким образом, чтобы не допустить случайного появления уязвимостей в системе безопасности . Дефекты, ошибки и логические ошибки неизменно являются основной причиной часто используемых уязвимостей программного обеспечения. Проанализировав тысячи обнаруженных уязвимостей, специалисты по безопасности обнаружили, что большинство уязвимостей возникает из-за относительно небольшого количества распространенных ошибок программирования программного обеспечения. Выявляя небезопасные методы кодирования, которые приводят к этим ошибкам, и обучая разработчиков безопасным альтернативам, организации могут предпринять упреждающие шаги, чтобы помочь значительно уменьшить или устранить уязвимости в программном обеспечении перед развертыванием.
Предотвращение переполнения буфера
Переполнение буфера , распространенная уязвимость системы безопасности программного обеспечения, происходит, когда процесс пытается сохранить данные за пределами буфера фиксированной длины. Например, если имеется 8 ячеек для хранения предметов, возникнет проблема, если будет предпринята попытка сохранить 9 предметов. В памяти компьютера переполненные данные могут перезаписать данные в следующем месте, что может привести к уязвимости системы безопасности (разбиение стека) или завершению программы (ошибка сегментации).
Пример программы C, склонной к переполнению буфера:
int vulnerable_function(char * large_user_input) {
char dst[SMALL];
strcpy(dst, large_user_input);
}
Если пользовательский ввод больше целевого буфера, произойдет переполнение буфера. Чтобы исправить эту небезопасную программу, используйте strncpy, чтобы предотвратить возможное переполнение буфера.
int secure_function(char * user_input) {
char dst[BUF_SIZE];
// copy a maximum of BUF_SIZE bytes
strncpy(dst, user_input, BUF_SIZE);
}
Другая безопасная альтернатива - динамически выделять память в куче с помощью malloc .
char * secure_copy(char * src) {
size_t len = strlen(src);
char * dst = (char *) malloc(len + 1);
if (dst != NULL) {
strncpy(dst, src, len);
// append null terminator
dst[len] = '\0';
}
return dst;
}
В приведенном выше фрагменте кода программа пытается скопировать содержимое src в dst, а также проверяет возвращаемое значение malloc, чтобы убедиться, что для целевого буфера можно выделить достаточно памяти.
Предотвращение атак с форматной строкой
Формат атака Строки , когда злоумышленник поставляет конкретные материалы , которые в конечном итоге будут введены в качестве аргумента в функцию , которая выполняет форматирование, такие как Е () . Атака включает в себя чтение злоумышленником или запись в стек .
Функция C printf записывает вывод в stdout. Если параметр функции printf не отформатирован должным образом, может появиться несколько ошибок безопасности. Ниже представлена программа, уязвимая для атаки на строку формата.
int vulnerable_print(char * malicious_input) {
printf(malicious_input);
}
Вредоносный аргумент, переданный программе, может быть «% s% s% s% s% s% s% s», что может привести к сбою программы из-за неправильного чтения памяти.
Предотвращение целочисленного переполнения
Целочисленное переполнение происходит, когда арифметическая операция приводит к тому, что целое число слишком велико для представления в доступном пространстве. Программа, которая неправильно проверяет целочисленное переполнение, вводит потенциальные программные ошибки и эксплойты.
Ниже приведена функция на C ++, которая пытается подтвердить, что сумма x и y меньше или равна определенному значению MAX:
bool sumIsValid_flawed(unsigned int x, unsigned int y) {
unsigned int sum = x + y;
return sum <= MAX;
}
Проблема с кодом в том, что он не проверяет целочисленное переполнение при операции сложения. Если сумма x и y больше максимально возможного значения an unsigned int
, операция сложения переполнится и, возможно, приведет к значению, меньшему или равному MAX, даже если сумма x и y больше MAX.
Ниже приведена функция, которая проверяет переполнение, подтверждая, что сумма больше или равна как x, так и y. Если бы сумма переполнилась, сумма была бы меньше x или меньше y.
bool sumIsValid_secure(unsigned int x, unsigned int y) {
unsigned int sum = x + y;
return sum >= x && sum >= y && sum <= MAX;
}
Предотвращение обхода пути
Обход пути - это уязвимость, при которой пути, предоставленные из ненадежного источника, интерпретируются таким образом, что возможен неавторизованный доступ к файлам.
Например, рассмотрим сценарий, который извлекает статью по имени файла, которое затем считывается сценарием и анализируется . Такой сценарий может использовать следующий гипотетический URL-адрес для получения статьи о корме для собак :
https://www.example.net/cgi-bin/article.sh?name=dogfood.html
Если в сценарии нет проверки ввода, вместо этого злоумышленник может подделать URL-адрес для получения файлов конфигурации с веб-сервера , полагая, что имя файла всегда действительное :
https://www.example.net/cgi-bin/article.sh?name=../../../../../etc/passwd
В зависимости от сценария, это может открыть файл / etc / passwd , который в Unix-подобных системах содержит (среди прочего) идентификаторы пользователей , их имена для входа , пути к домашним каталогам и оболочки . (Смотрите SQL-инъекцию для подобной атаки.)
Смотрите также
Примечания
использованная литература
- Тейлор, Искусство; Брайан Бюдж; Рэнди Лэйман (2006). Взлом открытых J2EE и Java . McGraw-Hill Primis. п. 426. ISBN. 0-390-59975-1.