Skip to content
KitploitKITPLOIT
ToolsBlog
Einreichen
ToolsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

··Feeds·Kontakt·Datenschutz·© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
exim-rce-cve-2018-6789 — Dieses Repository bietet eine Lernumgebung, um zu verstehen, wie ein Exim-RCE-Exploit für CVE-2018-6789 funktioniert. | Kitploit
Tools/GitHubGitHub/martinclauss/exim-rce-cve-2018-6789
SchwachstellenanalyseExploitationDebuggerLernen & BildungBinary-ExploitationLabs & Praxis
GitHubmartinclauss/exim-rce-cve-2018-6789

exim-rce-cve-2018-6789

Dieses Repository bietet eine Lernumgebung, um zu verstehen, wie ein Exim-RCE-Exploit für CVE-2018-6789 funktioniert.

Repository anzeigen
1172vor 1 MonatNoch nicht geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen

Exim RCE (CVE-2018-6789) Lernumgebung

Beschreibung

Dies ist eine Sammlung von Dateien, Skripten, Notizen, ... um eine Umgebung zur Untersuchung der Exim RCE (CVE-2018-6789) einzurichten. Sie kann verwendet werden, um Exim zu debuggen, Exploits zu schreiben, Exim-Funktionsaufrufe zu verfolgen, die benutzerdefinierte Speicherverwaltung von Exim (Storeblocks) zu erlernen, herauszufinden, wie ein realer Exploit funktioniert, ...

Sie sollte nur für akademische Zwecke verwendet werden!

Voraussetzungen

  • Vagrant mit libvirt/KVM (das vagrant-libvirt-Plugin)
  • Docker (nur, wenn Sie Docker auf Ihrem Host und nicht in der Vagrant-VM ausführen möchten)

Einrichtung

Laden Sie den Quellcode von Exim herunter, indem Sie Folgendes ausführen:

root@kitploit:~
$ git submodule update --init

VM

Es gibt eine Vagrantfile im Stammverzeichnis. Sie verwendet als Virtualisierungsanbieter. Die Box wird direkt von Fedoras Spiegel über gezogen, da Vagrant Cloud Downloads derzeit defekt sind (HCP-Migration); Fedora veröffentlicht dort nur libvirt- und VirtualBox-Boxen (kein VMware), und eine direkte ist anbieterspezifisch, daher zielt dieses Setup nur auf libvirt ab.

libvirt
box_url
box_url
root@kitploit:~
# -*- mode: ruby -*-
# vi: set ft=ruby :

memory = 8192 # in MiB
cpus = 4

Vagrant.configure("2") do |config|
  # Vagrant Cloud Downloads sind defekt; Box von Fedoras Spiegel holen
  config.vm.box = "fedora-44-cloud-base"
  config.vm.box_url = "https://download.fedoraproject.org/pub/fedora/linux/releases/44/Cloud/x86_64/images/Fedora-Cloud-Base-Vagrant-libvirt-44-1.7.x86_64.vagrant.libvirt.box"

  config.vm.provider "libvirt" do |lv|
    lv.memory = memory
    lv.cpus = cpus
  end

  config.vm.provision "shell", inline: <<-SHELL
  	/vagrant/scripts/setup_vm.sh
  SHELL
end

Sie können die Konfiguration nach Belieben ändern, aber bedenken Sie, dass das Skript setup_vm.sh beispielsweise dnf zur Paketinstallation verwendet. Wenn Sie Ubuntu verwenden möchten, müssen Sie die dnf install-Zeilen durch apt-get install ersetzen und die Paketnamen entsprechend anpassen. Es gibt jedoch keine Garantie, dass die Einrichtung korrekt funktioniert.

Wenn Sie mit Ihrer Konfiguration zufrieden sind, führen Sie einfach Folgendes aus:

root@kitploit:~
$ vagrant up

um die Maschine einzurichten, und danach:

root@kitploit:~
$ vagrant ssh

um sich mit ihr zu verbinden. Wenn Sie nicht wissen, wie man Vagrant verwendet, werfen Sie einen Blick hier: https://www.vagrantup.com/intro/getting-started/

Docker-Container

Vagrant bindet das aktuelle Verzeichnis (d.h. das Repository, das Sie gerade geklont haben) als gemeinsames Verzeichnis unter /vagrant ein. Um das Docker-Image für Exim zu erstellen und auszuführen, geben Sie die folgenden Befehle innerhalb Ihrer VM (vagrant ssh) ein:

