Техника сетевых атак
Шрифт:
· copy con myfile
· Hello, World!
· ^Z
· 1 файлов скопировано
·
· copy myfile con
· Hello, World!
· 1 файлов скопировано
Начинающим, вероятно, следует пояснить - символ «Ctrl-Z» указывает программе на завершение ввода и конец файла. В самом файле он отсутствует.
В качестве другого примера используем коротенькую демонстрационную
· #include «stdio.h»
· int main(int argc, char *argv[])
· {
· char buf[100],out[7],tmp,p=0;
· FILE *f;
· f=fopen(argv[1],"r");
· fgets( amp;buf[0],100,f);
· fclose(f);
· f=fopen(argv[2],"w");
· while(buf[p])
· {
· sprintf( amp;out[0],"0x%X\n",buf[p++]);
· fputs( amp;out[0],f);
·}
· return 0;
·}
Она читает одну строку из файла, переданного в качестве первого аргумента командной строки, и записывает во второй ASCII коды символов в шестнадцатеричном представлении. Например, так:
· io.exe con con
· Hello, Sailor!
· 0x48
· 0x65
· 0x6C
· 0x6C
· 0x6F
· 0x2C
· 0x20
· 0x53
· 0x61
· 0x69
· 0x6C
· 0x6F
· 0x72
· 0x21
· 0xA
Характерная особенность этой (да и многих других) программ - использование клавиатуры и терминала для приема и отображения информации. Но постоянно указывать ‘con con’ слишком утомительно, гораздо лучше заранее назначить устройства ввода-вывода по умолчанию.
В стандартной библиотеке языка Си для этой цели используются файловые манипуляторы stdin и stdout, связанные со стандартными устройствами ввода и вывода соответственно. Модернизированный вариант программы может выглядеть так (на диске он находится под именем “/SRC/iostd.c”):
· #include «stdio.h»
· int main(int argc, char *argv[])
· {
· char buf[100],out[7],tmp,p=0;
· fgets( amp;buf[0],100,stdin);
· while(buf[p])
· {
· sprintf( amp;out[0],"0x%X\n",buf[p++]);
· fputs( amp;out[0],stdout);
·}
· return 0;
·}
Но как в этом случае заставить программу выводить результаты работы в файл, а не терминал? Стандартный ввод-вывод выгодно отличается возможностью направить его куда угодно, указав в командной строке специальный символ “»” для вывода и “«” для ввода.
Например, используем ранее созданный файл myfile и выведем результат работы iostd в файл “out.txt”. Это можно сделать следующим образом:
· iostd.exe «myfile»out.txt
· 0x48
· 0x65
· 0x6C
· 0x6C
· 0x6F
· 0x2C
· 0x20
· 0x53
· 0x61
· 0x69
· 0x6C
· 0x6F
· 0x72
· 0x21
· 0xA
· 1 файлов скопировано
Да, это работает! Но как? Командный интерпретатор при запуске анализирует командную строку и если обнаруживает символы перенаправления ввода-вывода, открывает соответствующие файлы и связывает с ними потоки ввода-вывода.
Перенаправление ввода-вывода полезная штука, но зачастую слишком уж уязвимая для атак. Рассмотрим следующий код (расположенный на диске под именем “/SRC/iohack.c”), часто встречающийся в UNIX-приложениях.
· #include «stdio.h»
· main
· {
· FILE *f;
· char buf[100],c=2;
· printf("$");
· fgets( amp;buf[0],100,stdin);
· if (buf[0]!='«')
· printf("%s\n", amp;buf[0]);
· else
· {
· while(buf[c]!=0xA) c++;
· buf[c]=0;
· if (f=fopen( amp;buf[1],"r"))
· while((c=fgetc(f))!=EOF)
· printf("%c",c);
·}
·}
Программа запрашивает у пользователя строку и выводит ее на экран. Но, если указать знак перенаправления потока ввода, на экран выдастся содержимое запрашиваемого файла! Например:
· iohack.exe
· $Hello!
· Hello!
·
· iohack.exe
· $«myfile
· Hello, Sailor!
С одной стороны, поддержка приложением перенаправления ввода-вывода очень удобна и облегчает работу с компьютером (в самом деле, зачем вводить текст вручную, если его можно взять из файла?), но… часто приводит к последствиям никак не запланированными разработчиком [94].
Приведенный выше пример, запущенный в среде UNIX, встретив конструкцию “«/etc/passwd” выдаст на экран содержимое файла паролей, или любого другого файла который будет запрошен. С первого взгляда ничего страшного в этом нет, - программа наследует все привилегии пользователя и получает доступ к тем, и только к тем, файлам, которые пользователь мог бы просмотреть и без помощи этой программы, скажем, командой “cat”.