"ТЕХНИКА СЕТЕВЫХ АТАК" - читать интересную книгу автора (Касперский Крис)

Первые шаги с UNIX (глава для начинающих)

O В этой главе:

O Оболочки - что это такое?

O Краткая история оболочек UNIX

O Как узнать какая оболочка выполняется в данный момент

O Как узнать, какие оболочки установлены на компьютере

O Как просмотреть список файлов

O Немного о правах доступа

O Как сменить текущую директорию

O Как создавать и удалять каталоги

O Как можно копировать файлы

O Как просмотреть содержимое файла

O Редактирование файлов с помощью редактора vi

O Фоновое выполнение процессов

O Как узнать список выполняемых процессов в системе

O Как можно «прибить» процесс

O Как пользоваться справочным руководством man


–Ой, Вань, гляди, какие форточки! Балдею, что за красота! А Юникс - буквы все да черточки, И непонятно ни черта. Юрий Нестеренко «Диалог у монитора»

В работе с UNIX нет ничего мистического и освоить простейшие операции можно в течение одного вечера, особенно если воспользоваться толковой книжкой. К счастью, недостатка в литературе испытывать не приходится, но слишком много - так же плохо, как и совсем ничего. Попробуй, выбери одну книжку из десятка, разбросанных по витрине! Поэтому, в «Технику сетевых атак» включена короткая глава, помогающая незнакомым с UNIX сделать свои первые шаги. На звание учебника она не претендует, но, по крайней мере, поясняет основные команды UNIX, используемые в этой книге.

Для UNIX существует множество интерактивных оболочек с развитым пользовательским интерфейсом - от Mortal Commander (аналог Norton Commander) до графических сред аля Windows. Они помогают начинающим освоиться в мире UNIX, но оказываются крайне неудобными для удаленного управления компьютером. Даже текстовой Mortal Commander ощутимо тормозит на модемных каналах. А о графических оболочках вспоминать и вовсе не приходится, - комфортная работа возможна лишь при наличии шустрой локальной сети! Поэтому, придется поступиться некоторыми удобствами, и, расставшись с мышью, разговаривать с компьютером языком текстовых команд. Такое общение с UNIX в чем-то напоминает работу с интерпретатором MS-DOS “command.com”. Разумеется, названия команд окажутся другими, но в целом принцип тот же.

В UNIX (в отличие от MS-DOS) нет стандартной командной оболочки, поэтому первая задача пользователя - выяснить, что именно установлено в системе, и какие альтернативные оболочки доступны.

Путь к используемой в данный момент оболочке содержится в переменной $SHELL и вывести его на экран можно с помощью команды “echo $SHELL” (соблюдая регистр). Результат ее работы может быть следующим:

· Эмулятор UWIN

· echo $SHELL

· /usr/bin/ksh

· Эмулятор CYGWIN

· echo $SHELL

· /bin/sh

Теперь по таблице 3 легко определить, какая именно оболочка запущена (конечно, при условии, что никакие злые духи не изменили имя исполняемого файла).

– Имя файла Название оболочки

– bash Усовершенствованная оболочка Борна

– csh Оболочка С

– ksh Оболочка Корна

– sh Оболочка Борна

– tcsh Оболочка TC


Таблица 3 Имена исполняемых файлов некоторых популярных оболочек

Пару слов об особенностях каждой оболочки. Первой на свет появилась оболочка Борна, фактически представляющая собой язык программирования, ориентированный на управление процессами, вводом-выводом и операции шаблонного поиска. Никакого интерактивного взаимодействия с пользователем в ней не предусматривалось, и вся работа сводилась к написанию управляющих программ - скриптов, обрабатываемых оболочкой.

Первая интерактивная оболочка, получившая название «С», возникла в университете Беркли. Она быстро завоевала популярность, но имела множество недостатков и содержала кучу ошибок, поэтому полностью вытеснить оболочку Борна так и не смогла. Проблема же совместного сосуществования заключалась в полной несовместимости командных языков обоих оболочек. Это приводило к невозможности выполнения скриптов, написанных для одной оболочки, другой оболочкой.

К тому же открытость исходных текстов “С” вызвала появление массы несовместимых между собой клонов. Некоторые из них дожили и до наших дней (как, например, “TC”,- своеобразный гибрид “С” и “TENEX” - операционной системы PDP-10).

Существовали и коммерческие оболочки. Из них наибольшей популярностью пользовалось творение, созданное Дэвидом Корном, объединившее в себе лучшие черты своих предшественников. Компании AT amp;T распространяла ее вместе с операционной системой System V, объявив стандартном де-юре.

Стандарт - хорошо, но платить компании никто не хотел, и вскоре оболочка Борна была полностью переписана в рамках проекта GNU, получив название bash - Borne Again Shell. Многочисленные усовершенствования и перенос в среду LINUX сделали bash самой популярной оболочкой всех времен и народов, хотя многие до сих пор предпочитают пользоваться C-Shell или оригинальной оболочкой Борна. К тому же, по-прежнему не иссякает поток энтузиастов, пишущих свои собственные оболочки.

Во многих случаях различия между оболочками не столь существенны и не отражаются на простейших операциях, но все примеры, приводимые в книге, предназначены для оболочки Корна и их успешное выполнение в других оболочках не гарантируется (хотя и предполагается). Поэтому, полезно знать, какие оболочки установлены администратором на машине. В этом поможет команда “cat /etc/shells”, результат работы которой на свежеустановленном эмуляторе UWIN выглядит следующим образом:

· cat /etc/shells

· /usr/bin/ksh

· /usr/bin/sh

· /usr/bin/tcsh

· /usr/bin/csh

· /bin/sh

· /bin/ksh

· /bin/csh

· /bin/tcsh

Запустить любую оболочку можно, набрав ее имя (возможно, вместе с полным путем), в командной строке. А вернуться назад обычно помогает команда exit. В качестве тренировочного упражнения полезно запустить все доступные оболочки по очереди. (Чаще всего пути ”/usr/bin” и “/bin” указывают на один и тот же каталог, поэтому эквивалентны друг другу).

· $ echo $SHELL

· /usr/bin/ksh

· $ /usr/bin/sh

· # echo $SHELL

· /usr/bin/ksh

· # exit

· $ /usr/bin/tcsh

· # echo $SHELL

· /usr/bin/ksh

· # exit

· $ /usr/bin/csh

· %echo $SHELL

· /usr/bin/ksh

· %exit

Для просмотра содержимого директорий в командном интерпретаторе “command.com” (MS-DOS) предусмотрена встроенная команда “dir”, но UNIX-оболочки не поддерживают такой команды. Вместо этого пользователю предоставляется возможность вызвать внешнюю утилиту, выполняющую всю необходимую работу. Обычно в UNIX для отображения содержимого каталога используется программа ‘ls’, находящаяся в каталоге “/bin”. Кстати, пользователи CYGWIN прежде чем смогут ей воспользоваться, должны скачать с сервера архив fileutils.tar.gz - в минимальный комплект поставки она не входит.

Вызов без параметров выводит на экран содержимое текущего каталога, а заглянуть в корень поможет наклонная черта - “ls /” [91]

· ls /

· A E proc

· base.bat etc reg

· baseserviceslink.sh F sys

· bin H tmp

· C home usr

· D lib var

· dev linka win

Узнать, что находится в каталоге “/etc” можно передав его имя в качестве параметра команде ‘ls’:

· $ ls /etc

· crontab inetdconfig.sh passwd.add traceit

· in.ftpd init.exe priv.exe tracer.exe

· in.rlogind login.allow profile ucs.exe

