Содержание статьи
- Разведка
- Nmap
- Исследование SNMP — порт 161 UDP
- Web — порт 3366 TCP
- Nmap IPv6
- Web — порт 80 IPv6
- Браузер
- Command Execution Panel
- Угон аккаунта Локи
- Смотрим результат выполнения команд
- PrivEsc: loki → root
- Пароль в .bash_history
- su от имени loki
- Первый способ: su от имени www-data
- Второй способ: systemd-run
- Ищем root.txt
- Эпилог
- RCE без авторизации
- WAF
- ICMP-шелл
- iptables
По уровню сложности эта виртуалка на Linux находится где-то между Medium и Hard (6,3 балла из 10), хотя изначальный ее рейтинг был определен как Insane. Если бы не некоторые ошибки создателя машины, она и правда была бы «безумной».
Вот что нас ждет на пути к финальному флагу:
- сбор и анализ информации, предоставляемой протоколом SNMP, с последующим извлечением авторизационных данных из аргументов командной строки для простого Python-сервера;
- получение IPv6-адреса машины из того же вывода SNMP (первый способ) либо через pivoting другого хоста на Hack The Box из его MAC-адреса (второй способ — алгоритм EUI-64);
- обнаружение веб-сервера, живущего по найденному IPv6-адресу и содержащего панель удаленного выполнения команд на атакуемой машине;
- обход фильтрации, который даст возможность инъекции произвольных команд, и захват авторизационных данных пользователя;
- получение реверс-шелла по IPv6 в обход правил iptables для запуска su от имени www-data (так как оказывается, что пользователя блокирует механизм распределения прав доступа ACL) и получения root-сессии с паролем, забытым в
.bash_history
; - наконец, на сладкое создание ICMP-шелла с помощью модуля Scapy на Python. Он даст возможность просматривать результаты удаленного исполнения команд при помощи утилиты ping.
Разведка
Nmap
Итак, по традиции начнем подготовительный этап сбора информации со сканирования портов с помощью Nmap.
TCP
Сперва сканируем весь диапазон TCP-портов хоста простым сканом SYN.
root@kali:~# nmap -n -v -Pn --min-rate 5000 -oA nmap/initial -p- 10.10.10.92
root@kali:~# cat nmap/initial.nmap
# Nmap 7.70 scan initiated Mon Apr 1 16:17:45 2019 as: nmap -n -v -Pn --min-rate 5000 -oA nmap/initial -p- 10.10.10.92
Nmap scan report for 10.10.10.92
Host is up (0.045s latency).
Not shown: 65533 filtered ports
PORT STATE SERVICE
22/tcp open ssh
3366/tcp open creativepartnr
Read data files from: /usr/bin/../share/nmap
# Nmap done at Mon Apr 1 16:18:11 2019 -- 1 IP address (1 host up) scanned in 26.45 seconds
И теперь делаем точечный запрос на порты 22 и 3366, используя определение версии сервисов и дефолтные скрипты NSE.
root@kali:~# nmap -n -v -Pn -sV -sC -oA nmap/version -p22,3366 10.10.10.92
root@kali:~# cat nmap/version.nmap
# Nmap 7.70 scan initiated Mon Apr 1 16:18:20 2019 as: nmap -n -v -Pn -sV -sC -oA nmap/version -p22,3366 10.10.10.92
Nmap scan report for 10.10.10.92
Host is up (0.042s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 2a:90:a6:b1:e6:33:85:07:15:b2:ee:a7:b9:46:77:52 (RSA)
| 256 d0:d7:00:7c:3b:b0:a6:32:b2:29:17:8d:69:a6:84:3f (ECDSA)
|_ 256 3f:1c:77:93:5c:c0:6c:ea:26:f4:bb:6c:59:e9:7c:b0 (ED25519)
3366/tcp open caldav Radicale calendar and contacts server (Python BaseHTTPServer)
| http-auth:
| HTTP/1.0 401 Unauthorized\x0D
|_ Basic realm=Test
| http-methods:
|_ Supported Methods: GET HEAD
|_http-server-header: SimpleHTTP/0.6 Python/2.7.15rc1
|_http-title: Site doesn't have a title (text/html).
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Mon Apr 1 16:18:44 2019 -- 1 IP address (1 host up) scanned in 24.05 seconds
Информации немного. Мы видим вот что.
- Это относительно новая сборка Ubuntu. Проверив баннер со строкой версии SSH
OpenSSH 7.6p1 Ubuntu 4
на launchpad.net — ресурсе, на котором хостятся репозитории пакетов для Ubuntu, — убеждаемся, что мы имеем дело с версией Bionic от 2018.03.07, поэтому искать эксплоиты для Secure Shell бессмысленно. - На 3366-м порте TCP работает простой Python HTTP-сервер с авторизацией. С самого начала начинать брутить вслепую что бы то ни было — откровенный моветон, поэтому расширим поверхность атаки сканированием UDP-портов.
UDP
Как и раньше, сначала «прощупаем почву», используя на этот раз флаг -sU
для диапазона UDP.
root@kali:~# nmap -n -v -Pn --min-rate 5000 -oA nmap/udp-initial -sU -p- 10.10.10.92
root@kali:~# cat nmap/udp-initial.nmap
# Nmap 7.70 scan initiated Mon Apr 1 16:26:41 2019 as: nmap -n -v -Pn --min-rate 5000 -oA nmap/udp-initial -sU -p- 10.10.10.92
Nmap scan report for 10.10.10.92
Host is up (0.048s latency).
Not shown: 65534 open|filtered ports
PORT STATE SERVICE
161/udp open snmp
Read data files from: /usr/bin/../share/nmap
# Nmap done at Mon Apr 1 16:27:08 2019 -- 1 IP address (1 host up) scanned in 26.56 seconds
И «добьем» расширенным запросом.
root@kali:~# nmap -n -v -Pn -sV -sC -oA nmap/udp-version -sU -p161 10.10.10.92
root@kali:~# cat nmap/udp-version.nmap
# Nmap 7.70 scan initiated Mon Apr 1 16:27:39 2019 as: nmap -n -v -Pn -sV -sC -oA nmap/udp-version -sU -p161 10.10.10.92
Nmap scan report for 10.10.10.92
Host is up (0.043s latency).
PORT STATE SERVICE VERSION
161/udp open snmp SNMPv1 server; net-snmp SNMPv3 server (public)
| snmp-info:
| enterprise: net-snmp
| engineIDFormat: unknown
| engineIDData: b6a9f84e18fef95a00000000
| snmpEngineBoots: 19
|_ snmpEngineTime: 16h02m33s
| snmp-interfaces:
| lo
| IP address: 127.0.0.1 Netmask: 255.0.0.0
| Type: softwareLoopback Speed: 10 Mbps
| Status: up
| Traffic stats: 0.00 Kb sent, 0.00 Kb received
| Intel Corporation 82545EM Gigabit Ethernet Controller (Copper)
| IP address: 10.10.10.92 Netmask: 255.255.255.0
| MAC address: 00:50:56:b9:7c:aa (VMware)
| Type: ethernetCsmacd Speed: 1 Gbps
| Status: up
|_ Traffic stats: 456.93 Kb sent, 39.49 Mb received
| snmp-netstat:
| TCP 0.0.0.0:22 0.0.0.0:0
| TCP 0.0.0.0:3366 0.0.0.0:0
| TCP 127.0.0.1:3306 0.0.0.0:0
| TCP 127.0.0.53:53 0.0.0.0:0
| UDP 0.0.0.0:161 *:*
| UDP 0.0.0.0:38577 *:*
|_ UDP 127.0.0.53:53 *:*
| snmp-processes:
| [... Вывод SNMP ...]
Service Info: Host: Mischief
Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Mon Apr 1 16:30:03 2019 -- 1 IP address (1 host up) scanned in 143.80 seconds
Уже интереснее — есть SNMP-сервер на 161-м порте UDP и даже подробности, полученные скриптами Nmap. Хотя полный вывод опущен (от Nmap он длинный и не очень информативный), от этого можно смело оттолкнуться при поиске пути проникновения в систему.
Исследование SNMP — порт 161 UDP
Что такое SNMP? Статья в «Википедии» гласит:
SNMP (англ. Simple Network Management Protocol — простой протокол сетевого управления) — стандартный интернет-протокол для управления устройствами в IP-сетях на основе архитектур TCP/UDP. К поддерживающим SNMP устройствам относятся маршрутизаторы, коммутаторы, серверы, рабочие станции, принтеры, модемные стойки и другие. Протокол обычно используется в системах сетевого управления для контроля подключенных к сети устройств на предмет условий, которые требуют внимания администратора.
SNMP возглавляет составленный SANS Institute список «Common Default Configuration Issues» с вопросом изначальной установки строк сообщества на значения «public» и «private» и занимал десятую позицию в SANS Top 10 самых критических угроз интернет-безопасности за 2000 год.
То есть SNMP позволяет собирать и расшаривать информацию о том, что происходит на хостах в сети. Информация такого рода инкапсулируется в базу управляющей информации MIB (Management Information Base), а идентификаторы объектов OID (Object Identifiers) однозначно определяют записи в этой базе. К примеру, идентификатор 1.3.6.1.2.1.4.34
описывает сущность ipAddressTable
(таблица IP-адресов), а 1.3.6.1.2.1.4.34.1.3
описывает сущность ipAddressIfIndex
(индекс интерфейса).
MIB основана на нотации ASN.1 и используется для упрощения представления данных в формате, понятном человеку, следовательно, она не является необходимым компонентом SNMP. Ближайшая аналогия — DNS-сервер, резолвящий легко читаемые доменные имена в такие чуждые нам цифры IP-адресов.
Рассмотрим, как можно выжать информацию из службы SNMP штатными средствами Kali Linux.
Настройка snmpwalk
Для анализа информации, которую целевой хост предоставляет по SNMP, воспользуемся snmpwalk — стандартной утилитой для разведки SNMP в Linux.
Если запустить snmpwalk при базовых настройках, ничего, кроме непонятных для человеческого взгляда идентификаторов OID, мы не получим. Здесь на помощь приходит пакет snmp-mibs-downloader
, который загружает и инсталлирует базу MIB. Установим его.
root@kali:~# apt install snmp-mibs-downloader -y
А затем разрешим использование MIB, закомментировав единственную значащую строку в /etc/snmp/snmp.conf
.
Собираем дамп
С помощью snmpwalk сдампим весь трафик SNMP с указанием версии протокола 2c
(самая распространенная) и строки сообщества public
, которая, по сути, служит паролем по умолчанию для местного способа аутентификации.
root@kali:~# snmpwalk -v 2c -c public 10.10.10.92 | tee snmpwalk.out
Вывод массивный, поэтому он был перенаправлен в файл snmpwalk.out
для дальнейшей работы.
К слову: если тебе нужно было оставаться более «бесшумным», было бы рационально запросить у snmpwalk только ту информацию, которая тебе нужна. Например, чтобы получить список запущенных процессов, достаточно уточнить запрос опцией hrSWRunName
(OID 1.3.6.1.2.1.25.4.2.1.2
).
root@kali:~# snmpwalk -v 2c -c public 10.10.10.92 hrSWRunName
HOST-RESOURCES-MIB::hrSWRunName.1 = STRING: "systemd"
HOST-RESOURCES-MIB::hrSWRunName.2 = STRING: "kthreadd"
HOST-RESOURCES-MIB::hrSWRunName.4 = STRING: "kworker/0:0H"
HOST-RESOURCES-MIB::hrSWRunName.6 = STRING: "mm_percpu_wq"
HOST-RESOURCES-MIB::hrSWRunName.7 = STRING: "ksoftirqd/0"
HOST-RESOURCES-MIB::hrSWRunName.8 = STRING: "rcu_sched"
HOST-RESOURCES-MIB::hrSWRunName.9 = STRING: "rcu_bh"
HOST-RESOURCES-MIB::hrSWRunName.10 = STRING: "migration/0"
HOST-RESOURCES-MIB::hrSWRunName.11 = STRING: "watchdog/0"
HOST-RESOURCES-MIB::hrSWRunName.12 = STRING: "cpuhp/0"
HOST-RESOURCES-MIB::hrSWRunName.13 = STRING: "kdevtmpfs"
HOST-RESOURCES-MIB::hrSWRunName.14 = STRING: "netns"
HOST-RESOURCES-MIB::hrSWRunName.15 = STRING: "rcu_tasks_kthre"
...
Список запущенных процессов
Вспомним, что мы видели питоновский HTTP-сервер на 3366-м порте TCP и он запрашивал авторизацию. Логин с паролем для такого сервака подаются питону в качестве аргументов командной строки в виде SimpleHTTPAuthServer [-h] [--dir DIR] [--https] port key
, поэтому мы можем попробовать отыскать их в захваченном дампе.
Для этого среди записей типа hrSWRunName
найдем процесс интерпретатора Python:
root@kali:~# cat snmpwalk.out | grep hrSWRunName | grep python
HOST-RESOURCES-MIB::hrSWRunName.593 = STRING: "python"
И далее по полученному индексу 593
выведем все, что относится к этому процессу в табличке hrSWRunTable
.
root@kali:~# cat snmpwalk.out | grep 593
HOST-RESOURCES-MIB::hrSWRunIndex.593 = INTEGER: 593
HOST-RESOURCES-MIB::hrSWRunName.593 = STRING: "python"
HOST-RESOURCES-MIB::hrSWRunID.593 = OID: SNMPv2-SMI::zeroDotZero
HOST-RESOURCES-MIB::hrSWRunPath.593 = STRING: "python"
HOST-RESOURCES-MIB::hrSWRunParameters.593 = STRING: "-m SimpleHTTPAuthServer 3366 loki:godofmischiefisloki --dir /home/loki/hosted/"
HOST-RESOURCES-MIB::hrSWRunType.593 = INTEGER: application(4)
HOST-RESOURCES-MIB::hrSWRunStatus.593 = INTEGER: runnable(2)
HOST-RESOURCES-MIB::hrSWRunPerfCPU.593 = INTEGER: 1129
HOST-RESOURCES-MIB::hrSWRunPerfMem.593 = INTEGER: 13852 KBytes
HOST-RESOURCES-MIB::hrSWInstalledIndex.593 = INTEGER: 593
HOST-RESOURCES-MIB::hrSWInstalledName.593 = STRING: "tzdata-2018d-1"
HOST-RESOURCES-MIB::hrSWInstalledID.593 = OID: SNMPv2-SMI::zeroDotZero
HOST-RESOURCES-MIB::hrSWInstalledType.593 = INTEGER: application(4)
HOST-RESOURCES-MIB::hrSWInstalledDate.593 = STRING: 0-1-1,0:0:0.0
Запись hrSWRunParameters
дает нам параметры запуска сервера -m SimpleHTTPAuthServer 3366 loki:godofmischiefisloki --dir /home/loki/hosted/
, где находятся нужные нам авторизационные данные loki:godofmischiefisloki
.
IPv6-адрес
Просматривая список процессов, я увидел запущенный apache2
.
root@kali:~# cat snmpwalk.out| grep hrSWRunName | grep apache
HOST-RESOURCES-MIB::hrSWRunName.770 = STRING: "apache2"
HOST-RESOURCES-MIB::hrSWRunName.2549 = STRING: "apache2"
HOST-RESOURCES-MIB::hrSWRunName.2550 = STRING: "apache2"
HOST-RESOURCES-MIB::hrSWRunName.2551 = STRING: "apache2"
HOST-RESOURCES-MIB::hrSWRunName.2552 = STRING: "apache2"
HOST-RESOURCES-MIB::hrSWRunName.2553 = STRING: "apache2"
При этом Nmap его не показал... Это может означать, что сервер крутится в мире IPv6, и было бы неплохо вытащить соответствующий IP-адрес, чтобы позже инициировать сканирование Nmap повторно (но на этот раз для IPv6-адреса).
root@kali:~# cat snmpwalk.out| grep ipAddressType | grep ipv6
IP-MIB::ipAddressType.ipv6."00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:01" = INTEGER: unicast(1)
IP-MIB::ipAddressType.ipv6."de:ad:be:ef:00:00:00:00:02:50:56:ff:fe:b9:7c:aa" = INTEGER: unicast(1)
IP-MIB::ipAddressType.ipv6."fe:80:00:00:00:00:00:00:02:50:56:ff:fe:b9:7c:aa" = INTEGER: unicast(1)
root@kali:~# ping6 -c2 dead:beef::0250:56ff:feb9:7caa
PING dead:beef::0250:56ff:feb9:7caa(dead:beef::250:56ff:feb9:7caa) 56 data bytes
64 bytes from dead:beef::250:56ff:feb9:7caa: icmp_seq=1 ttl=63 time=43.5 ms
64 bytes from dead:beef::250:56ff:feb9:7caa: icmp_seq=2 ttl=63 time=42.9 ms
--- dead:beef::0250:56ff:feb9:7caa ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 4ms
rtt min/avg/max/mdev = 42.922/43.214/43.507/0.358 ms
Видим маршрутизируемый IPv6-адрес de:ad:be:ef::02:50:56:ff:fe:b9:7c:aa
и link-local IPv6-адрес fe:80::02:50:56:ff:fe:b9:7c:aa
, которые, кстати, будут меняться при каждом ресете виртуалки.
EUI-64
Рассмотрим, как работает механизм автоматической генерации link-local IPv6-адреса на основе идентификатора EUI-64 из MAC-адреса на примере Mischief.
Для этого нам нужно находиться на одном канальном уровне (OSI layer 2) с тем хостом, адрес которого мы хотим узнать. Чтобы посмотреть, как это работает, залогинимся на другой виртуальной машине с Hack The Box, которая называется Hawk. Так как все запущенные инстансы находятся в одном логическом сегменте (виртуальной) сети 10.10.10.0/24
, то мы можем достучаться с Hawk до Mischief. Другими словами, пусть Hawk станет нашим связующим звеном — Pivot Point.
Дадим пинг от Hawk до Mischief и запросим ARP-таблицу для того, чтобы вытащить MAC Mischief.
root@hawk:~$ ping 10.10.10.92
PING 10.10.10.92 (10.10.10.92) 56(84) bytes of data.
64 bytes from 10.10.10.92: icmp_seq=1 ttl=64 time=64.0 ms
^C
--- 10.10.10.92 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 64.063/64.063/64.063/0.000 ms
root@hawk:~$ arp -a
_gateway (10.10.10.2) at 00:50:56:aa:f1:dd [ether] on ens33
? (10.10.10.92) at 00:50:56:b9:7c:aa [ether] on ens33
Добыли MAC-адрес — 00:50:56:b9:7c:aa
. Чтобы получить из него link-local IPv6-адрес, нужно провести следующие нехитрые манипуляции:
- Сгруппируем MAC в привычной для IPv6 форме, а именно по два октета —
0050:56b9:7caa
. - В начало MAC допишем
fe80::
—fe80::0050:56b9:7caa
. - В середину MAC вставим
ff:fe
—fe80::0050:56ff:feb9:7caa
. - Инвертируем шестой бит MAC —
fe80::0250:56ff:feb9:7caa
(было0000 0000
, стало0000 0010
, или0x02
). - Через символ процента укажем интерфейс (так как в мире IPv6 адреса привязываются к интерфейсам, а не к узлам и, если не указать интерфейс, трафик не будет знать, куда ему идти) —
fe80::0250:56ff:feb9:7caa%ens33
.
Проверяем, что получилось.
root@hawk:~$ ping6 -c4 fe80::0250:56ff:feb9:7caa%ens33
PING fe80::0250:56ff:feb9:7caa%ens33(fe80::250:56ff:feb9:7caa%ens33) 56 data bytes
64 bytes from fe80::250:56ff:feb9:7caa%ens33: icmp_seq=1 ttl=64 time=136 ms
64 bytes from fe80::250:56ff:feb9:7caa%ens33: icmp_seq=2 ttl=64 time=0.236 ms
64 bytes from fe80::250:56ff:feb9:7caa%ens33: icmp_seq=3 ttl=64 time=0.240 ms
64 bytes from fe80::250:56ff:feb9:7caa%ens33: icmp_seq=4 ttl=64 time=0.272 ms
--- fe80::0250:56ff:feb9:7caa%ens33 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3031ms
rtt min/avg/max/mdev = 0.236/34.259/136.290/58.907 ms
It’s alive! Теоретически можно было бы продолжать прохождение через проксирование Hawk, реализуя схему Proxy Pivoting, если бы была такая необходимость. Но к счастью, нас ждет другой путь.
WWW
Еще несколько инструментов для взаимодействия с SNMP.
- snmp-check — «из коробки» дает читабельный (но не самый подробный) результат без необходимости ставить MIB. Входит в состав Kali Linux.
- onesixtyone — утилита для брутфорса строк сообщества. Пригодилась бы нам, если бы дефолтная строка
public
не подошла. - enyx — небольшой скрипт на Python, позволяющий по SNMP узнать IPv6-адрес хоста в одно действие. Интересно, что написал скрипт создатель самой ВМ Mischief.
Продолжение доступно только участникам
Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте
Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее
Вариант 2. Открой один материал
Заинтересовала статья, но нет возможности стать членом клуба «Xakep.ru»? Тогда этот вариант для тебя! Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.
Я уже участник «Xakep.ru»