Книга: Программирование для Linux. Профессиональный подход
Листинг 10.6. (grep-dictionary.c) Поиск слова в словаре
Листинг 10.6. (grep-dictionary.c) Поиск слова в словаре
#include <stdio.h>
#include <stdlib.h>
/* Функция возвращает ненулевое значение, если аргумент WORD
встречается в файле /usr/dict/words. */
int grep_for_word(const char* word) {
size_t length;
char* buffer;
int exit_code;
/* Формирование строки 'grep -x WORD /usr/dict/words'.
Строка выделяется динамически во избежание
переполнения буфера. */
length =
strlen("grep -х ") + strlen(word) +
strlen(" /usr/dict/words") + 1;
buffer = (char*)malloc(length);
sprintf(buffer, "grep -x %s /usr/dict/words", word);
/* Запуск команды. */
exit_code = system(buffer);
/* Очистка буфера. */
free(buffer);
/* Если команда grep вернула значение 0, значит, слово найдено
в словаре. */
return exit_code == 0;
}
Обратите внимание на подсчет числа символов в строке и динамическое выделение буфера, что позволяет обезопасить программу от переполнения буфера. К сожалению, небезопасна сама функция system()
(описана в разделе 3.2.1, "Функция system()"). Функция вызывает стандартный интерпретатор команд и принимает от него код завершения. Но что произойдет, если злоумышленник вместо слова введет показанную ниже строку?
foo /dev/null; rm -rf /
В этом случае сервер выполнит такую команду:
grep -х foo /dev/null; rm -rf / /usr/dict/words
Теперь проблема стала очевидной. Пользователь запустил одну команду, якобы grep, а на самом деле их оказалось две, так как интерпретатор считает точку с запятой разделителем команд. Первая команда — это по-прежнему безобидный вызов утилиты grep
, зато вторая команда пытается удалить все файлы в системе. Даже если серверная программа не имеет привилегий суперпользователя, она удалит все файлы, доступные запустившему ее пользователю. Похожая проблема возникает и при использовании функции popen()
(описана в разделе 3.4.4, "Функции popen()
и pclose()
"), которая создает канал между родительским и дочерним процессами, но тоже вызывает интерпретатор для запуска команды.
Существуют два способа устранения подобных проблем. Первый заключается в использовании функции семейства exec()
вместо функции system()
или popen()
. Специальные символы интерпретатора команд (например, точка с запятой) не подвергаются обработке, если они присутствуют в списке аргументов функции exec()
. Естественно, при этом пропадают преимущества таких функций, как system()
и popen()
.
Второй способ — проверка строки на предмет "благонадежности". В случае сервера словарей следует убедиться в том, что слово содержит только буквы (для этого предназначена функция isalpha()
). Такое слово не представляет угрозы.
- Листинг 10.1. (simpleid.c) Отображение идентификаторов пользователя и группы
- Ключевые слова
- 1.2.1. Ключевые слова и идентификаторы
- Новые ключевые слова
- Прием 45. «Простые слова. Четкие идеи. Сильные эмоции»
- 13.3.4. Поиск и замена текста
- Листинг 15.11. Код для загрузки файла с Web-сервера
- Фильтры и поиск
- Вот как мы можем повлиять на коммерческий фактор (иными словами, повысить доверие посетителей к сайту)
- 1.3.1. Индексирование сайта в поисковых системах
- Глава 4 Поиск и выбор идеи
- Глава 1 Поиск (Найдется всё!)