· in.rshd login.deny rc ums.exe

· in.telnetd mailx.rc services

· inetd.conf mkpasswd.exe shells

· inetd.exe passwd stop_uwin

Конечно же, поддерживаются символы-джокеры, - знаки «звездочка» и «вопрос». В UNIX, в отличие от MS-DOS, существует конструкция [char set], которую имеет смысл рассмотреть подробнее. Но для начала нелишне вспомнить назначение “*” и “?”. Знак “*” обозначает любое множество любых символов (включая пустое), а “?” всего один непустой символ. Поэтому, “ls x*” выведет на экран все файлы (и каталоги), начинающиеся с буквы ‘x’, а “ls?tmp”- покажет ‘_tmp’,’$tmp’ и так далее.

Конечно же, временами гибкости таких шаблонов оказывается недостаточно, например, как быть, когда требуется получить список файлов, начинающихся и на букву ‘i’, и на букву ‘p’? В MS-DOS с этим пришлось бы управляться в два захода, последовательно отдавая команды ‘dir i*’ и ‘dir p*’. К счастью, в UNIX с той же проблемой можно управиться за один присест! Например, так:

· $ ls /etc/[ip]*

· /etc/in.ftpd /etc/inetd.conf /etc/passwd

· /etc/in.rlogind /etc/inetd.exe /etc/passwd.add

· /etc/in.rshd /etc/inetdconfig.sh /etc/priv.exe

· /etc/in.telnetd /etc/init.exe /etc/profile

А как быть, если необходимо отобразить все файлы, в имени которых присутствует хотя бы одна цифра? Неужели придется писать утомительно длительную последовательность ‘ls *[0123456789]*’ [92]? К счастью нет! И необходимый интервал можно задать следующим образом: ‘[0-9]’, например, вот так:

