ПИШЕМ БАЖНУЮ CGI`ШКУ НА C

Спецвыпуск Xakep, номер #022, стр. 022-026-3


Данной ошибке подвержены следующие функции: все функции семейства printf (sprintf, fprintf, vsprintf и т.д.), функции семейства scanf (если форматная строка ввода формируется с использованием введенных пользователем строк), функции, основанные на printf - syslog, setproctitle и т.д.

Рекомендация одна - "не ленись" и пиши полный вариант вызова, а также осторожно используй введенные пользователем строки при формировании форматной строки.

3. Чтение и запись произвольных файлов

При использовании введенных пользователем строк в качестве имен файлов в функциях open, fopen надо отфильтровывать из введенных строк символы '.'(если '.' по каким-либо причинам нужна, тогда надо отфильтровывать '\..', '/..', '../' и '..\').

Пример грамотного кода, который сначала отфильтровывает точки и только потом использует для создания директории введенную строку:

char buf[1024] ={0};;

fgets (stdin, sizeof(buf)/sizeof(buf[0]), buf);

for (int j = 0, i = 0; ; ++i)

{

if (buf[i] != '.')

buf[j++] = buf[i];

if (!buf[i]) break;

}

mkdir (buf);

Данную фильтрацию надо применять для всех функций работы с файлами - open, fopen, mkdir, rmdir, chdir, tempnam, tmpnam, функции exec, функции spawn.

4. Функция system

Для выполнения системных утилит или для вызова других программ часто используется функция system. Если строки, введенные пользователем, используются в функции system, то их надо обязательно брать в кавычки. При этом если исходная строка уже содержала кавычки, то их надо отфильтровывать (если кавычки в строке все-таки необходимы, тогда их нужно эскейпить - заменяя на две кавычки подряд или на слэш кавычки, в зависимости от используемой системы).

Посылаем введенную пользователем строку себе на WinPopup:

std::string s;

std::cin >> s;

std::string s2 = "net send 127.0.0.1 ";

for (std::string::iterator it = s.begin(); it != s.end(); ++it)

{

if (*it == '"') s2+= '"'; //или s2+='\\'

s2+= *it;

}

std::system (s2);

EXIT(0)

В данной статье я рассмотрел только самые широко распространенные ошибки, за бортом остались мелкие и специфичные ошибки, а также те ошибки, которые невозможно (очень сложно) использовать для внедрения exploit`а.

Напоследок я могу сказать только одно: проверяй и еще раз проверяй все введенные параметры, которые приходят со стороны пользователя. Проверяй даже в том случае, если эти параметры формируются твоим кодом, т.к. если программа стоит у пользователя, ее легко взломать и подправить передаваемые параметры либо написать свою программу, которая будет опять же генерировать "плохие" данные. Еще лучше, если данные, приходящие от пользователя, не используются напрямую, а используются только косвенно. Так, если cgi-шка работает с файлами, то название файла лучше не передавать на сторону клиента, а лучше сохранить в массиве, а клиенту отдать только индекс; при получении индекса от клиента обратно проверить его на корректность и достать название файла из массива по этому индексу.

Назад на стр. 022-026-2  Содержание