getline(cin, username);
Буфер строки username
free()
.Проблема переполнения буфера возникает при работе с любыми статическими массивами, а не только со строками. При написании безопасных программ следует тщательно проверять, не осуществляется ли запись в массив за его пределами.
10.6.2. Конкуренция доступа к каталогу /tmp
Другая распространенная проблема безопасности связана с созданием файлов с предсказуемыми именами, в основном в каталоге /tmp
prog
, выполняющаяся от имени пользователя root
, всегда создает временный файл /tmp/prog
и помещает в него важную информацию. Тогда злоумышленник может заранее создать символическую ссылку /tmp/prog
на любой другой файл в системе. Когда программа попытается создать временный файл, функция open()
завершится успешно, но в действительности вернет дескриптор символической ссылки. Любые данные, записываемые во временный файл, окажутся перенаправленными в файл злоумышленника.В такой ситуации говорят о конкуренции. Она неявно существует между автором программы и хакером. Кто первым успеет создать временный файл, тот и победит.
Посредством этой атаки часто уничтожаются системные файлы. Создав нужную символическую ссылку, хакер может заставить программу, выполняющуюся с правами суперпользователя, затереть важный системный файл, например /etc/passwd
Один из способов избежать такой атаки — создавать временные файлы со случайными именами. Например, можно прочитать из устройства /dev/random
Другой подход заключается в вызове функции open()
O_EXCL
. Он заставляет функцию завершиться неудачей, если обнаруживается факт существования файла. К сожалению, это не срабатывает, если программа работает через NFS. Нельзя заранее предсказать, в какой файловой системе будет находиться программа, поэтому рассчитывать только на флаг O_EXCL
нельзя.В разделе 2.1.7, "Временные файлы", рассказывалось о применении функции mkstemp()
O_EXCL
после того, как было выбрано трудно угадываемое имя. Другими словами, применять функцию небезопасно, если каталог /tmp
смонтирован через NFS.[35]Прием, который всегда работает, заключается в вызове функции lstat()
В листинге 10.5 представлена функция, которая пытается безопасно открыть файл в каталоге /tmp
#include
#include
#include
#include
/* Функция возвращает дескриптор созданного временного файла.
Файл будет доступен для чтения и записи только тому
пользователю, чей идентификатор равен эффективному
идентификатору текущего процесса. Если файл не удалось создать,
возвращается -1. */
int secure_temp_file() {
/* Этот дескриптор ссылается на устройство /dev/random, из
которого будут получены случайные данные. */
static int random_fd = -1;
/* Случайное целое число. */
unsigned int random;
/* Буфер для преобразования числа в строку. */
char filename[128];
/* дескриптор создаваемого временного файла. */
int fd;
/* информация о созданном файле. */
struct stat stat_buf;
/* Если устройство /dev/random еще не было открыто,
открываем его. */
if (random_fd == -1) {