Представьте себе удивление администратора, который не очень понимает, что творит, казалось бы, тривиальная программа ls
X-файлы
Настроился аки Малдер, и... познакомился с продолжением предыдущей истории. Представьте себе удивление администратора, который не очень понимает, что творит, казалось бы, тривиальная программа ls:
[root@exploited home]$ which ls /bin/ls [root @exploited home]$ ls /bin/ls /bin/ls [root @exploited home]$ cd /bin [root @exploited /bin]$ ls ... df dmesg kill nologin su ... awk dnsdomainname ln ping tar ... bsh echo mail red true ... date gunzip mv sort zcat [root @exploited /bin]$
В каталоге /bin было все, что угодно кроме ls. Никакая комбинация типа ls -al|fgrep ls не позволяла обнаружить сам ls. Типичное привидение. Команда ps не обнаруживала наличие каких-либо странностей в поведении системы. Команда top предпочитала выдавать невразумительную диагностику и отползала. Однако подозрение было очевидным (Малдер, однако) - ПРИШЕЛЬЦЫ. Т. е., простите, крекеры.
Подменить достаточное количество команд таким образом, чтобы скрыть абсолютно все, достаточно сложно. Однако как же жить без веры к ls? Я сам неоднократно попадал в ситуации, когда, благодаря неаккуратным действиям системного администратора, не находил ls. Естественно, сработали рефлексы:
echo *,
где «*» отрабатывает shell собственноручно. Поэтому фокусы ls не помешают нам увидеть полный список файлов (естественно, shell тоже можно подменить, но их-то в системе, как правило, много). Более того, echo *|wc и ls|wc выявляет различие в несколько файлов. Ой, а мы-то и не заметили: списки отличаются на ls, ps и netstat. Вот уж угораздило. И c каких это пор?
[root @exploited home]$ ls -al /bin/ls -rwxr-xr-x 1 root root 29380 Dec 23 1999 /bin/ls
Неужели с момента установки? Что бы еще спросить?
[root @exploited home]$ ls -lc /bin/ls -rwxr-xr-x 1 root root 29380 Nov 8 12:18 ls
Это уже несколько теплее, есть даже повод посмотреть на фрагменты регистрационного файла. Такое любопытство позволило обнаружить некоторую активность в ближайшей сети. Для поиска изменений можно воспользоваться find c ключами -mtime/-ctime:
[root @exploited home]$ find / -ctime -30 ... /bin/ls ... /bin/netstat ... /bin/ps .... /usr/bin/find .... /usr/bin/top ....
Да, доверие к find тоже падает. Просто везуха, что ls и find позволяют работать с полными именами. Как вы, вероятно, догадываетесь, среди каталогов обнаружилось несколько чрезвычайно подозрительных. Например, каталог с именем «.» — точка с двумя пробелами. Для более детальной проверки ls позволяет использовать ключ -b. По команде cd «.» заходим в этот странный каталог, и ls немедленно становится слепым, в упор не видит ничего в данном каталоге. Команда file * оказалась менее упорной и указала на ряд скриптов и программ, которые, конечно, были немедленно проверены. Видно, что на нашем компьютере поработал товарищ Снифер и составил неплохой список паролей. Тут же обнаружилось, что в списке подмены необходимо проверить и ряд демонов. Что же делать, ps-то врет, а netstat бредит? Как найти процесс? Есть несколько методов. Возможен прямой просмотр cmdline в подкаталогов proc:
[oblakov@test /proc]$ more [1-9] */cmdline :::::::::::::: 1/cmdline :::::::::::::: init [3] .....
Аналогично можно использовать fgrep, например:
[oblakov@test /proc]$ fgrep -l getty [1-9]*/cmdline 1647/cmdline 1649/cmdline
Для борьбы с конкретными портами подходит команда fuser -n tcp 22 и т.п. Заметим, кстати, что отсутствие процесса в списке ps не защищает его от последствий kill -9 ...
История с подключением администратора сети пока еще открыта. Мы же еще раз вернемся к теме предыдущего номера и команде debugfs.
[root@test /root]# debugfs /dev/hda3 debugfs: ls 2 (12) . 2 (12) .. 11 (20) lost+ found 2049 (12) etc 4097 (12) tmp ... 39190 (16) cdrom 37029 (12) pub debugfs:cd /bin debugfs: ls 18433 (12) . 2 (12) .. 18451 (16) egrep 18452 (16) fgrep .... 18829 (980) nologin debugfs: stat mkdir Inode: 18462 Type: regular Mode: 0755 Flags: 0x0 Version: 1 User: 0 Group: 0 Size: 8292 File ACL: 0 Directory ACL: 0 Links: 1 Blockcount: 18 Fragment: Address: 0 Number: 0 Size: 0 ctime: 0x369232cb — Tue Jan 5 18:42:03 1999 atime: 0x3a27e409 — Fri Dec 1 20:46:49 2000 mtime: 0x344eaddb — Thu Oct 23 05:52:27 1997 BLOCKS: 74406 74407 74408 74409 74410 74411 74412 74413 74414 TOTAL: 9 debugfs: dump dump: Usage: dump_inode [-p]
Как вы видите, это еще один способ все проверить и, если необходимо, что-то поправить или, для команды dump, сохранить. Для упрощения жизни debugfs имеет команду help и позволяет, достаточно просто бродить по файловой системе. Не думаю, что кто-то использует «эксплойты» для debugfs.
Для тех, кто предполагает, что лозунг кота Леопольда «Давайте жить дружно» несколько преждевременен, появилась новая книга: «Максимальная безопасность в Linux». Книга выпущена издательством DiaSoft. В ней есть ряд изъянов, но она должна быть полезна.
Из замечаний администратора пострадавшего хоста: естественно, вы не должны ограничиваться простейшими командами. Чем больше у вас утилит, тем быстрее вы обнаружите расхождение в их поведении. Дальнейший анализ при помощи mc (его никто не подменял) показал, что данное вторжение было не первым. Один только ls подменяли не менее двух раз. Машина полностью переустановлена.
Масса Солнца
Любому администратору в Unix приходится разбираться с чужими и писать собственные скрипты для массовых операций, т. е. для работы с большим количеством файлов.
Например, попробуем выполнить смену расширения у всех файлов с .h на .c и наоборот.
[oblakov@test temp]$ >a.h [oblakov@test temp]$ >b.h [oblakov@test temp]$ for i in *.h > do > mv $i `basename $i .h`.c > done [oblakov@test temp]$ ls a.c b.c [oblakov@test temp]$ ls *.c | sed ?s/^(.*).c$/mv 1.c 1.h/? | sh [oblakov@test temp]$ ls a.h b.h
Все выглядит достаточно пристойным. Попробуем использовать разного рода подстановки. Скажем, решим задачу по выводу информации о всех файлах, которые имеют два подряд идущих одинаковых символа в имени файла:
[oblakov@test oblakov]$ ls -l `ls | sed -n -e ?/(.)1/p?` -rwxr-xr-x 1 oblakov narod 4166 Jul 15 1999 hello1 -rw-r—r— 1 oblakov narod 29 Jul 15 1999 hello1.c -rw-r—r— 1 oblakov narod 120 Jun 30 17:02 uuu.tar
Отлично сработало. Правда, еще весь каталог uuu выводился - всегда-то что-то забудешь.
Должен ли скрипт подобного рода работать всегда? Ясно, что нет. Стандартная проблема с скриптами подобного рода заключается в выполняемом для команды `` преобразовании - исключение лишних пробелов и переходов на следующую строку. Попробуем показать зубы:
[oblakov@test oblakov]$ >-RR [oblakov@test oblakov]$ >»a b» — два, заметим, пробела [oblakov@test oblakov]$ ls -ld `ls | sed -n -e ?/(.)1/p?` ls: a: No such file or directory ls: b: No such file or directory -rwxr-xr-x 1 oblakov narod 4166 Jul 15 1999 hello1 -rw-r—r— 1 oblakov narod 29 Jul 15 1999 hello1.c drwxr-xr-x 2 oblakov narod 1024 Jun 30 17:01 uuu -rw-r—r— 1 oblakov narod 120 Jun 30 17:02 uuu.tar [oblakov@test oblakov]$ ls | sed -n -e ?/(.)1/p? -RR a b hello1 hello1.c uuu uuu.tar [oblakov@test oblakov]$
Как вы видите, ls -ld слопал файл -RR, поскольку принял его за ключ. Файл же «a b» вообще перекосило. Замечу, что создание «ключевых» файлов достаточно типично. Например:
[oblakov@test temp]$ tar -cf -v * a.h b.h [oblakov@test temp]$ ls -v a.h b.h
Вопрос об удалении подобных файлов (-f -r) мы ставили перед читателями еще в первом номере «Открытых систем» за 1999 год. Решений несколько. Один из вариантов предполагает использование множественности «имен» файла:
rm ./-f
Так, однако, с подстановкой у нас был прокол. Проехали.
Еще раз вернемся к вопросу о массовом удалении файлов. Например, удалить все .tmp файлы с модификацией более, чем неделю назад:
find . -type f -name ?*.tmp? -mtime +7 -print -exec rm {} ;
Условие может быть более сложным. Попробуем другой вариант (только не говорите мне, что -print я пишу зря):
[oblakov@test temp]$ find . -type f - name «*.tmp» -print | while read a; do rm «$a»; done
Как кажется, данный скрипт выполняет аналогичные действия, только без проверки даты. Однако это не совсем так. Если вы попытаетесь удалять данные пользователей при помощи подобного скрипта, то при соответствующем подборе структуры каталогов пользователь сможет уничтожить любой заданный файл (например, /etc/passwd). Это опять же вытекает из того, что в имени файла могут встречаться любые символы за исключением / и нулевого. Значит, возможно появление файла с именем, включающим символ перехода на другую строку — со всеми вытекающими последствиями.
Более миролюбивый пример (попытка удаление файлов с именем длиннее четырех символов):
[oblakov@test temp]$ >»a.h b.h» [oblakov@test temp]$ ls -b -v a.h a.h b.h b.h [oblakov@test temp]$ find . -type f - name «????*» -print | while read a; do rm $a; done [oblakov@test temp]$ ls -b -v a.h b.h [oblakov@test temp]$ >a.h [oblakov@test temp]$ >b.h [oblakov@test temp]$ find . -type f - name «????*» -exec rm {} ; [oblakov@test temp]$ ls -b -v a.h b.h [oblakov@test temp]$ find . -name «-*» -exec rm {} ; [oblakov@test temp]$ ls a.h b.h [oblakov@test temp]$ >«a <- здесь мы нажали Enter> b» [oblakov@test temp]$ ls a?b a.h b.h [oblakov@test temp]$ find . -name «*b» -exec rm {} ; [oblakov@test temp]$ ls a.h b.h
Как вы видите, find справляется с ситуацией несколько лучше. А если возможностей find упорно не хватает, а файлы-таки обрабатывать хочется? Тогда надо либо передавать файл какому-то скрипту в качестве параметра (и очень осторожно с ним работать), либо использовать что-либо наподобие - print0:
[oblakov@test temp]$ > «a > b» [oblakov@test temp]$find . -name «*b» -print0 ./a b[oblakov@test temp]$ find . -name «*b» -print0 | xargs -0 rm [oblakov@test temp]$ ls a.h b.h
В данном случае все работает корректно потому, что разделителем для аргументов от find поступает нулевой символ.
В принципе, find не обязан работать корректно всегда. Этот случай возможен при большой глубине вложенности каталогов. Впрочем, это относится и ко многим другим утилитам. Аналогичные проблемы встречаются и в других операционных системах. В любом случае написание скриптов требует от администратора определенной осторожности, особенно, если его скрипты общедоступны и могут быть кем-либо со всей серьезностью «проанализированы» на пробиваемость. Например, удаление данных пользователя всегда лучше выполнять с правами пользователя — мало ли что он умеет у себя устроить.
Присылайте свои X-файлы по адресу oblakov@bigfoot.com.