· $ls /etc/*[0-9]*

· /etc/k1y /etc/mkss2old /etc/track7

Если такой информации окажется недостаточно и потребуется узнать, скажем, права доступа к файлу, имя владельца и время последнего изменения, то придется воспользоваться ключом ‘-l’ (маленькая латинская буква L, не спутайте с единицей). Например, так:

· ls -l /etc

· -rwxr-r- 1 root Everyone 46 Feb 16 1999 crontab

· -rwxr-r- 1 root Everyone 19968 Feb 17 1999 mkpasswd.exe

· drwxr-r- 2 root Everyone 512 Jul 2 16:52 mydir

· -rwxr-r- 1 root Everyone 119 Jul 1 12:45 passwd

· lrwxr-r- 1 root Everyone 20 Jun 4 03:10 services -» /C/WINDOWS//services

· -rwxr-r- 1 root Everyone 88 Feb 17 1999 shells

· -rwxr-r- 1 root Everyone 73216 Feb 2 07:25 ums.exe

Первая колонка сообщает права доступа. Она состоит из тех трехсимвольных групп, определяющих права доступа создателя (то бишь владельца файла), его группы и всех остальных пользователей. Каждая группа в свою очередь состоит из трех атрибутов, разрешающих чтение (r), запись (w) и исполнение (x).


- Расшифровка файловых атрибутов

Тут надобно заметить, что в UNIX выполняемые файлы распознаются по атрибуту ‘x’, и могут иметь любое расширение или вовсе не иметь его. Обычно большинство файлов и каталогов имеют следующие права доступа ‘rwxr-r-r’, т.е. создатель файла может делать с ним что угодно, а всем остальным разрешается читать, но не модифицировать или запускать.

Для изменения прав доступа предусмотрена утилита chmod (сокращение от Change Mode). Для того, чтобы действие возымело эффект, необходимо указать группу пользователей (‘u’ - для владельца, ‘g’ - для членов его группы, ‘o’ - для всех прочих и ‘a’ для всех-всех, т.е. ‘u’+’g’+’o’ одновременно), затем наличие (знак ‘+’) или отсутствие (знак ‘-‘) требуемого атрибута. Например, защитить собственные файлы от «чужого глаза» можно с помощью команды ‘chmod g-r,o-r *’.

Директории отличаются от простых файлов по стоящему впереди символу ‘d’ (смотри рисунок 009.txt)


- Директории в UNIX отличаются от файлов наличием атрибута ‘d’

Следующая колонка сообщает количество псевдонимов, под которыми файл (директория) известен системе. Например, для каталога ‘/bin’ это число равно двум, поскольку обычно ‘/bin’ и ‘/usr/bin’ ссылаются на одну и ту же директорию.

· drwxrwxrwx 2 root Everyone 512 Jun 4 00:50 bin

· drwxrwxrwx 3 root Everyone 512 Jun 4 00:51 dev

· drwxrwxrwx 16 root Everyone 512 Jun 4 00:51 lib

Затем идет имя владельца файла (в данном примере ‘root’) и группа, к которой он принадлежит (‘Everyone’). И замыкают строку размер, время создания и имя файла (директории). Вся остальная информация по работе с ‘ls’ содержится в руководстве ‘man’ и может быть получена с помощью команды ‘man ls’.

Перейти в другой каталог, как и в MS-DOS, можно с помощью команды ‘cd’. Стоит заметить, в UNIX нет понятия диска, поэтому специальной команды для его изменения не существует - для навигации достаточно одного ‘cd’. Например:

· $ cd / · $ ls · A E proc · base.bat etc reg · baseserviceslink.sh F sys · bin H tmp · C home usr · D lib var · dev linka win · $ cd /A · $ ls · tpna.arj · $ cd /var · $ ls · adm tmp uninstall

Для создания новых каталогов предназначена команда ‘mkdir’ (Make Directory). Вызов ‘mkdir myname’ создаст в текущем каталоге новую директорию ‘myname’. А вот попытка создать несколько вложенных друг в друга каталогов провалится, если не указать ключ ‘-p’. Например:

· $ mkdir temp · $ cd temp · $ ls · $ mkdir 1/2/3 · mkdir: 1/2/3: [No such file or directory] · $ mkdir -p 1/2/3 · $ ls · 1 · $ ls 1 · 2 · $ ls 1/2 · 3

Кстати, обратите внимание, - в UNIX ключи задаются до имен файлов, иначе вместо ключа ‘-p’ создастся директория с таким именем. Да, ‘mkdir’ позволяет создать более одного каталога за вызов. Например:

· $ mkdir 1 2 3 · $ ls · 1 2 3

Удалить ненужные каталоги поможет команда ‘rm’. По умолчанию удаляются одни файлы, а для уничтожения директорий необходимо задать дополнительный ключ ‘-d’. Если удаляемый каталог содержит вложенные директории, то начать удаление необходимо с самого «нижнего» из них или воспользоваться ключом ‘-r’, рекурсивно стирающим все без разбора. Так, для уничтожения созданных в предыдущем примере каталогов ‘/1/2/3’ можно воспользоваться следующими командами:

· rm -d /1/2/3

· rm -d /1/2

· rm -d /1

· Или обойтись всего одной:

· rm -d -r /1

А для копирования файлов в UNIX предусмотрена утилита ‘cp’ - аналог ‘copy’ из MS-DOS. Например, скопировать “/etc/passwd” в свой собственный каталог можно командой: “cp /etc/passwd /home”, а просмотреть его содержимое поможет утилита ‘cat’. Например:

· $ cp /etc/passwd /home

· $ cat /home/passwd

· root:x:0:13:Built-in account for administering the computer/domain:/tmp:/usr/bin/ksh

· telnetd:x:1:1:telnetd:/:/dev/null

Тут необходимо сделать небольшое пояснение. Изначально ‘cat’ разрабатывалась для объединения нескольких файлов в один, но в качестве целевого файла использовался стандартный вывод, поэтому пользоваться утилитой приходилось приблизительно так “cat file1 file2 file 3» file123”. Знак “»” обрабатывался оболочкой, подменяющей стандартный вывод указанным файлом. Если же целевой файл не указывался, утилита последовательно выводила содержимое перечисленных файлов на экран.

Конечно, существуют и более элегантные способы просмотра содержимого файла и его редактирования. Например, редактор ‘vi’ [93]. Это классическая утилита UNIX может вызвать насмешку у пользователей MS-DOS/Windows, привыкших к визуальному редактированию, поскольку редактор ‘vi’ управляется своим собственным командным языком, без знаний которого невозможно даже сохранить файл или выйти из vi!

Сначала это шокирует, но позже, освоившись с vi, начинаешь понимать насколько же оболванивает и ограничивает визуальный интерфейс. С другой стороны, edit.com не требует никакого обучения - сел и работай, а командный язык редактора vi можно изучать месяцами, в течение которых большую часть времени придется провести за листанием документации, с небольшими перерывами на собственно набивку текста.

Да, это так! Но при ближайшем рассмотрении недостатки оборачиваются преимуществами. Командный язык несравненно гибче системы меню и значительно ускоряет редактирование текста, стоит освоить его в совершенстве. Конечно, можно возразить «лучше за час добежать, чем за день долететь», но, в конечном счете, время, потраченное на освоение vi, может превзойти ожидаемое увеличение производительности оператора, да и машинное время сегодня не так критично, как стремление максимально облегчить умственную деятельность пользователей.

Действительно, в UNIX существуют вполне привычные пользователям Windows редакторы, и выбор того или иного - личное дело каждого. Разумеется, при условии, что выбранный редактор установлен в системе. К сожалению, администраторы многих серверов не балуют своих пользователей разнообразием, тем более, когда предоставляют хостинг бесплатно. Теоретически возможно связаться с администратором и попросить установить ваш любимый редактор, но практически это оказывается сложнее изучения vi, который поставляется со всеми UNIX-совместимыми системами, и всегда доступен (если, конечно, не удален администратором).

Поэтому минимальные навыки работы с редактором vi никогда не помешают, и как знать - может быть, через некоторое время он окажется вашим любимым редактором!

Для того чтобы пользоваться vi, вовсе не обязательно устанавливать на своем компьютере операционную систему UNIX или один из ее эмуляторов, - vi дал рождение многочисленным клонам, некоторые из которых успешно перенесены в среду Windows 9x/Windows NT и даже MS-DOS. Большую популярность завоевал vim, портированный на платформы Amiga, Atari, Mac System 7, UNIX, MS-DOS, Windows, словом практически для любого компьютера существует реализация vim. Остается добавить, что vim свободно распространяется вместе с исходными текстами и находится, например, на быстром германском ftp сервере - ftp://ftp.fu-berlin.de/misc/editors/vim, а на компакт-диске, прилагаемом к книге, он помещен вместе с сопроводительной документацией в директорию “/FILES/vim”.

Сразу же после запуска vi будет выглядеть приблизительно так, как показано на рисунке 054.bmp (в данном случае vi был запушен с параметром hello для создания нового файла).


 Внешний вид редактора vim - клона vi, запущенный в операционной системе Windows

Знаки “~” (тильда) указывают на конец файла и в действительности отсутствуют в файле. Если попытаться набрать текст “Hello, World!” на экране ничего не появится, а vi ответит разраженным покрикиванием.

Дело в том, что у vi есть два режима - командный режим и режим вставки. В командном режиме можно перемещать курсор по экрану, искать и заменять фрагменты текста, сохранять и загружать файлы с диска - словом командовать редактором, а режим вставки предназначен для ввода самого текста.

Сразу же после запуска vi оказывается в командном режиме и переключится в режим вставки можно, например, нажав клавишу «i». Дождавшись появления курсора вверху экрана, наберем восклицание “Hello, Word!” или что-нибудь в этом духе. Теперь необходимо сохранить файл на диск. Но как? Прежде необходимо один раз нажать «Esc» для переключения в командный режим, затем набрать следующую последовательность «:» «q» «w» «Enter».

Да… сложная вещь vi, но на самом деле все еще впереди! Загрузим только что созданный в редактор, указав его имя в командной строке, и попробуем отредактировать строку - изменить “Hello, World!” на “Hello, my world!”. Сначала попытаемся подвести курсор к месту правки, не пользуясь клавишами-стрелками, ибо не на всех платформах они правильно действуют. Хорошенькое начало, - чем же тогда управлять курсором?

Вообще-то не стоит волноваться понапрасну - раскладка клавиатуры обычно подбирается так, чтобы пользователи могли работать ни о чем не задумываясь, но все же иногда встречаются нерадивые администраторы, криво инсталлирующие vi на свою машину. Поэтому, на всякий случай полезно знать, что клавиша «h» в командном режиме перемещает курсор на одну позицию влево, «l» - вправо, а «j» и «k» соответственно вниз и вверх.

Нажмем шесть раз клавишу «l» или используем комбинацию «6»«l» (обычно цифра стоящая перед любой командой предписывает повторить эту команду надлежащие количество раз). Теперь наберем ‘my’, автоматически раздвигая остальные символы, а что бы заменить большую букву ‘W’ на строчечную войдем в командный режим по «Esc» и включим режим вставки символа, нажатием «r». Или же используем команду «~» (тильда) для инвертирования регистра символов.

Конечно, никто не и не утверждает, что пользоваться vi легко, но тягостные дни и месяцы обучения окупятся богатыми предоставляемыми возможностями, - vi поддерживает именованные буферы, макросы, обладает развитым механизмом шаблонного поиска, позволяет запускать команды оболочки не выходя из редактора, словом в умелых руках способен творить чудеса. Но эта книга не учебник по vi, поэтому, не задерживаясь на нем дальше, вернемся к освоению UNIX.

Продемонстрировать многозадачность UNIX поможет тот же vi - как быть, если, не выходя из редактора, потребуется выполнить какое-то действие? В Windows достаточно щелкнуть мышкой по заголовку окна другой программы или нажать «Alt»-«Tab», но разработчики UNIX пошли по другому пути.

Если нажать «Ctrl-Z», то выполнение процесса vi приостановится, и произойдет выход в оболочку. Убедиться в том, что ‘vi’ еще жив поможет команда ‘ps’, отображающая список всех процессов в системе (процесс vi.exe выделен жирным шрифтом):

· $ ps · PID TT TIME COMMAND · 148799 tty10 0 vi.exe · 150872 tty10 0 ps.exe · 320924 tty10 0 ksh.exe

Слева показаны идентификаторы процессов. Зная идентификатор процесса его можно «прибить» командной ‘kill’ или запустить передним планом утилитой ‘fg’. Например, так: “fg 148799” или так - “fg %1”, где “%1” задает порядковый номер процесса в списке. Независимо от способа запуска “fg”, редактор vi вновь появится на экране. Нажмем еще раз «Ctrl-Z» и воспользуемся командной kill для убиения процесса - “kill 148799” или “kill %1” - оба варианта одинаково хороши, но второй писать существенно короче.

А как поступить, если в vi требуется провести поиск сложного шаблона по всему тексту, выполняющийся ну неприлично длительный промежуток времени, в течение которого ничего не остается, как сидеть и тупо пялится на экран?

На помощь приходит фоновое выполнение задач. В этом случае понижается приоритет процесса, а экран предоставляется другому приложению. Перевести приложение в фоновой режим поможет команда “bg”, запускаемая точно так же как и “fg” (которая, кстати, пригодится для возращения процесса из фонового в нормальный режим). Большинство оболочек распознают символ ‘ amp;’, расположенный в конце командной строки, и автоматически запускают приложение в фоновом режиме. Например:

·

$ vi amp; · [1] 141008 · $ ps · PID TT TIME COMMAND · 87458 tty10 0 ps.exe · 141008 tty10 0 vi.exe · 320924 tty10 0 ksh.exe · [1] + Stopped (SIGTTIN) vi amp; · $

На этом краткое введение в UNIX можно считать законченным. Умения прогуляться по каталогам и запустить нужную программу для начала окажется вполне достаточно. Конечно, это не избавляет от необходимости приобретения справочных руководств и учебников по UNIX, но множество полезной информации можно найти и во встроенной справочной системе, доступной для просмотра с помощью утилиты ‘man’.

Получить помощь по любой команде можно, указав ее название в командной строке, например, так “man ls” (Смотри рисунок 055.bmp)


Демонстрация встроенной справочной системы man
Устройство конвейера и перенаправление ввода-вывода (глава для начинающих)

O В этой главе:

O Концепция ввода-вывода

O Перенаправление ввода-вывода

O Использование перенаправления ввода-вывода для атак

O Устройство конвейера

O Поддержка конвейера MS-DOS

O Использование конвейера для атак


Понимание концепции ввода-вывода в UNIX требуется как для самих атак, так и для успешной защиты от них.

Любую программу можно рассматривать как «черный ящик» с входом и выходом. Это справедливо для большинства консольных приложений MS-DOS и Windows 9x/Windows NT, но графические приложения помимо результатов своей работы выводят множество вспомогательной информации, и в определенных ситуациях оказываются бесполезными. Например, все серверные приложения должны по возможности минимизировать обмен с пользователем, посылая и принимая только полезную информацию, а обличить ее в красивый интерфейс можно и на клиентской стороне.

Разработчики UNIX значительно облегчили написание модульных программ, унифицировав систему ввода-вывода. С любым устройством стало возможно обращаться точно так, как с файлом, в частности читать и писать в него. Поэтому, результат работы одной программы может быть использован другой или выведен на экран.

Например, программу копирования файлов “copy” (MS-DOS) ничуть ни хуже использовать для создания новых файлов и вывода их содержимого на экран. Для этого достаточно вспомнить, что с клавиатурой и терминалом (объединенных в MS-DOS в устройстве под именем ‘con’) можно обращаться точь-в-точь как с обычным файлом. Доказывает это утверждение следующий эксперимент:

· copy con myfile · Hello, World! · ^Z · 1 файлов скопировано · · copy myfile con · Hello, World! · 1 файлов скопировано

Начинающим, вероятно, следует пояснить - символ «Ctrl-Z» указывает программе на завершение ввода и конец файла. В самом файле он отсутствует.

В качестве другого примера используем коротенькую демонстрационную программу, написанную на языке Си - “/SRC/io.c”, исходный текст которой приведен ниже (для наглядности никакие проверки не выполняются).

· #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 · copy out.txt con · 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”.

Но все безоблачно лишь на первый взгляд. В UNIX есть два типа процессов - наследующие права пользователя и исполняющиеся от имени системы. Примером последних может служить почтовый демон SendMail, обычно исполняющийся с наивысшими привилегиями. Ранние версии поддерживали перенаправление ввода-вывода и позволяли приаттачить к письму любой файл, даже недоступный простому пользователю.

Разумеется, SendMail не одинок, и подобные ошибки допущены во множестве приложений, щедро разбросанных по серверам. Часто для их поиска даже не требуется кропотливого изучения исходных текстов программы - достаточно во всех вводимых строках (или полях заголовка) подставить символ “«” и посмотреть на реакцию программы - нет-нет, да повезет!

Однако возможности перенаправления ввода-вывода очень ограничены. Рассмотрим это на следующем примере, - пусть требуется получить отсортированный в обратном порядке список файлов текущей директории. Команда ‘ls’ не предоставляет такого сервиса, поэтому придется воспользоваться утилитой ‘sort’ Сперва сохраним результат работы команды ‘ls’ (или dir в MS-DOS) в файле temp. Затем используем его в качестве входного потока данных утилиты ‘sort’, запушенной с ключом ‘-r’ для задания обратного порядка сортировки.

· $ ls»temp

· $ sort -r «temp

· temp

· sioux.pl

· passwd

· iohack.o

· iohack.c

· index_hack.htm

· demos.txt

· bomb.pl

· attack2.htm

Да, это работает, но требует создания лишнего файла на диске и в целом недостаточно удобно. А нельзя ли связать стандартный вывод одной программы со стандартным вводом другой? Можно! И такая конструкция называется конвейер или труба (от английского pipe).

Для создания конвейера необходимо использовать символ “|”, разделяющий запускаемые программы следующим образом: “программа 1 параметры | программа 2 параметры | программа 3 параметры”. Разумеется, стандартный ввод первой программы в цепочке и стандартный вывод последней могут быть перенаправлены с помощью символов “«” и “»” соответственно (результат попытки перенаправления остальных непредсказуем, и обычно разрывает цепочку конвейера).

Интереснее проследить, как происходит взаимодействие процессов и передача данных по конвейеру. Конвейер - сути дела тот же файл, но скрытый от пользователя, построенный по принципу FIFO (от английского First Input First Output - первый пришел - первым и уйдешь). Так, запись в конвейер, из которого никто не читает, рано или поздно вызывает его переполнение (а размер буфера обычно порядка четырех килобайт) и приводит к блокировке процесса-писателя, до тех пор, пока хотя бы один байт из конвейера не будет прочитан. Точно так, попытка чтения из пустого конвейера приводит к остановке процесса-читателя до тех пор, пока в нем не окажется хотя бы один байт.


Схематическое изображения конвейера

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

· $ ls | sort -r

· sioux.pl

· passwd

· iohack.o

· iohack.c

· index_hack.htm

· demos.txt

· bomb.pl

· attack2.htm

Не правда ли намного проще и элегантнее? Между прочим, конвейеры поддерживаются не исключительно одной UNIX, - не хуже с ними справляется и старушка MS-DOS. Доказывает это эксперимент, приведенный ниже:

· dir /b | sort /r

· sioux.pl

· passwd

· iohack.o

· iohack.c

· index_hack.htm

· demos.txt

· bomb.pl

· attack2.htm

Кажется, в этом нет ничего удивительного, но зададим простой вопрос, - как однозадачная операционная система MS-DOS может одновременно запустить два процесса? Оказывается, в ней реализован несколько другой механизм поддержки конвейера, - сначала запускается первая слева программа, записывает все результаты своей работы в некоторый промежуточный буфер, затем запускается вторая программа и получает из буфера входные данные. Это уже не труба получается, а настоящий бассейн!

С первого взгляда в таком подходе ничего дурного нет, но некоторые примеры могут работать некорректно или и вовсе не работать. К таким относится, например, UNIX-утилита “yes”, посылающая на стандартный вывод бесконечный поток символов ‘y’. За кажущейся бесполезностью она часто требуется для пакетного выполнения программ, периодически отвлекающих пользователя запросами на подтверждение выполнения какой-нибудь операции.

В UNIX конвейер полностью заполняется символами ‘y’, и выполнение утилиты “yes” приостанавливается, до тех пор, пока другой процесс не возьмет из конвейера один или несколько символов. Но в MS-DOS два процесса не могут исполняться параллельно, и пока процесс “yes” не закончит выполнение, никакое другое приложение не сможет получить управление, а поскольку выполнение ”yes” не завершиться никогда (программа-то умышленно зациклена) система скинет ласты и впадет в дурной цикл.


 Сравнение конвейеров в UNIX и MS-DOS. В MS-DOS конвейер больше похож на «бассейн», чем на «трубопровод»

Поддержка конвейеров - штука замечательная, но только не с точки зрения безопасности. Следующий код доказывает это утверждение (на диске он находится под именем “/SRC/pipe.hack.pl”).

· open(FH,«»); · if (FH) · { · while(«FH») · { · print; ·} ·}

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

· ls|

· sioux.pl

· passwd

· iohack.o

· iohack.c

· index_hack.htm

· demos.txt

· bomb.pl

Опаньки! Да ведь функция open языка Perl негласно поддерживает конвейер! Вместо открытия файла происходит его запуск! Вряд ли стоит объяснять, какие последствия вытекают из этого! Так, одна из версий SendMail позволяла в качестве обратного адреса отправителя письма подставить строчку “|/usr/bin/sh” и оболочка действительно запускалась, предоставив атакующему привилегированный доступ в систему (от имени демона).

Огромное количество защит оказалось взломано именно «благодаря» поддержке конвейера, позволяющего выполнять на удаленной машине любой код [95]. Аналогично перенаправлению ввода-вывода, конвейерные дырки могут быть обнаружены не только тщательным изучением исходных тестов приложений, но и простой подстановкой знака “|” во все доступные строки ввода и поля заголовков. Не так уж и редко это срабатывает.

Важно отметить, подобной «вкусности» подвержена не только операционная система UNIX, но и множество других, в частности Windows 9x/Windows NT. Убедиться в этом поможет приведенный выше код “pipe.hack.pl”. Достаточно запустить его на платформе Windows и ввести следующую команду:

· dir | · Том в устройстве F не имеет метки · Серийный номер тома: 2F42-0AE8 · Содержимое папки F:\TPNA\src ·. «ПАПКА» 28.06.00 23:14. ·… «ПАПКА» 28.06.00 23:14… · IO C 294 06.07.00 10:29 io.c · IO OBJ 775 06.07.00 10:18 io.obj · IO EXE 32 768 06.07.00 10:18 io.exe · IOSTD C 228 06.07.00 10:30 iostd.c · IOSTD OBJ 627 06.07.00 10:26 iostd.obj · IOSTD EXE 32 768 06.07.00 10:26 iostd.exe · MYFILE 16 06.07.00 10:53 myfile · OUT TXT 89 06.07.00 10:53 out.txt · IOHACK C 295 06.07.00 15:18 iohack.c · IOHACK OBJ 827 06.07.00 14:58 iohack.obj · IOHACK EXE 32 768 06.07.00 14:58 iohack.exe · PIPEHA~1 PL 65 06.07.00 22:29 pipe.hack.pl · 12 файлов 101 520 байт · 2 папок 1 710 641 152 байт свободно

Методы противодействия и защиты от подобных ошибок будут описаны в главе «Атака на WEB-сервер», а ниже будет объяснено почему символ конвейера появляется то слева от команды (как в примере с “|/usr/bin/sh”), то справа (“dir |”). Вообще-то «классический» конвейер состоит минимум из двух программ, и вывод первой из них попадает на ввод второй. То есть конструкцию “program 1 | program 2” можно изобразить как “stdin ® program 1 ® program 2® stdout”. А в случае, когда используется всего лишь одна программа, вывод программы, стоящей до символа конвейера, перенаправляется в открываемый функцией “open” манипулятор, а вывод программы, стоящей за символом конвейера, никуда не перенаправляется и идет прямиком на терминал.

Сказанное позволяет продемонстрировать приведенный ниже код (на диске, прилагаемом к книге, он находится в файле “/SRC/pipe.test.pl”):

· open(FH,«»); · if (FH) · { · while( $x=«FH» ) · { · print “Этот текст прочитан из файла:$x” ; ·} ·}

Строка «Этот текст прочитан из файла», предваряющая переменную $x, позволит отличить символы, получаемые чтением из файла, от текста непосредственно выводимого программой на экран.

· echo Hello, Sailor |

· Этот текст прочитан из файла:Hello, Sailor

· |echo Hello, Sailor!

· Hello, Sailor!

В первом случае, когда команда “echo” стоит до символа конвейера, результат ее работы направляется в открываемый функцией open манипулятор, откуда он может читается оператором “«»” и выводится на экран вызовом “printf”.

В другом случае, когда команда “echo” стоит после символа конвейера, результат ее работы направляется в стандартное устройство вывода, и минует оператор “print”.

И так-то славно дело пошло! Я сижу на мачте верхом, кручу бочку одной рукой, другой снимаю с конвейера готовую продукцию, передаю Фуксу, тот Лому, а Лом считает, записывает и выпускает на берег. Часа за три весь остров заселили. Александр Некрасов

Удаленное выполнение программ (глава для начинающих)

O В этой главе:

O История возникновения telnet

O Устройство telnet-сервера

O Настойка telnet-клиента

O Вход в удаленную систему

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


 

Протокол telnet был разработан в начале 80-х годов в качестве типового метода 8-битной двунаправленной связи между виртуальным терминальным устройством и компьютером. Виртуальным терминал назван для того, чтобы отличать его от обычного (неинтеллектуального, dumb). По мере снижения цен на персональные компьютеры найти неинтеллектуальные терминалы становится все труднее. Многие из них представляют собой просто экран и клавиатуру, соединенные с компьютером через последовательный интерфейс. Персональные компьютеры, оснащенные собственными процессорами, ОЗУ и дисковой памятью, гораздо универсальнее и быстро вытесняют неинтеллектуальные терминалы. Около десяти лет назад, когда я работал в фирме, производящей UNIX-компьютеры, только высшее руководство имело свои собственные ПК, у простых смертных были установлены терминалы, подключенные по каналам со скоростью передачи 9600 бит/с. А счастливые пользователи ПК связывались с центральными UNIX-компьютерами с помощью DOS-версии telnet.

Зан Олифан

Терминалом тогда называли маломощный компьютер, обслуживающий монитор и клавиатуру, а все вычисления выполняла высокопроизводительная [96] ЭВМ. Подобная схема жива и сегодня - именно так функционируют современные суперкомпьютеры, да и не только они.

Программа, выполняющаяся на центральной ЭВМ, получает с терминала исходные данные, выполняет все необходимые вычисления и отправляет результат своей работы обратно на терминал. Ну, чем не классический пример, иллюстрирующий идеальную концепцию ввода-вывода?

Потребность стандартизации взаимодействия терминала с удаленным компьютером возникла еще на заре развития ARPANET, и в результате этого в 1969 году на свет появился протокол telnet (сокращение от telecommunication network protocol - сетевой коммуникационный протокол). С его помощью удавалось осуществить заход на сервер с удаленного терминала, и необходимость иметь аппаратный доступ к узлу (попробуй-ка ее обеспечить!) отпадала. Помимо telnet был разработан и проколол rlogin, впервые появившийся в 4.2 BSD UNIX и предназначавшийся для удаленного управления терминалами между UNIX-узлами. В отличие от универсального telnet, протокол rlogin мог использоваться только в среде UNIX. Это упрощало его программирование, но и ограничивало области применения. Поэтому, в настоящее время протокол telnet по популярности заметно превосходит rlogin.

Оба протокола будут подробно рассмотрены в главе «Протокол telnet и rlogin», здесь же они будут кратко описаны в общих чертах.

Технически удаленный доступ в систему можно реализовать перенаправлением ввода-вывода. В самом деле, какая разница соединен терминал с компьютером проводами или межконтинентальной сетью Internet? С точки зрения прикладных программ терминал всегда остается терминалом, даже если физически не существует в природе. В UNIX любое устройство (в том числе виртуальное) может представляться в виде файла. А файл в свою очередь - это объект, поддерживающий, по крайней мере, две основных операции - чтения и записи данных. Поэтому, Internet-соединение можно представить как некоторый воображаемый файл.

Грубо говоря, все премудрости telnet-сервера сводятся к умению запихать терминальный ввод-вывод в TCP-соединение (хотя теоретически можно создать telnet и на базе UDP протокола). Схематично взаимодействие между telnet-сервером и telnet-клиентом показано на рисунке t26_1.jpg


 Модель взаимодействия telnet-клиента с telnet-сервером

На бумаге все, как всегда, просто, но вот на деле возникает множество непредвиденных сложностей, вынуждающих идти на всевозможные ухищрения. Это вряд ли интересно начинающим, поэтому вернемся к нашим баранам, отослав профессионалов к главе «Протоколы telnet и rlogin», в которой тот описывается во всех подробностях.

На заре развития Internet, когда еще никто не успел додуматься до WEB, а центром сетевой жизни были почта и Usenet, протокол telnet оказался основным средством межсетевого общения. Сегодня же подобный сервис - большая экзотика. И вряд ли сложно догадаться почему - слишком много развелось за последнее время вредителей и вандалов всех мастей, а удаленное выполнение программ - мощное оружие в руках злоумышленника, вот и стали администраторы закрывать ворота на свои сервера.

К счастью, в Internet существует несколько хороших бесплатных telnet-серверов, предоставляющих бесплатный доступ. В книге для большинства экспериментов будет использоваться hobbiton.org, но читатель может выбрать и другой сервер, огромный список которых находится на страничке http://www.telnet.org/htm/places_misc.htm.

Достаточный признак наличия telnet-сервера на узле - открытый двадцать третий порт. Впрочем, далеко не каждый сервер пускает к себе всех желающих. Сразу же после установки соединения запрашивается имя пользователя и пароль, но только в редких случаях удается ввести нечто вроде “guest” (в переводе на русский «гость») или “newuser” (в переводе на русский «новый пользователь»).

Для общения с telnet-сервером потребуется telnet-клиент. Какой именно выбрать - зависит от вкуса читателя, в книге же будет использоваться исключительно telnet.exe, входящий в штатную поставку Windows 9x/Windows NT. Это не лучший выбор и его возможности сильно ограничены, но он всегда доступен любому пользователю, в то время как остальные утилиты еще попробуй-ка, разыщи!


Приложение telnet.exe, поставляемое с Windows 95 и Windows 98, содержит ошибку, связанную с переполнением буфера слишком длинным аргументом командной строки. Это позволяет выполнить любой код на компьютере жертвы, стоит ей кликнуть по ссылке в окне браузера, наподобие telnet://server.com/xxxxxxxx, где “xxxx…” специальным образом подобранная последовательность [97].

До начала работы любого клиента необходимо настроить. Ниже будет показано как это сделать на примере штатного клиента Windows. Остальные же клиенты конфигурируются в той или иной степени аналогично. Запустив telnet.exe, необходимо вызывать диалог «Параметры терминала», активируя пункт меню “~Терминал/Параметры”. Появляется следующее окно (смотри рисунок 059):


Параметры терминала telnet.exe

При работе с telnet-сервером флажок «Отображение ввода» (другой распространенный вариант названия этой опции «Локальное эхо» [98]) необходимо сбросить, иначе все вводимые с клавиатуры символы будут дублироваться. Это происходит потому, что telnet-сервер возвращает клиенту все символы, набранные им с клавиатуры. Не может же пользователь работать вслепую?

Это кажется настолько очевидным, что существование альтернативных вариантов просто не укладывается в голове, но, несмотря на это они существуют! Напротив, в большинстве экспериментов, описываемых в книге, флажок «Отображение ввода» придется устанавливать, поскольку такие сервера как, например, SMTP, POP3, HTTP «молча» проглатывают отдаваемые пользователем команды и возвращают результат своей работы, но не отображают принятые символы на терминале. Однако клиент telnet может самостоятельно выводить на экран все нажатые клавиши, если флажок «Отображение ввода» установлен.

Две следующие опции управляют формой курсора. Значение их определяется вкусами и пристрастиями пользователя. Установка флажка «мерцающий курсор» приводит к миганию, позволяя его легче отыскать на экране. Если же мерцание раздражает - этот флажок можно сбросить.

Форму курсора предлагается выбрать между «простым» и «прямоугольным». «Простая» приводит к появлению на экране символа прочерка, изображенного на рисунке 063. Напротив, прямоугольный курсор занимает всю строку целиком и выглядит так, как показано на рисунке 062.


 Вид курсора при установленном флаге «прямоугольный курсор»

 Вид курсора при сброшенном флаге «прямоугольный курсор»

«Клавиатура VT100» указывает на необходимость эмуляции клавиатуры терминала VT-100, отличающегося от обычных терминалов наличием клавиш-стрелок, управляющими положением курсора. Если этот флажок сбросить, в редакторе vi придется пользоваться клавишами ‘hjkl’, что может оказаться несколько непривычно современному пользователю, поэтому “VT100” лучше всегда держать установленным.

Размер буфера это число строк, которые будет запоминать telnet-клиент, допуская возможность прокрутки окна. Рекомендуется установить достаточно большое значение, иначе вывод результатов работы программы станет уходить «вверх» за окно, и не будет никакой возможности вернуть его назад. Впрочем, в качестве альтернативы telnet.exe допускает протоколирование сеанса работы, - сохранение всех нажатых клавиш и полученной от сервера информации в файле протокола.

Протоколирование - часто необходимая в работе вещь и лучше ее всегда держать включенной. Для этого достаточно открыть меню “~Терминал/Начать протоколирование” и указать имя файла в который будет вестись запись. Закончить сеанс протоколирования можно либо выходом из telnet, либо прекращением протоколирования командой меню “~Терминал/Закончить протоколирование”.

Наконец, шрифты, как и цвет фона окна, задаются каждым по своему вкусу и желанию и на работу терминала ничуть не влияют.

Таким образом, до начала сеанса с telnet-сервером необходимо сбросить флажок «Отображение ввода» и установить «Эмуляция VT100», значения всех остальных могут варьироваться в зависимости от вкусов пользователя.

Врезка «замечание»

В поставку Windows 2000 входит значительно измененный, консольный, telnet-клиент, краткое описание которого находится в главе «Обзор telnet-клиентов». Однако допустимо использование прежнего, графического telnet-клиента, взятого из поставки Windows 95 (Windows 98) или Windows NT 4.x. Для этого достаточно скопировать один исполняемый файл telnet.exe.

Но старый клиент не способен соединится с telnet-сервером Windows 2000, поскольку не поддерживает NTLM аутентификацию, которую настоятельно рекомендуется использовать в целях безопасности. Со всеми же остальными задачами, описанными в этой книге, он успешно справляется.

Следующий эксперимент демонстрирует подключение к telnet-серверу hobbiton.org и регистрацию нового пользователя. Для этого необходимо выбрать пункт меню “~Подключить/Удаленная система”. Когда на экране появится диалоговое окно, изображенное на рисунке 060 в поле «Имя узла» указать «hobbiton.org» (или адрес другого узла, к которому необходимо подключиться на данный момент). Содержимое поля «порт» на данном этапе необходимо оставить по умолчанию, то есть “telnet” или ввести численное значение порта - “23” и выбрать “vt100” в «Типе терминала».


Рисунок 060 Диалог «подключение»

Затем нажать кнопочку «подключить», и пару секунд появится заставка “OpenBSD” [99], и требование ввести имя пользователя и пароль (смотри рисунок 061).


Рисунок 061 Начало telnet-сессии с сервером

Если ввести свое имя и взятый наугад пароль, сервер поругается,- не знаем мы, мол, таких проходимцев, пробуйте еще раз. Для регистрации нового пользователя необходимо в качестве имени ввести “newuser”. Сервер задаст несколько придирчивых вопросов о поле, возрасте, месте проживания и через некоторое время, варьирующиеся от десятков минут до нескольких дней, создаст новый аккаунт и пустит в систему.


Что можно сделать с помощью Perl (глава для начинающих)

O В этой главе:

O История создания языка Perl

O Назначение и возможности Perl

O Демонстрация возможностей Perl


«…программисты слишком часто обвиняют в грехах именно себя. Программистам нужно меньше времени тратить на оправдания. Если программирование не интересно, мы не будем убеждать других стать программистами» Ларри Уолл

Народная молва утверждает, лучше, дескать, один раз увидеть, чем сто раз услышать. Поэтому, вместо пылкой агитации за изучение языка Perl, ниже будет приведен один маленький, не самый эффектный, но достаточно оригинальный эксперимент. Как известно, большинство серверов новостей Usenet часто сильно перегружены и не отличаются завидной скоростью. А сами конференции порой содержат тысячи сообщений, просматривать которые в on-line весьма медленно и накладно.

Между тем, текстовые сообщения легко сжимаются любым архиватором в несколько раз, - будь сервер малость поумнее, - он мог бы передавать упакованный поток данных на компьютер клиента, заметно уменьшая сетевой трафик.

Но такую операцию не трудно осуществить и самостоятельно: выбрать сервер с быстрым каналом, установить на нем клиентскую программу, которая умела бы читать сообщения из выбранной конференции, упаковывать их и выкладывать на быстрый FTP, поддерживающий докачку.

Ниже приведена одна из возможных реализаций такой программы (на диске, прилагаемом к книге, она находится в файле “/SRC/nr.pl”). В качестве упражнения зайдите telnet-ом на hobbiton.org (смотри главу «Удаленное выполнение программ») и наберите следующий текст в редакторе vi:

· #!/usr/local/bin/perl · use Socket; · · #Настойки по умолчанию · #$server='mailserver.corvis.ru'; · #$server='oberon.rnd.runnet.ru'; · $server='news.fido7.ru'; · $group='fido7.ru.nethack'; · $listfile='list.txt'; · $msgfile='msg.txt'; · · print "NNTP Reader Version 2.0 (c) 2000 Kris Kaspersky\n"; · print "Open nf.cfg file…"; · · #Попытка взятия настоек из файла · if (open(FH,"nr.cfg")) · { · print "OK\n"; · $server=«FH»; · $server=~ s/\n//; · $group=«FH»; · $group =~ s/\n//; ·} · else · { · print "fail\n"; ·} · · print "Server [$server]:"; · $tmp=«»; if (length($tmp)»2) {$server=$tmp; $server=~ s/\n//;} · · · print "Command (MSG|LIST|EXIT):"; · $tmp=«»; · · if ($tmp=~/MSG\n/) · { · print "Group [$group]:"; · $tmp=«»; · if (length($tmp)»2) {$group=$tmp; $group=~ s/\n//;} · getmsg(); ·} · · if ($tmp=~/LIST\n/) · { · LIST(); ·} · · if ($tmp=~/EXIT\n/) · { · EXIT(); ·} · · #Сохраняем настойки в файле · if (open(FH,"»nr.cfg")) · { · print FH "$server\n"; · print FH "$group\n"; ·} · close (FH); · · · sub getmsg() · { · · $cmdcount=0; · print "Connecting to $server…"; · socket(NNTP, PF_INET(), SOCK_STREAM(), getprotobyname("tcp") || 6); · connect(NNTP, sockaddr_in(119,inet_aton($server))) || die; · print "ok!\n"; · · recv(NNTP,$rc,200,0); # Приглашение сервеа · print "$rc\n"; · · send(NNTP,"GROUP $group\r\n",0); # Выбор группы · $group_res=«NNTP»; · if(substr($group_res,0,3)-411) · { · print "$group_res\n"; · die; ·} · print "$group_res\n"; · · open(FH,"»$msgfile"); # Открыть файл сообщений · print FH "$group_res\n"; · $cmdcount=0; · · $reader=1; # цикл · $msgdone=0; # Сообщений прочитано · · while($reader) · { · send(NNTP,"ARTICLE\r\n",0); # Новая статья · · while(substr(($rc=«NNTP»),0,3)!~/\.\r\n/) · {# Чтение статьи · · if (!$rc) {print "Close connection\n";die;} · print FH $rc; ·} · print FH $rc; · $msgdone++; # Следующее сообщение · print "=$msgdone;\r"; # Протокол на экран · · send(NNTP,"NEXT\r\n",0); # Следующее сообщение · $nx=«NNTP»; · · $add=1; · while($add) · { · if (substr($nx,0,1)!~/\./){$add=0;} · if (substr($nx,0,1)=~/\./){$nx=«NNTP»;} · ·} · $nx++; · · if ($nx-422) {$reader=0;} # Выход из цикла ·} · · close (FH); · · if (open(CF,"$msgfile.gz")) # Удалить файл если он уже есть! · { · close(CF); · unlink("$msgfile.gz"); ·} · · open(FG,"|gzip $msgfile"); # Сжать! · print "Done\n"; · close(NNTP); ·} · · sub LIST() · { · print "Connect to $server…"; · socket(NNTP, PF_INET(), SOCK_STREAM(), getprotobyname("tcp") || 6); · connect(NNTP, sockaddr_in(119,inet_aton($server))) || die; · print "ok\n"; · · recv(NNTP,$rc,200,0); · print $rc; · · print "»LIST\n"; · send(NNTP,"LIST\r\n",0); · · open(FH,"»$listfile"); · print FH "Server: $server \nLIST:\n"; · · $cmdcount=0; · · while(substr(($rc=«NNTP»),0,1)!~/\./) · { · $cmdcount++; · #if ($debug) {print "$rc«BR»\n";} · print "=$cmdcount\r"; · · print FH $rc; ·} · close (FH); · · · if (open(CF,"$listfile.gz")) · { · close(CF); · unlink("$listfile.gz"); ·} · · print "Done\n"; · open(FG,"|gzip $listfile"); · · close(NNTP); · print "«HR»\n"; ·}

Запустите созданный файл командой “perl nr.pl”. На экране терминала появится следующее:

· NNTP Reader Version 2.0 (c) 2000 Kris Kaspersky

· Open nf.cfg file…fail

· Server [news.fido7.ru]:

Нажмите клавишу «Enter» или введите адрес news сервера, с которым хотите установить соединение. Затем появится следующий запрос:

· Command (MSG|LIST|EXIT):MSG

Выберете команду “MSG” для получения всех сообщений заданной конференции, или “LIST” для выдачи списка всех доступных конференций. Если выбрать команду “MSG” программа попросит ввести название конференции, сообщения которой требуется получить:

· Group [fido7.ru.nethack]:

После нажатия “Enter” начнется процесс перекачки сообщений на удаленный сервер. Если он действительно находится на быстром канале, это не займет много времени.

· Connecting to news.fido7.ru…ok!

· 200 ddt.demos.su InterNetNews NNRP server INN 2.3experimental 20-Nov-1998 ready (posting ok).

· 211 418 26550 26967 fido7.ru.nethack

· =55;

По окончании процесса в текущей директории будет создан файл “list.txt.gz” (если был запрошен список конференций) или “msg.txt.gz”, содержащий текст сообщений. Воспользуйтесь любым ftp-клиентом и выкачайте этот файл на свой локальный компьютер. Распакуйте его архиватором gzip (или совместимым с ним Winzip32) и, ради любопытства, сопоставьте размеры файла до и после упаковки, прикинув, сколько же времени удалось сэкономить.

Это довольно мирный пример, показывающий полезность Perl в повседневной жизни. Точно так можно перекачать файл с любого сервера, (например, ftp) не поддерживающего докачку, на сервер докачку поддерживающий.

Применительно к атакам подобная технология позволяет убить сразу двух зайцев. Во-первых, она обеспечивает анонимность (ведь программа исполняется от имени удаленного сервера, везде оставляя его адрес, а не IP злоумышленника), а во-вторых, многие атаки с медленного модемного канала реализовать принципиально невозможно!

Любую атаку можно свести к программной реализации, т.е. последовательность инструкций, работающих либо в полностью автономном, либо диалоговом режиме. В первом случае все необходимые установки задаются однократно до начала атаки, после чего атакующий идет пить кофе, дожидаясь окончания работы программы. А во втором требуется тесное взаимодействие с оператором - выдача промежуточных результатов, анализ ситуации и ввод очередной последовательности команд.

В сетевом программировании большую популярность завоевали интерпретаторы, не требующие предварительной компиляции программы перед ее выполнением. Интерпретаторы позволяют создавать мобильный код, одинаково хорошо работающий под управлением любой серверной платформы, разумеется, при условии, что для нее имеется реализации требуемого интерпретатора, и он установлен в системе.

Существует целое море самых разнообразных интерпретаторов, казалось бы, выбирай, - не хочу. Но большинство из них не сыскало большой популярности и известно лишь узкому кругу приверженцев. Вероятность обнаружить какой-нибудь из них на произвольно взятом сервере близка к нулю, и если нет возможности умаслить администратора системы и уговорить установить интерпретатор полюбившегося вам языка - ничего работать не будет.

Впрочем, существует язык, интерпретатор которого установлен на подавляющем большинстве серверов. Речь идет о Perl. Эта аббревиатура расшифровывается как Practical Extraction and Reporting Language - или по-русски Практический Язык для Извлечения (текстов) и Генерации (отчетов).

Одна из легенд утверждает, якобы Perl был создан Ларри Уоллом для поиска и извлечения сообщений из своей огромной базы конференций Usenet.


Ларри Уолл

Но, на самом деле, все происходило не совсем так. Язык Perl действительно создан Ларри Уоллом, выпустившим первую версию в 1986 году и названную им “Gloria”. К этому его побудило несовершенство существующего инструментария разработки средств управления и мониторинга многоуровневых сетей. Ларри испробовал все - и sh, и awk, и sed, и tr, но их возможностей не хватало для элегантного выполнения поставленной задачи и в созданные скрипты постоянно вносить приходилось изменения.

Врезка «информация»

Аббревиатура “awk” представляет собой первые буквы имен разработчиков языка Альфред Эхо (Aho), Питер Вейнбергер (Weinberger), Брайн Керниган (Kernighan). Синтаксис языка напоминал Си и был ориентирован на обработку текстов. От классического Си, awk отличался поддержкой регулярных выражений, ассоциативных массивов и свободным определением типов переменных и описаний.

В конце концов, Ларри решился создать собственный инструментарий. Он заимствовал все лучшее из существующих языков: форматы вывода были скопированы из BASIC, динамические контексты подарил Lisp, ассоциативные массивы пришли из awk, а синтаксис стал неотличим от Си.

Гибрид оказался удачным и быстро завоевал популярность в компьютерных кругах. Успеху способствовала полная неакадемичность языка, проявляющая в огромном количестве умолчаний, часто запутывающая новичка, но сокращающих размер листинга и за это горячо любимыми всеми профессионалами.

Врезка «замечание»
«Реальные языки эволюционируют, они не «топчутся на месте». Действительно революционные компьютерные языки, похоже, не привились. Самыми интересными из последних разработок будут как раз те, которые учитывают особенности и взаимосвязь культурных традиций разных наций. Весь мир превращается в единый компьютер с тесными внутренними связями. Безусловно, XML может помочь выполнять преобразование одних форматов данных в другие, но мы работаем и над тем, чтобы упростить процесс программирования для миллиардов потенциальных программистов во всем мире» Ларри Уолл

Вскоре Gloria была перекрещена в Pearl (в переводе на русский - жемчужина), а когда выяснилось, что такой язык уже есть, пришлось убрать одну букву, превратив жемчужину в подножную пищу кораблей пустыни (Perl обозначает колючка).

Постепенно к работе над Perl подключились десятки и сотни людей со всех концов Земного Шара и язык начал активно совершенствоваться. Со временем большая часть кода оказалась написана сторонними разработчиками, но Ларри Уолл по-прежнему остается идейным вдохновителем языка, находясь на почетном посту «генерального архитектора».

Сегодня Perl - развитый инструмент, отлично подходящий для создания Internet-приложений. Одно из несомненных достоинств - его бесплатность. Получить копию интерпретатора можно, посетив сайт www.perl.org

Наличие Perl потребуется для большинства примеров этой книги. С его помощью можно сделать практически все что угодно, и порой намного быстрее и элегантнее, чем на классическом Си/Си++. Изначально Perl так и задумывался - как инструмент быстрого программирования. «Мы пытаемся сохранить произведения искусства, продлить их существование, но даже пища, захороненная вместе с фараонами, со временем приходит в негодность. Итак, плоды нашего программирования на Perl то же в чем-то эфемерны. Этот аспект “кухни Perl” часто порицают. Если хотите - называйте его “программированием на скорую руку”, но миллиардные обороты в кафе быстрого обслуживания позволяют надеяться, что быстрая еда может быть качественной (нам хотелось бы в это верить» писал Ларри в предисловии к книге “Perl cookbook”.

Но, каким бы простым Perl не был, он все же требует вдумчивого изучения. Сегодня на рынке по этой теме можно найти множество книг, рассчитанных, как и на профессионалов, так и на начинающих пользователей. Однако для глубокого понимания материалов и примеров, приводимых в этой книге, потребуется не только значение синтаксиса самого языка, но навыки программирования сокетов. По идее эта тема должна излагаться в любой книжке, посвященной сетевому программированию, но легко убедиться: большинство авторов предпочитают ограничиться каркасными библиотеками и не лезть вглубь, на низкий уровень TCP/IP. Зато книги, посвященные Си, часто рассчитаны на профессионального читателя и порой описывают интерфейс сокетов во всех подробностях.

Впрочем, все «темные» места в настоящей книге будут комментироваться достаточно подробно, чтобы даже неподготовленный читатель смог разобраться в излагаемом материале, но лучше все же по ходу дела обращаться к специализированной литературе.

"Будьте вы хоть семи пядей во лбу, - вам никогда не удастся запомнить все напечатанное в грудах книг и таблиц. Ведь в них есть и самое важное, и просто важное, и второстепенное, и, наконец, просто ненужное - то, что либо успело устареть, едва родившись, либо потеряло значение к настоящему времени." Аркадий Стругацкий, Борис Стругацкий "Страна багровых туч"