Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Einreichen
ToolsExploitsBlog
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.

FeedsKontaktDatenschutz© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
CVE-2017-5123 — PoC CVE-2017-5123 - LPE - Umgehen von SMEP/SMAP. Kein KASLR | Kitploit
Tools/GitHubGitHub/c3r34lk1ll3r/cve-2017-5123
Privilege EscalationExploitationLernen & BildungBinary-ExploitationLabs & Praxis
GitHubc3r34lk1ll3r/cve-2017-5123

CVE-2017-5123

PoC CVE-2017-5123 - LPE - Umgehen von SMEP/SMAP. Kein KASLR

Repository anzeigen
33411vor 6 JahrenVon Kitploit geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen

CVE-2017-5123

PoC CVE-2017-5123 - LPE - Umgehung von SMEP/SMAP. Kein KASLR

Die waitid-Implementierung in Upstream-Kernels hat das Ziel, auf das die Ergebnisinformationen kopiert werden, nicht eingeschränkt. Dies kann es lokalen Benutzern ermöglichen, in geschützten Kernel-Speicher zu schreiben, was zu einer Privilegieneskalation führen kann.

Einleitung

In dieser kleinen Abhandlung werde ich eine Kernel-Sicherheitslücke analysieren, die es uns ermöglicht, root-Rechte zu erlangen.

Diese Datei ist in vier Teile unterteilt:

  1. VM-Einrichtung;
  2. Sicherheitslückenanalyse;
  3. Ausnutzung;
  4. PoC.

Ich möchte darauf hinweisen, dass es viele bessere Möglichkeiten gibt, diese CVE auszunutzen (tatsächlich ist dies nur ein PoC zum Erlernen des Kernels und kann in freier Wildbahn nicht verwendet werden), aber ich denke, dass diese Methodik als Einführung in die Kernel-Ausnutzung nützlich sein kann.

VM-Einrichtung

Kernel-Build

Diese Schwachstelle wurde in 4c48abe91be0 eingeführt, daher müssen wir diese Kernel-Version bauen.

Das kann etwas knifflig sein, da es sich um eine alte Version handelt und der Code gepatcht werden sollte. Ich habe ein Repository mit bereits gepatchtem Kernel-Code und einer .config-Datei erstellt, sodass Sie klonen und bauen können.

git clone https://github.com/c3r34lk1ll3r/kernel_mirror.git
cd kernel_mirror
git checkout origin/modified_v4.14
wget https://gist.githubusercontent.com/c3r34lk1ll3r/c9c34ae86140cc7a24d0d90141686ee8/raw/52431b577a71e3fe8f89d6ce355ce9c1c54c53b6/.config
make -j 8 --output-sync=recurse

Beachten Sie, dass dieser Kernel mit virtio-Treibern gebaut wird, sodass Sie virtio disk zum Teilen von Dateien zwischen Host und VM verwenden können.

Rootfs-Einrichtung

Nun erstellen wir das initiale rootfs:

qemu-img create -f raw hda.raw 10G
# Formatieren der Festplatte zu ext4
mkfs.ext4 ./hda.raw 
# Erstellen eines Mountpunkts für das Image
mkdir /tmp/mount1
# Einbinden der Festplatte
sudo mount -o loop ./hda.raw /tmp/mount1

Dann sollten wir eine grundlegende Linux-Distribution installieren, z.B. mit pacstrap oder debootstrap.

sudo pacstrap /tmp/mount1 base base-devel vim

Schließlich können wir das System anpassen:

# Hinzufügen eines 'test'-Benutzers
echo 'test:x:1000:1000::/home/test:/bin/bash' | sudo tee -a /tmp/mount1/etc/passwd
# ohne Passwort
echo 'test::14871::::::' | sudo tee -a /tmp/mount1/etc/shadow 
# Wir können eine virtio-Festplatte mounten, um Dateien zwischen Host und Gast auszutauschen
echo '/transient /home/test/shared 9p trans=virtio,version=9p2000.L,rw,user,exec 0 0' | sudo tee -a /tmp/mount1/etc/fstab
sudo mkdir -p /tmp/mount1/home/test/shared 
# Es ist nützlich, sudo-Berechtigung zu haben
echo '%wheel ALL=(ALL) NOPASSWD: ALL' | sudo tee -a /tmp/mount1/etc/sudoers
echo 'wheel:x:998:test' | sudo tee -a /tmp/mount1/etc/group

sudo chown -R 1000:1000 /tmp/mount1/home/test
sudo umount /tmp/mount1

Wenn alles in Ordnung ist, können wir nun unser Testsystem mit qemu ausprobieren:

