From 48179e1f828b352b5c5f188279d8a8bb997c0837 Mon Sep 17 00:00:00 2001 From: Jonas Hinterdorfer Date: Mon, 17 Nov 2025 08:16:25 +0000 Subject: [PATCH] add setup --- Dockerfile | 7 + docker-compose.yaml | 19 ++ setup.sql | 36 +++ src/index.php | 728 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 790 insertions(+) create mode 100644 Dockerfile create mode 100644 docker-compose.yaml create mode 100644 setup.sql create mode 100644 src/index.php diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..3ed371e --- /dev/null +++ b/Dockerfile @@ -0,0 +1,7 @@ +FROM php:8.2-apache + +# Install PDO MySQL driver +RUN docker-php-ext-install pdo pdo_mysql mysqli + +# Enable Apache rewrite (optional, but often useful) +RUN a2enmod rewrite diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..75cf063 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,19 @@ +services: + web: + build: . + ports: + - "80:80" + volumes: + - ./src:/var/www/html + depends_on: + - db + + db: + image: mysql:8.0 + environment: + MYSQL_ROOT_PASSWORD: rootpass + MYSQL_DATABASE: testdb + ports: + - "3306:3306" + volumes: + - ./database1:/var/lib/mysql diff --git a/setup.sql b/setup.sql new file mode 100644 index 0000000..cf1f8e5 --- /dev/null +++ b/setup.sql @@ -0,0 +1,36 @@ +-- Datenbank erstellen (falls nicht durch Docker-Umgebung bereits erstellt) +CREATE DATABASE IF NOT EXISTS testdb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +USE testdb; + +-- Bank-Tabelle erstellen +CREATE TABLE IF NOT EXISTS bank ( + iban VARCHAR(34) PRIMARY KEY, + name VARCHAR(255) NOT NULL, + passwd VARCHAR(255) NOT NULL, + balance DECIMAL(10, 2) DEFAULT 0.00, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + INDEX idx_name (name) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- Transaktions-Tabelle erstellen +CREATE TABLE IF NOT EXISTS transf ( + sender VARCHAR(34) NOT NULL, + recipient VARCHAR(34) NOT NULL, + amount DECIMAL(10, 2) NOT NULL, + time INT UNSIGNED NOT NULL, + text VARCHAR(500) DEFAULT '', + PRIMARY KEY (sender, recipient, time), + INDEX idx_sender (sender, time), + INDEX idx_recipient (recipient, time), + INDEX idx_time (time), + FOREIGN KEY (sender) REFERENCES bank(iban) ON DELETE CASCADE, + FOREIGN KEY (recipient) REFERENCES bank(iban) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- Test-Accounts erstellen (Passwort: "test123" für alle) +INSERT INTO bank (iban, name, passwd, balance) VALUES +('DE1234', 'Max Mustermann', '$2y$10$YourHashedPasswordHere1', 5000.00), +('DE5678', 'Lisa Schmidt', '$2y$10$YourHashedPasswordHere2', 3500.00), +('DE9012', 'Thomas Müller', '$2y$10$YourHashedPasswordHere3', 12000.00) +ON DUPLICATE KEY UPDATE balance=balance; + diff --git a/src/index.php b/src/index.php new file mode 100644 index 0000000..c6d1d5e --- /dev/null +++ b/src/index.php @@ -0,0 +1,728 @@ + PDO::ERRMODE_EXCEPTION, + PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, + PDO::ATTR_EMULATE_PREPARES => false + ]); + } catch (PDOException $e) { + die("Datenbankverbindung fehlgeschlagen db: " . $e->getMessage()); + } + } + return $db; +} + +// Sicheres Passwort-Hashing +function secureHash($password) { + return password_hash($password, PASSWORD_ARGON2ID); +} + +function verifyPassword($password, $hash) { + return password_verify($password, $hash); +} + +// CSRF-Token-Management +function generateCSRFToken() { + if (!isset($_SESSION['csrf_token'])) { + $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); + } + return $_SESSION['csrf_token']; +} + +function validateCSRFToken($token) { + return isset($_SESSION['csrf_token']) && hash_equals($_SESSION['csrf_token'], $token); +} + +// Sichere Ausgabe +function e($string) { + return htmlspecialchars($string, ENT_QUOTES, 'UTF-8'); +} + +// Input-Validierung +function validateIBAN($iban) { + return preg_match('/^[A-Z0-9]{6,34}$/', $iban); +} + +function validateAmount($amount) { + return is_numeric($amount) && $amount >= 1 && $amount <= 1000; +} + +function validateName($name) { + return strlen($name) >= 3 && strlen($name) <= 100 && preg_match('/^[a-zA-ZäöüÄÖÜß\s\-]+$/u', $name); +} + +// Session-Prüfung +function requireLogin() { + if (!isset($_SESSION['iban'])) { + header('Location: index.php'); + exit; + } +} + +// === REGISTRIERUNG === +if (isset($_GET['act']) && $_GET['act'] == "register") { + if ($_SERVER['REQUEST_METHOD'] === 'POST') { + $name = trim($_POST["name"] ?? ""); + $pass = $_POST["pass"] ?? ""; + $pass_confirm = $_POST["pass_confirm"] ?? ""; + + // Validierung + $errors = []; + + if (!validateName($name)) { + $errors[] = "Name muss 3-100 Zeichen lang sein und darf nur Buchstaben, Leerzeichen und Bindestriche enthalten"; + } + + if (strlen($pass) < 8) { + $errors[] = "Passwort muss mindestens 8 Zeichen haben"; + } + + if ($pass !== $pass_confirm) { + $errors[] = "Passwörter stimmen nicht überein"; + } + + if (empty($errors)) { + $db = getDB(); + + // Generiere eindeutige IBAN + do { + $iban = 'DE' . str_pad(rand(0, 999999999999), 12, '0', STR_PAD_LEFT); + $stmt = $db->prepare("SELECT COUNT(*) FROM bank WHERE iban = ?"); + $stmt->execute([$iban]); + } while ($stmt->fetchColumn() > 0); + + // Benutzer anlegen + try { + $hash = secureHash($pass); + $stmt = $db->prepare("INSERT INTO bank (iban, name, passwd, balance) VALUES (?, ?, ?, ?)"); + $stmt->execute([$iban, $name, $hash, 1000.00]); // Startguthaben: 1000€ + + $_SESSION['msg'] = "Registrierung erfolgreich! Ihre IBAN: $iban - Startguthaben: 1000€"; + $_SESSION['reg_iban'] = $iban; // Für Anzeige auf Login-Seite + header("Location: index.php"); + exit; + } catch (PDOException $e) { + $_SESSION['emsg'] = "Registrierung fehlgeschlagen"; + header("Location: index.php?act=register"); + exit; + } + } else { + $_SESSION['emsg'] = implode("
", $errors); + header("Location: index.php?act=register"); + exit; + } + } +} + +// === Überweisung durchführen === +if (isset($_GET['recv']) && isset($_SESSION['iban'])) { + requireLogin(); + + // CSRF-Token prüfen (aus POST) + if (!isset($_POST['csrf_token']) || !validateCSRFToken($_POST['csrf_token'])) { + $_SESSION['emsg'] = "Sicherheitsfehler - ungültiges Token"; + header('Location: index.php?act=main'); + exit; + } + + $recv = trim($_GET['recv']); + $amount = $_GET['amount']; + $text = trim($_GET['text'] ?? ""); + + // Input-Validierung + if (!validateIBAN($recv)) { + $_SESSION['emsg'] = "Ungültige Empfänger-IBAN"; + header('Location: index.php?act=main'); + exit; + } + + if (!validateAmount($amount)) { + $_SESSION['emsg'] = "Ungültiger Betrag (1-1000)"; + header('Location: index.php?act=main'); + exit; + } + + if (strlen($text) > 200) { + $_SESSION['emsg'] = "Text zu lang (max. 200 Zeichen)"; + header('Location: index.php?act=main'); + exit; + } + + $db = getDB(); + + // Kontostand prüfen + $stmt = $db->prepare("SELECT balance FROM bank WHERE iban = ?"); + $stmt->execute([$_SESSION["iban"]]); + $r = $stmt->fetch(); + + if (!$r) { + header('Location: index.php'); + exit; + } + + $bal = $r['balance']; + if ($bal + 1000 < $amount) { + $_SESSION['emsg'] = "Kontostand zu niedrig"; + header('Location: index.php?act=main'); + exit; + } + + // Empfängerkonto prüfen + $stmt = $db->prepare("SELECT balance FROM bank WHERE iban = ?"); + $stmt->execute([$recv]); + if (!$stmt->fetch()) { + $_SESSION['emsg'] = "Empfängerkonto existiert nicht"; + header('Location: index.php?act=main'); + exit; + } + + // Transaktion durchführen + try { + $db->beginTransaction(); + + $stmt = $db->prepare("UPDATE bank SET balance = balance - ? WHERE iban = ?"); + $stmt->execute([$amount, $_SESSION["iban"]]); + + $stmt = $db->prepare("UPDATE bank SET balance = balance + ? WHERE iban = ?"); + $stmt->execute([$amount, $recv]); + + $stmt = $db->prepare("INSERT INTO transf (sender, recipient, amount, time, text) VALUES (?, ?, ?, ?, ?)"); + $stmt->execute([$_SESSION["iban"], $recv, $amount, time(), $text]); + + $db->commit(); + $_SESSION['msg'] = "Überweisung erfolgreich durchgeführt"; + } catch (Exception $e) { + $db->rollBack(); + $_SESSION['emsg'] = "Überweisung fehlgeschlagen"; + } + + header('Location: index.php?act=main'); + exit; +} + +$act = $_GET['act'] ?? ""; + +// === Passwort ändern === +if ($act == "chpass") { + requireLogin(); + + if (!isset($_POST['csrf_token']) || !validateCSRFToken($_POST['csrf_token'])) { + $_SESSION['emsg'] = "Sicherheitsfehler"; + header('Location: index.php?act=main'); + exit; + } + + $pass = $_POST["pass"] ?? ""; + + if (strlen($pass) < 8) { + $_SESSION['emsg'] = "Passwort muss mindestens 8 Zeichen haben"; + header('Location: index.php?act=main'); + exit; + } + + $hash = secureHash($pass); + $db = getDB(); + + $stmt = $db->prepare("UPDATE bank SET passwd = ? WHERE iban = ?"); + $stmt->execute([$hash, $_SESSION["iban"]]); + + $_SESSION['msg'] = "Passwort wurde erfolgreich geändert"; + header('Location: index.php?act=main'); + exit; +} + +// === Name suchen === +if ($act == "search") { + requireLogin(); + + if (!isset($_POST['csrf_token']) || !validateCSRFToken($_POST['csrf_token'])) { + $_SESSION['emsg'] = "Sicherheitsfehler"; + header('Location: index.php?act=main'); + exit; + } + + $name = trim($_POST["name"] ?? ""); + + if (strlen($name) > 100) { + $_SESSION['emsg'] = "Suchbegriff zu lang"; + header('Location: index.php?act=main'); + exit; + } + + $db = getDB(); + + // SICHER: Prepared Statement mit LIKE + $stmt = $db->prepare("SELECT iban, name FROM bank WHERE name LIKE ? LIMIT 50"); + $stmt->execute(["%$name%"]); + + $a = []; + while ($r = $stmt->fetch()) { + array_push($a, [$r['iban'], $r['name']]); + } + $_SESSION['iban_names'] = $a; + + header('Location: index.php?act=main'); + exit; +} + +// === Login === +if ($act == "login") { + $iban = trim($_POST["iban"] ?? ""); + $pass = $_POST["pass"] ?? ""; + + if (!validateIBAN($iban)) { + $_SESSION['emsg'] = "Ungültige IBAN"; + header("Location: index.php"); + exit; + } + + $db = getDB(); + + $stmt = $db->prepare("SELECT iban, passwd, name FROM bank WHERE iban = ?"); + $stmt->execute([$iban]); + $r = $stmt->fetch(); + + if ($r && verifyPassword($pass, $r['passwd'])) { + // Login erfolgreich + session_regenerate_id(true); // Session-Fixation verhindern + $_SESSION['iban'] = $r['iban']; + $_SESSION['name'] = $r['name']; + header("Location: index.php?act=main"); + } else { + $_SESSION['emsg'] = "Login fehlgeschlagen - IBAN oder Passwort falsch"; + header("Location: index.php"); + } + exit; +} + +// === Logout === +if ($act == "logout") { + session_destroy(); + header("Location: index.php"); + exit; +} + +// === Transfer-Details anzeigen === +if ($act == "showtrans") { + requireLogin(); + + $id = $_GET["id"] ?? 0; + + if (!is_numeric($id)) { + header('Location: index.php?act=main'); + exit; + } + + $db = getDB(); + + $stmt = $db->prepare("SELECT sender, recipient, amount, time, text FROM transf WHERE time = ?"); + $stmt->execute([$id]); + $r = $stmt->fetch(); + + if (!$r) { + $_SESSION['emsg'] = "Transaktion nicht gefunden"; + header('Location: index.php?act=main'); + exit; + } + + // Prüfen ob User berechtigt ist diese Transaktion zu sehen + if ($r['sender'] !== $_SESSION['iban'] && $r['recipient'] !== $_SESSION['iban']) { + $_SESSION['emsg'] = "Keine Berechtigung"; + header('Location: index.php?act=main'); + exit; + } + + $src = $r['sender']; + $dest = $r['recipient']; + $amount = $r['amount']; + $text = $r['text']; + + $stmt = $db->prepare("SELECT name FROM bank WHERE iban = ?"); + $stmt->execute([$src]); + $srcn = $stmt->fetch()['name'] ?? "Unbekannt"; + + $stmt->execute([$dest]); + $destn = $stmt->fetch()['name'] ?? "Unbekannt"; +} +?> + + + + + + NSCS-Bank - Sicher + + + +
+' . e($_SESSION['msg']) . '
'; + unset($_SESSION['msg']); +} +if (isset($_SESSION['emsg'])) { + echo '
' . e($_SESSION['emsg']) . '
'; + unset($_SESSION['emsg']); +} + +// === REGISTRIERUNGS-SEITE === +if ($act == "register") { +?> +

