Содержание статьи
- Разведка
- 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
В этой статье я покажу, как получить права суперпользователя на виртуальной машине Mischief с CTF-площадки Hack The Box. Этот забег даст нам навыки работы с протоколом SNMP, поможет понять принцип IPv6-маршрутизации и разобраться с механизмом распределения прав доступа ACL, а под занавес мы построим и протестируем полноценный ICMP-шелл на Python.
По уровню сложности эта виртуалка на 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.92Nmap scan report for 10.10.10.92Host is up (0.045s latency).Not shown: 65533 filtered portsPORT STATE SERVICE22/tcp open ssh3366/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.92Nmap scan report for 10.10.10.92Host is up (0.042s latency).
PORT STATE SERVICE VERSION22/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 Unauthorizedx0D|_ 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/nmapService 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.92Nmap scan report for 10.10.10.92Host is up (0.048s latency).Not shown: 65534 open|filtered portsPORT STATE SERVICE161/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.92Nmap scan report for 10.10.10.92Host is up (0.043s latency).
PORT STATE SERVICE VERSION161/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/nmapService 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 hrSWRunNameHOST-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 pythonHOST-RESOURCES-MIB::hrSWRunName.593 = STRING: "python"
И далее по полученному индексу 593 выведем все, что относится к этому процессу, в табличке hrSWRunTable.
root@kali:~# cat snmpwalk.out | grep 593HOST-RESOURCES-MIB::hrSWRunIndex.593 = INTEGER: 593HOST-RESOURCES-MIB::hrSWRunName.593 = STRING: "python"HOST-RESOURCES-MIB::hrSWRunID.593 = OID: SNMPv2-SMI::zeroDotZeroHOST-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: 1129HOST-RESOURCES-MIB::hrSWRunPerfMem.593 = INTEGER: 13852 KBytesHOST-RESOURCES-MIB::hrSWInstalledIndex.593 = INTEGER: 593HOST-RESOURCES-MIB::hrSWInstalledName.593 = STRING: "tzdata-2018d-1"HOST-RESOURCES-MIB::hrSWInstalledID.593 = OID: SNMPv2-SMI::zeroDotZeroHOST-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 apacheHOST-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 ipv6IP-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:7caaPING dead:beef::0250:56ff:feb9:7caa(dead:beef::250:56ff:feb9:7caa) 56 data bytes64 bytes from dead:beef::250:56ff:feb9:7caa: icmp_seq=1 ttl=63 time=43.5 ms64 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 4msrtt 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.92PING 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 0msrtt 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%ens33PING fe80::0250:56ff:feb9:7caa%ens33(fe80::250:56ff:feb9:7caa%ens33) 56 data bytes64 bytes from fe80::250:56ff:feb9:7caa%ens33: icmp_seq=1 ttl=64 time=136 ms64 bytes from fe80::250:56ff:feb9:7caa%ens33: icmp_seq=2 ttl=64 time=0.236 ms64 bytes from fe80::250:56ff:feb9:7caa%ens33: icmp_seq=3 ttl=64 time=0.240 ms64 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 3031msrtt 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.
Продолжение доступно только участникам
Материалы из последних выпусков становятся доступны по отдельности только через два месяца после публикации. Чтобы продолжить чтение, необходимо стать участником сообщества «Xakep.ru».
Присоединяйся к сообществу «Xakep.ru»!
Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», увеличит личную накопительную скидку и позволит накапливать профессиональный рейтинг Xakep Score! Подробнее
1 год7690 р. |
1 месяц720 р. |
Я уже участник «Xakep.ru»