qemu-system-x86_64 \
    -kernel ./kernel_mirror/arch/x86_64/boot/bzImage \
    -hda ./hda.raw \
    -m 4G \
    -cpu "Skylake-Client-IBRS,ss=on,vmx=on,hypervisor=on,tsc-adjust=on,clflushopt=on,umip=on,md-clear=on,stibp=on,arch-capabilities=on,ssbd=on,xsaves=on,pdpe1gb=on,ibpb=on,amd-ssbd=on,skip-l1dfl-vmentry=on,hle=off,rtm=off" \
    -smp 4 \
    -vga virtio \
    -enable-kvm \
    -nographic \
    -machine type=q35,accel=kvm \
    -virtfs "fsdriver=local,id=fs.1,path=./trans_fs,security_model=mapped,writeout=immediate,mount_tag=/transient" \
    -append "root=/dev/sda rw noquiet nokaslr console=ttyS0 loglevel=5" \
    -chardev "vc,id=vc.0,cols=1920,rows=1080" \
    -net "user,hostfwd=tcp::10022-:22" \
    -net "nic" \
    -s

Sicherheitslücke

Die Beschreibung der CVE besagt, dass es während des Systemaufrufs waitid eine uneingeschränkte Schreiboperation gibt.

Öffnen wir kernel/exit.c und schauen uns den Code an:

SYSCALL_DEFINE5(waitid, int, which, pid_t, upid, struct siginfo __user *,
		infop, int, options, struct rusage __user *, ru)
{
    struct rusage r;
    struct waitid_info info = {.status = 0};
    long err = kernel_waitid(which, upid, &info, options, ru ? &r : NULL);
    int signo = 0;

    if (err > 0) {
        signo = SIGCHLD;
        err = 0;
        if (ru && copy_to_user(ru, &r, sizeof(struct rusage)))
            return -EFAULT;
    }
    if (!infop)
        return err;
    user_access_begin();
    unsafe_put_user(signo, &infop->si_signo, Efault);
    unsafe_put_user(0, &infop->si_errno, Efault);
    unsafe_put_user(info.cause, &infop->si_code, Efault);
    unsafe_put_user(info.pid, &infop->si_pid, Efault);
    unsafe_put_user(info.uid, &infop->si_uid, Efault);
    unsafe_put_user(info.status, &infop->si_status, Efault);
    user_access_end();
    return err;
Efault:
    user_access_end();
    return -EFAULT;
}

Diese Funktion ist recht einfach: Nach einigen Prüfungen gibt es verschiedene Aufrufe von unsafe_put_user(...) und die Funktion kehrt zurück.

Der Hauptteil dieser Funktion besteht aus der Funktion unsafe_put_user(...), also gehen wir dorthin (arch/x86/include/asm/uaccess.h):

/*
 * The "unsafe" user accesses aren't really "unsafe", but the naming
 * is a big fat warning: you have to not only do the access_ok()
 * checking before using them, but you have to surround them with the
 * user_access_begin/end() pair.
 */
#define user_access_begin()	__uaccess_begin()
#define user_access_end()	__uaccess_end()

#define unsafe_put_user(x, ptr, err_label)					\
do {										\
    int __pu_err;								\
    __typeof__(*(ptr)) __pu_val = (x);					\
    __put_user_size(__pu_val, (ptr), sizeof(*(ptr)), __pu_err, -EFAULT);	\
    if (unlikely(__pu_err)) goto err_label;					\
} while (0)

#define unsafe_get_user(x, ptr, err_label)					\
do {										\
    int __gu_err;								\  
    __inttype(*(ptr)) __gu_val;						\
    __get_user_size(__gu_val, (ptr), sizeof(*(ptr)), __gu_err, -EFAULT);	\
    (x) = (__force __typeof__(*(ptr)))__gu_val;				\
    if (unlikely(__gu_err)) goto err_label;					\
} while (0)

Es gibt eine fette Warnung im Kommentar: Wenn Sie unsafe_put/get_user verwenden möchten, sollten Sie zuerst access_ok() aufrufen und sie mit user_access_begin/end() umschließen.

Wenn wir uns den vorherigen Code (waitid) ansehen, sehen wir, dass access_ok() nie aufgerufen wird, der Systemaufruf diese Warnung also verletzt.

Aber was sind diese Makros?

SMAP/SMEP

SMAP und SMEP sind zwei Sicherheitsfunktionen, die im Kernel eingeführt wurden, um das Schreiben von Exploits zu erschweren. Zu beachten ist, dass diese Funktionen von der CPU erzwungen werden.

SMEP verhindert die Ausführung von Userspace-Code, während sich die CPU im Supervisor-Modus befindet; SMAP blockiert den Lese-/Schreibzugriff auf den Benutzerspeicher.

Der Kernel muss Daten in den/vom Benutzerspeicher schreiben/lesen, und dies kann auf zwei Arten erfolgen:

  1. Es gibt Funktionen (z.B. copy_from_user), die das Kopieren des Speichers in den Kernelspace ermöglichen;
  2. vorübergehendes Deaktivieren von SMAP.
Tool herunterladen