🏦 Neues Konto eröffnen

+ +
+ 📝 Registrierung: + +
+ +
+
+ + +
+
+ + +
+
+ + +
+ +
+ + + +

🏦 NSCS-Bank

+ + +
+ ✅ Ihre neue IBAN:
+ + +
+ Bitte notieren Sie sich diese IBAN für den Login! +
+ + +
+ ✅ Sicherheitsfeatures: + +
+ +
+
+ + +
+
+ + +
+ +
+ + + +

Transfer Detail

+
+

Sender: -

+

Empfänger: -

+

Betrag:

+

Zeit:

+

Text:

+
+
+ + +
+prepare("SELECT balance FROM bank WHERE iban = ?"); + $stmt->execute([$_SESSION["iban"]]); + $r = $stmt->fetch(); + $bal = $r['balance']; +?> +

Hallo ! 👋

+ +
+ +
+

IBAN:

+

+
+ +
+ +

📋 Überweisungsliste

+ prepare("SELECT sender, recipient, amount, time FROM transf WHERE (sender = ? OR recipient = ?) AND time > ? ORDER BY time DESC"); + $stmt->execute([$_SESSION["iban"], $_SESSION["iban"], time() - 10 * 3600]); + + $has_transactions = false; + while ($r = $stmt->fetch()) { + $has_transactions = true; + echo '
'; + echo e(number_format($r['amount'], 2, ',', '.')) . '€ ' . e($r['sender']) . ' ➔ ' . e($r['recipient']) . ' - '; + echo 'Detail'; + echo '
'; + } + + if (!$has_transactions) { + echo '

Keine Transaktionen in den letzten 10 Stunden

'; + } + ?> + +
+ +

💸 Neue Überweisung

+
+ +
+ + +
+
+ + +
+
+ + +
+ +
+ +
+ +

🔍 IBAN suchen

+
+ +
+ + +
+ +
+ + '; + echo '

Suchergebnisse:

'; + $a = $_SESSION['iban_names']; + if (count($a) == 0) { + echo '

Keine Ergebnisse gefunden

'; + } else { + foreach ($a as $item) { + echo '
' . e($item[0]) . ' - ' . e($item[1]) . '
'; + } + } + echo ''; + unset($_SESSION['iban_names']); + } + ?> + +
+ +

🔒 Passwort ändern

+
+ +
+ + +
+ +
+ +
+ +
+ +
+ + + +