root@kitploit:~
[vagrant@localhost ~]$ cd /vagrant
[vagrant@localhost vagrant]$ ./scripts/reset_docker.sh

Der erste Durchlauf wird viel länger dauern, da Exim aus dem Quellcode erstellt wird. Wenn Sie Debugging-Skripte oder andere Dateien ändern, die in den Docker-Container kopiert werden, können Sie jederzeit ./scripts/reset_docker.sh verwenden, um das Docker-Image neu zu erstellen. Sie können natürlich auch die notwendigen Zeilen aus dem Skript extrahieren und als einzelne Befehle ausführen.

Wenn alles fertig ist, sollten Sie eine Root-Konsole sehen:

root@kitploit:~
Successfully tagged exim:latest
787f310ef922a1e519cf8bb47f1c4fed5f510da705e7ceefd48f160c980e969c
root@787f310ef922:/opt#

Die seltsamen Zeichenfolgen können auf Ihrem Rechner anders aussehen, aber Sie befinden sich jetzt in einem Debian-Docker-Container, der in einer Fedora-VM auf Ihrem Host-Rechner läuft.

Verwendung der VM und des Containers

Erstellen Sie zunächst zwei SSH-Sitzungen mit vagrant ssh in zwei Terminalfenstern. Eines kann verwendet werden, um Exploits auszuführen und mit Exim über SMTP zu interagieren. Das andere wird verwendet, um Exim im Docker-Container zu starten, auszuführen, zu debuggen, ... ASLR ist in der VM deaktiviert, sodass Sie zuverlässige Haltepunkte setzen können, die sich während Debugging-Sitzungen nicht ändern.

Beispielsitzung:

Erstes Terminal:

root@kitploit:~
$ vagrant ssh
[vagrant@localhost vagrant]$

Zweites Terminal:

root@kitploit:~
$ vagrant ssh
[vagrant@localhost vagrant]$ cd /vagrant
[vagrant@localhost vagrant]$ ./scripts/reset_docker.sh
...
# Jetzt befinden Sie sich im Debian-Docker-Container
root@99296cf63016:/opt# ./run_exim.sh
root@99296cf63016:/opt# ./attach_exim.sh

Das Skript run_exim.sh wird beendet und Exim läuft im Hintergrund. Das Skript ./attach_exim.sh sollte gdb an den laufenden Exim-Daemon-Prozess anhängen und Ihnen eine Ausgabe wie diese geben:

root@kitploit:~
...
pwndbg: loaded 170 commands. Type pwndbg [filter] for a list.
pwndbg: created $rebase, $ida gdb functions (can be used with print/break)

Attaching to process 14
Reading symbols from /usr/exim/bin/exim-4.89_1-1-fc6d6586-XX-1...done.
...
0x00007ffff6b7f5e3 in __select_nocancel () at ../sysdeps/unix/syscall-template.S:84
84	../sysdeps/unix/syscall-template.S: No such file or directory.
Breakpoint 1 at 0x5555555c03d2: file smtp_in.c, line 1762.
Breakpoint 2 at 0x5555555c051d: file smtp_in.c, line 1884.
Breakpoint 3 at 0x55555556a2c8: file base64.c, line 154.
Breakpoint 4 at 0x5555555c6aca: file smtp_in.c, line 3690.

Exim läuft und wartet auf Anfragen. Die gesetzten Haltepunkte stammen aus der Datei debugging/breakpoints. Sie können Strg+C verwenden, um den Prozess zu unterbrechen und die Kontrolle an gdb zu übergeben. Sie könnten auch eines der bereitgestellten Exploit-Skripte ausführen, um zu testen, ob alles wie erwartet funktioniert:

Erstes Terminal:

root@kitploit:~
[vagrant@localhost ~]$ cd /vagrant/sploits/
[vagrant@localhost sploits]$ ./sploit_0.py
[+] Opening connection to localhost on port 25: Done

Zweites Terminal:

