ПИШЕМ БАЖНУЮ 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 Содержание
|