root@kitploit:~
Thread 2.1 "exim" hit Breakpoint 2, smtp_reset (reset_point=reset_point@entry=0x555555843078) at smtp_in.c:1884
1884	{
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
──────────────────────────────────────────────[ REGISTERS ]───────────────────────────────────────────────
 RAX  0x555555843078 ◂— 0x0
 RBX  0x0
 RCX  0x555555824b40 (store_last_get) —▸ 0x555555843078 ◂— 0x0
 RDX  0x555555820b30 (yield_length) ◂— 0x15800001c38
 RDI  0x555555843078 ◂— 0x0
 RSI  0x0
 R8   0x3
 R9   0x52
 R10  0x73
 R11  0x246
 R12  0x5555555ec7fa ◂— 'daemon.c'
 R13  0x555555843078 ◂— 0x0
 R14  0x0
 R15  0x0
 RBP  0x5555555ee3db ◂— and    byte ptr [rax], ah /* '  %s\n' */
 RSP  0x7ffffffbe528 —▸ 0x5555555c31d1 (smtp_setup_msg+67) ◂— mov    dword ptr [rip + 0x260b6d], 0
 RIP  0x5555555c051d (smtp_reset) ◂— push   rbp
────────────────────────────────────────────────[ DISASM ]────────────────────────────────────────────────
 ► 0x5555555c051d <smtp_reset>       push   rbp
   0x5555555c051e <smtp_reset+1>     push   rbx
   0x5555555c051f <smtp_reset+2>     sub    rsp, 8
   0x5555555c0523 <smtp_reset+6>     mov    rbp, rdi
   0x5555555c0526 <smtp_reset+9>     mov    qword ptr [rip + 0x263657], 0 <0x555555823b88>
   0x5555555c0531 <smtp_reset+20>    mov    dword ptr [rip + 0x263645], 0 <0x555555823b80>
   0x5555555c053b <smtp_reset+30>    mov    dword ptr [rip + 0x26364f], 0 <0x555555823b94>
   0x5555555c0545 <smtp_reset+40>    mov    dword ptr [rip + 0x263699], 0 <0x555555823be8>
   0x5555555c054f <smtp_reset+50>    mov    dword ptr [rip + 0x263687], 0 <0x555555823be0>
   0x5555555c0559 <smtp_reset+60>    mov    dword ptr [rip + 0x263679], 0 <0x555555823bdc>
   0x5555555c0563 <smtp_reset+70>    mov    dword ptr [rip + 0x263677], 0 <0x555555823be4>
────────────────────────────────────────────[ SOURCE (CODE) ]─────────────────────────────────────────────
In file: /opt/exim/src/src/smtp_in.c
   1879 Returns:    nothing
   1880 */
   1881
   1882 static void
   1883 smtp_reset(void *reset_point)
 ► 1884 {
   1885 recipients_list = NULL;
   1886 rcpt_count = rcpt_defer_count = rcpt_fail_count =
   1887   raw_recipients_count = recipients_count = recipients_list_max = 0;
   1888 cancel_cutthrough_connection("smtp reset");
   1889 message_linecount = 0;
────────────────────────────────────────────────[ STACK ]─────────────────────────────────────────────────
00:0000│ rsp  0x7ffffffbe528 —▸ 0x5555555c31d1 (smtp_setup_msg+67) ◂— mov    dword ptr [rip + 0x260b6d], 0
01:0008│      0x7ffffffbe530 —▸ 0x7ffffffbe600 ◂— 0x0
02:0010│      0x7ffffffbe538 —▸ 0x7ffffffbe540 —▸ 0x555555605f1a ◂— add    byte ptr [rip + 0x25203a73], ah
03:0018│      0x7ffffffbe540 —▸ 0x555555605f1a ◂— add    byte ptr [rip + 0x25203a73], ah
04:0020│      0x7ffffffbe548 —▸ 0x555555843078 ◂— 0x0
05:0028│      0x7ffffffbe550 ◂— 0x0
06:0030│      0x7ffffffbe558 —▸ 0x7ffff6b7f5e3 (__select_nocancel+10) ◂— cmp    rax, -0xfff
07:0038│      0x7ffffffbe560 ◂— 0x7ffffffbe560
──────────────────────────────────────────────[ BACKTRACE ]───────────────────────────────────────────────
 ► f 0     5555555c051d smtp_reset
   f 1     5555555c31d1 smtp_setup_msg+67
   f 2     55555556de43 daemon_go+10909
   f 3     55555556de43 daemon_go+10909
   f 4     555555583ca5 main+21601
   f 5     7ffff6abe2e1 __libc_start_main+241
──────────────────────────────────────────────────────────────────────────────────────────────────────────
Breakpoint smtp_reset
pwndbg>

Sie können alle Haltepunkte mit d löschen und mit c fortfahren, damit das Skript sploit_0.py bis zum Ende läuft:

Zweites Terminal:

root@kitploit:~
Breakpoint smtp_reset
pwndbg> d
pwndbg> c
Continuing.
[Inferior 2 (process 42) exited with code 01]

Erstes Terminal:

root@kitploit:~
...
220 787f310ef922 ESMTP Exim 4.89_1-1-fc6d6586-XX Mon, 02 Mar 2020 14:47:24 +0000
250-787f310ef922 Hello test.example.org [172.17.0.1]
250-SIZE 52428800
250-8BITMIME
250-PIPELINING
250-AUTH PLAIN
250-CHUNKING
250-PRDR
250 HELP

501 Invalid base64 data
[*] Closed connection to localhost port 25

Wenn der von Ihnen debuggte (angehängte) forked-Prozess beendet wird (z. B. [Inferior 2 (process 42) exited with code 01]), können Sie gdb beenden und ./attach_exim.sh erneut ausführen.

GDB-Skripte

Unter debugging finden Sie einige Skripte, die nützlich sein könnten. Eines der Skripte ist showmem.py. Es ermöglicht Ihnen, die Storeblocks von Exim und die entsprechenden Heap-Chunks zu inspizieren. Sie können es in gdb mit dem Befehl smem ausführen:

root@kitploit:~
pwndbg> smem
...
[SHOWMEM]: 0x5555558402b0: heap chunk of size 0x000004b0 (used) / data:
[SHOWMEM]: 0x555555840760: heap chunk of size 0x00000030 (used) / data: /lib/x86_64-linux-gnu
[SHOWMEM]: 0x555555840790: heap chunk of size 0x00000050 (used) / data: ...UUU
[SHOWMEM]: 0x5555558407e0: heap chunk of size 0x000000e0 (used) / data:
[SHOWMEM]: 0x5555558408c0: heap chunk of size 0x00000370 (free) / data: .~....
[SHOWMEM]: 0x555555840c30: heap chunk of size 0x00000040 (used) / data:
[SHOWMEM]: 0x555555840c70: heap chunk of size 0x00002020 (used) / data:
[SHOWMEM]:   0x555555840c80: storeblock of size 0x00002000      / data:
[SHOWMEM]: 0x555555842c90: heap chunk of size 0x00002020 (used) / data:
[SHOWMEM]:   0x555555842ca0: storeblock of size 0x00002000      / data: root
[SHOWMEM]: 0x555555844cb0: heap chunk of size 0x00008010 (used) / data:
[SHOWMEM]: 0x55555584ccc0: heap chunk of size 0x00002010 (used) / data:
[SHOWMEM]: 0x55555584ecd0: heap chunk of size 0x00001010 (used) / data: 220 99296cf63016 ESMTP Exim 4.89_1-1-fc6d6586-XX M
[SHOWMEM]: 0x55555584fce0: heap chunk of size 0x0001d320 (free) / data:

Die eingerückten Speicherbereiche sind die Storeblocks, die anderen Bereiche sind Heap-Chunks (glibc). Derzeit ist dies eine Näherung, da ich die verwendeten Chunks nicht mit den Free-Listen von glibc abgeglichen habe, daher kann es einige falsche Angaben zu verwendeten/freien Blöcken geben. Sie können jederzeit pwndbg's bins, heap, ... Befehle als zusätzliche Informationsquelle verwenden!

Hinweis: Bei libvirt / KVM wird das /vagrant-Verzeichnis über rsync synchronisiert. Bearbeiten Sie daher Dateien auf dem Host und führen Sie vagrant rsync aus (oder lassen Sie vagrant rsync-auto laufen), um Ihre Änderungen vor dem Neuerstellen des Containers in die VM zu kopieren.

Struktur

root@kitploit:~
.
├── debugging                # GDB-bezogene Skripte
│   ├── breakpoints
│   ├── gdbinit
│   ├── showmem.py
│   └── trace.py
├── Dockerfile               # Dockerfile zum Erstellen und Debuggen von Exim
├── Exim                     # Quellcode für die anfällige Exim-Version
├── exim_code_backup         # Sicherung des anfälligen Exim-Quellcodes
│   └── exim-fc6d65867e82009a6e0671771728d41d3423a790.zip
├── exim_files               # Gepatchte Exim-Dateien zum korrekten Erstellen von Exim
│   ├── configure
│   ├── eximon.conf
│   ├── Makefile
│   └── Makefile-Linux
├── README.md
├── scripts                  # Hilfsskripte zum Debuggen von Exim
│   ├── attach_exim.sh
│   ├── reset_docker.sh
│   ├── run_exim.sh
│   └── setup_vm.sh
├── sploits                  # Inkrementelle Exploit-Skripte und ein Skript zum Finden des 0xf1-Bytes
│   ├── exim_0xf1.py
│   ├── smtp.py
│   ├── sploit_0.py
│   ├── sploit_1.py
│   ├── sploit_2.py
│   ├── sploit_3.py
│   ├── sploit_4.py
│   ├── sploit_5.py
│   ├── sploit_6.py
│   ├── sploit_7.py
│   ├── sploit_8.py
│   ├── sploit_9.py
│   └── sploit_10.py
└── Vagrantfile              # Vagrantfile zum Erstellen der VM, die den Docker-Container hostet

Exploit-Skripte

Die Exploit-Skripte befinden sich unter sploits. Sie sind inkrementell aufgebaut, um das Verständnis der verschiedenen Schritte zu erleichtern. Sie sind nahezu identisch mit den Schritten, die von @straightblast426 auf medium.com bereitgestellt werden.

sploit_10.py ist das finale Skript, das die RCE in einem einzigen Skript demonstrieren soll. Dieses Skript startet keine Reverse Shell, sondern erstellt eine Datei unter /tmp. Sie können dies ändern, indem Sie die folgende Zeile bearbeiten:

root@kitploit:~
cmd = '/bin/bash -c "touch /tmp/pwned"'

Bitte beachten Sie, dass das bereitgestellte sploit_10.py-Skript nicht der einzige Weg ist, die Schwachstelle auszunutzen. Es gibt zum Beispiel andere Möglichkeiten, den Heap anzuordnen!

Einschränkungen

Das Grooming ist empfindlich gegenüber der Umgebung: halten Sie host_lookup = deaktiviert (ein Reverse-DNS-Client-Name verschmutzt den Heap, den der Exploit groomt) und den Container auf debian:bullseye (das Grooming funktioniert nur mit Debian's glibc 2.31, nicht mit Ubuntu's oder bookworm's). Dies bedeutet auch, dass dieses Repository (wie es ist) nur so lange funktioniert, wie es eine Distribution gibt, die glibc 2.31 bereitstellt (erstmals veröffentlicht 2020)!

Der next-Zeiger wird mit einer konstanten, zuvor bekannten Adresse geändert (die auch für Sie funktionieren sollte, wenn Sie das identische Setup verwenden). Wenn Sie diesen Exploit gegen einen anderen laufenden Exim werfen würden, würde er nicht funktionieren (die Chancen sind sehr gering). Sie könnten ASLR mit etwas Brute-Force umgehen. Das funktioniert recht gut, da Exim sich forkt (klont), um Client-Anfragen zu bearbeiten. Das bedeutet, dass das gesamte Speicherlayout gleich bleibt und Sie eine realistische Chance haben, den next-Zeiger zu erraten. Wenn Sie nicht wissen, was der next-Zeiger ist, sollten Sie zuerst die Referenzen lesen.

Wenn Sie exim etwas anders bauen, kann die Position des next-Zeigers anders sein. Sie müssen die Adresse des Storeblocks finden, der acl_smtp_rcpt enthält. Befolgen Sie diese Schritte und passen Sie den Zeiger in den entsprechenden sploit_xx.py-Dateien an:

root@kitploit:~
# Mit VM verbinden: vagrant ssh
./run_exim.sh
./attach_exim.sh

# pwndbg startet, dann Strg-C
pwndbg> smem
[SHOWMEM]: 0x55555562e6b0: heap chunk of size 0x00002020 (used) / data: .2cUUU
[SHOWMEM]:   0x55555562e6c0: storeblock of size 0x00002000      / data: /usr/exim/configure
...

Der Storeblock mit der Adresse 0x55555562e6c0 enthält auch acl_smtp_rcpt:

root@kitploit:~
pwndbg> p acl_smtp_rcpt
$1 = (uschar *) 0x55555562e7f0 "acl_check_rcpt"

Ersetzen Sie sie also in den Exploit-Skripten durch die Adresse, die mit dem Befehl smem angezeigt wird:

root@kitploit:~
# ...
# Adresse des ACL-Strings-Storeblocks (nicht des Chunks)
address_of_acl_storeblock = 0x55555562E6C0
# ...

Referenzen

  • https://devco.re/blog/2018/03/06/exim-off-by-one-RCE-exploiting-CVE-2018-6789-en/ (Sicherung)
  • https://medium.com/@straightblast426/my-poc-walk-through-for-cve-2018-6789-2e402e4ff588 (Sicherung)
Tool herunterladen