Răsfoiți Sursa

Add error handling for save operations and improve logout security

- Check return values of save functions and show error messages
- Change logout from GET to POST with CSRF protection
- Add session security settings and regeneration
- Make save functions return boolean success status
Medowar 1 lună în urmă
părinte
comite
1f1e3d1fda
10 a modificat fișierele cu 218 adăugiri și 123 ștergeri
  1. 52 35
      admin/admins.php
  2. 34 21
      admin/categories.php
  3. 8 4
      admin/faq.php
  4. 4 1
      admin/index.php
  5. 25 9
      admin/login.php
  6. 34 21
      admin/organizations.php
  7. 35 21
      admin/products.php
  8. 8 4
      admin/settings.php
  9. 10 0
      config.sample.php
  10. 8 7
      includes/functions.php

+ 52 - 35
admin/admins.php

@@ -67,13 +67,17 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
                     "description" => $description,
                     "email" => $email,
                 ];
-                saveAdminAccounts($adminAccounts);
-                logAccess("Admin added admin account", [
-                    "username" => $username,
-                    "description" => $description,
-                ]);
-                $message = "Admin wurde erfolgreich angelegt.";
-                $messageType = "success";
+                if (saveAdminAccounts($adminAccounts)) {
+                    logAccess("Admin added admin account", [
+                        "username" => $username,
+                        "description" => $description,
+                    ]);
+                    $message = "Admin wurde erfolgreich angelegt.";
+                    $messageType = "success";
+                } else {
+                    $message = "Admin konnte nicht gespeichert werden.";
+                    $messageType = "error";
+                }
             }
         }
 
@@ -98,12 +102,16 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
             } else {
                 $adminAccounts[$targetUsername]["description"] = $description;
                 $adminAccounts[$targetUsername]["email"] = $email;
-                saveAdminAccounts($adminAccounts);
-                logAccess("Admin updated admin description", [
-                    "username" => $targetUsername,
-                ]);
-                $message = "Beschreibung und E-Mail wurden aktualisiert.";
-                $messageType = "success";
+                if (saveAdminAccounts($adminAccounts)) {
+                    logAccess("Admin updated admin description", [
+                        "username" => $targetUsername,
+                    ]);
+                    $message = "Beschreibung und E-Mail wurden aktualisiert.";
+                    $messageType = "success";
+                } else {
+                    $message = "Änderungen konnten nicht gespeichert werden.";
+                    $messageType = "error";
+                }
             }
         }
 
@@ -127,12 +135,16 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
                 $adminAccounts[$targetUsername][
                     "password_hash"
                 ] = password_hash($newPassword, PASSWORD_BCRYPT);
-                saveAdminAccounts($adminAccounts);
-                logAccess("Admin changed admin password", [
-                    "username" => $targetUsername,
-                ]);
-                $message = "Passwort wurde aktualisiert.";
-                $messageType = "success";
+                if (saveAdminAccounts($adminAccounts)) {
+                    logAccess("Admin changed admin password", [
+                        "username" => $targetUsername,
+                    ]);
+                    $message = "Passwort wurde aktualisiert.";
+                    $messageType = "success";
+                } else {
+                    $message = "Passwort konnte nicht gespeichert werden.";
+                    $messageType = "error";
+                }
             }
         }
 
@@ -146,24 +158,29 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
                 $messageType = "error";
             } else {
                 unset($adminAccounts[$targetUsername]);
-                saveAdminAccounts($adminAccounts);
-                logAccess("Admin deleted admin account", [
-                    "username" => $targetUsername,
-                ]);
+                if (!saveAdminAccounts($adminAccounts)) {
+                    $message = "Admin konnte nicht gelöscht werden.";
+                    $messageType = "error";
+                    $adminAccounts = getAdminAccounts();
+                } else {
+                    logAccess("Admin deleted admin account", [
+                        "username" => $targetUsername,
+                    ]);
 
-                if (
-                    isset($_SESSION["admin_username"]) &&
-                    $_SESSION["admin_username"] === $targetUsername
-                ) {
-                    $_SESSION["admin_logged_in"] = false;
-                    unset($_SESSION["admin_username"]);
-                    session_destroy();
-                    header("Location: login.php");
-                    exit();
-                }
+                    if (
+                        isset($_SESSION["admin_username"]) &&
+                        $_SESSION["admin_username"] === $targetUsername
+                    ) {
+                        $_SESSION["admin_logged_in"] = false;
+                        unset($_SESSION["admin_username"]);
+                        session_destroy();
+                        header("Location: login.php");
+                        exit();
+                    }
 
-                $message = "Admin wurde gelöscht.";
-                $messageType = "success";
+                    $message = "Admin wurde gelöscht.";
+                    $messageType = "success";
+                }
             }
         }
 

+ 34 - 21
admin/categories.php

@@ -33,13 +33,17 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
                     "id" => $categoryId,
                     "label" => $label,
                 ];
-                saveCategories($categories);
-                logAccess("Admin added category", [
-                    "category_id" => $categoryId,
-                    "label" => $label,
-                ]);
-                $message = "Kategorie wurde erfolgreich angelegt.";
-                $messageType = "success";
+                if (saveCategories($categories)) {
+                    logAccess("Admin added category", [
+                        "category_id" => $categoryId,
+                        "label" => $label,
+                    ]);
+                    $message = "Kategorie wurde erfolgreich angelegt.";
+                    $messageType = "success";
+                } else {
+                    $message = "Kategorie konnte nicht gespeichert werden.";
+                    $messageType = "error";
+                }
             }
         }
 
@@ -66,13 +70,18 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
                     $message = "Kategorie nicht gefunden.";
                     $messageType = "error";
                 } else {
-                    saveCategories($categories);
-                    logAccess("Admin updated category", [
-                        "category_id" => $categoryId,
-                        "label" => $label,
-                    ]);
-                    $message = "Kategorie wurde erfolgreich aktualisiert.";
-                    $messageType = "success";
+                    if (saveCategories($categories)) {
+                        logAccess("Admin updated category", [
+                            "category_id" => $categoryId,
+                            "label" => $label,
+                        ]);
+                        $message = "Kategorie wurde erfolgreich aktualisiert.";
+                        $messageType = "success";
+                    } else {
+                        $message =
+                            "Kategorie konnte nicht gespeichert werden.";
+                        $messageType = "error";
+                    }
                 }
             }
         }
@@ -106,13 +115,17 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
                     $message = "Kategorie nicht gefunden.";
                     $messageType = "error";
                 } else {
-                    saveCategories($categories);
-                    logAccess("Admin deleted category", [
-                        "category_id" => $categoryId,
-                        "label" => $label,
-                    ]);
-                    $message = "Kategorie wurde gelöscht.";
-                    $messageType = "success";
+                    if (saveCategories($categories)) {
+                        logAccess("Admin deleted category", [
+                            "category_id" => $categoryId,
+                            "label" => $label,
+                        ]);
+                        $message = "Kategorie wurde gelöscht.";
+                        $messageType = "success";
+                    } else {
+                        $message = "Kategorie konnte nicht gelöscht werden.";
+                        $messageType = "error";
+                    }
                 }
             }
         }

+ 8 - 4
admin/faq.php

@@ -19,10 +19,14 @@ if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_POST["save_faq"])) {
         $messageType = "error";
     } else {
         $content = isset($_POST["content"]) ? (string) $_POST["content"] : "";
-        saveFaqContent($content);
-        logAccess("Admin updated FAQ content");
-        $message = "FAQ-Inhalt wurde gespeichert.";
-        $messageType = "success";
+        if (saveFaqContent($content)) {
+            logAccess("Admin updated FAQ content");
+            $message = "FAQ-Inhalt wurde gespeichert.";
+            $messageType = "success";
+        } else {
+            $message = "FAQ-Inhalt konnte nicht gespeichert werden.";
+            $messageType = "error";
+        }
     }
 }
 

+ 4 - 1
admin/index.php

@@ -61,7 +61,10 @@ include __DIR__ . '/../includes/header.php';
                 <a href="settings.php">Einstellungen</a>
                 <a href="faq.php">FAQ bearbeiten</a>
                 <a href="admins.php">Admins verwalten</a>
-                <a href="login.php?logout=1">Abmelden</a>
+                <form method="POST" action="login.php" class="inline-form">
+                    <?php echo csrfField(); ?>
+                    <button type="submit" name="logout" class="btn btn-secondary btn-small">Abmelden</button>
+                </form>
             </div>
         </details>
     </div>

+ 25 - 9
admin/login.php

@@ -2,17 +2,32 @@
 require_once __DIR__ . "/../config.php";
 require_once __DIR__ . "/../includes/functions.php";
 
-// Handle logout
-if (isset($_GET["logout"])) {
-    $_SESSION["admin_logged_in"] = false;
-    unset($_SESSION["admin_username"]);
-    session_destroy();
-    header("Location: login.php");
-    exit();
-}
-
 $error = "";
 
+// Handle logout via POST + CSRF
+if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_POST["logout"])) {
+    if (!validateCsrfToken($_POST["csrf_token"] ?? "")) {
+        $error = "Ungültiges Token. Bitte versuchen Sie es erneut.";
+    } else {
+        $_SESSION = [];
+        if (ini_get("session.use_cookies")) {
+            $params = session_get_cookie_params();
+            setcookie(
+                session_name(),
+                "",
+                time() - 42000,
+                $params["path"],
+                $params["domain"],
+                $params["secure"],
+                $params["httponly"],
+            );
+        }
+        session_destroy();
+        header("Location: login.php");
+        exit();
+    }
+}
+
 if ($_SERVER["REQUEST_METHOD"] === "POST") {
     // Validate CSRF token
     if (!validateCsrfToken($_POST["csrf_token"] ?? "")) {
@@ -26,6 +41,7 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
             isset($users[$username]) &&
             password_verify($password, $users[$username])
         ) {
+            session_regenerate_id(true);
             $_SESSION["admin_logged_in"] = true;
             $_SESSION["admin_username"] = $username;
             logAccess("Admin login successful", ["username" => $username]);

+ 34 - 21
admin/organizations.php

@@ -38,13 +38,17 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
                     "sort_order" => $sortOrder,
                     "active" => $active,
                 ];
-                saveOrganizations($organizations);
-                logAccess("Admin added organization", [
-                    "org_id" => $orgId,
-                    "label" => $label,
-                ]);
-                $message = "Organisation wurde angelegt.";
-                $messageType = "success";
+                if (saveOrganizations($organizations)) {
+                    logAccess("Admin added organization", [
+                        "org_id" => $orgId,
+                        "label" => $label,
+                    ]);
+                    $message = "Organisation wurde angelegt.";
+                    $messageType = "success";
+                } else {
+                    $message = "Organisation konnte nicht gespeichert werden.";
+                    $messageType = "error";
+                }
             }
         }
 
@@ -76,13 +80,18 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
                 unset($organization);
 
                 if ($updated) {
-                    saveOrganizations($organizations);
-                    logAccess("Admin updated organization", [
-                        "org_id" => $organizationId,
-                        "label" => $label,
-                    ]);
-                    $message = "Organisation wurde aktualisiert.";
-                    $messageType = "success";
+                    if (saveOrganizations($organizations)) {
+                        logAccess("Admin updated organization", [
+                            "org_id" => $organizationId,
+                            "label" => $label,
+                        ]);
+                        $message = "Organisation wurde aktualisiert.";
+                        $messageType = "success";
+                    } else {
+                        $message =
+                            "Organisation konnte nicht gespeichert werden.";
+                        $messageType = "error";
+                    }
                 } else {
                     $message = "Organisation nicht gefunden.";
                     $messageType = "error";
@@ -109,13 +118,17 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
                     return $organization["id"] !== $organizationId;
                 }),
             );
-            saveOrganizations($organizations);
-            logAccess("Admin deleted organization", [
-                "org_id" => $organizationId,
-                "label" => $orgLabel,
-            ]);
-            $message = "Organisation wurde gelöscht.";
-            $messageType = "success";
+            if (saveOrganizations($organizations)) {
+                logAccess("Admin deleted organization", [
+                    "org_id" => $organizationId,
+                    "label" => $orgLabel,
+                ]);
+                $message = "Organisation wurde gelöscht.";
+                $messageType = "success";
+            } else {
+                $message = "Organisation konnte nicht gelöscht werden.";
+                $messageType = "error";
+            }
         }
 
         $organizations = getOrganizations(false);

+ 35 - 21
admin/products.php

@@ -213,13 +213,18 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
                                 ) + 1;
                         $record["id"] = $newId;
                         $products[] = $record;
-                        saveProducts($products);
-                        logAccess("Admin added product", [
-                            "product_id" => $newId,
-                            "product_name" => $record["name"],
-                        ]);
-                        $message = "Produkt wurde angelegt.";
-                        $messageType = "success";
+                        if (saveProducts($products)) {
+                            logAccess("Admin added product", [
+                                "product_id" => $newId,
+                                "product_name" => $record["name"],
+                            ]);
+                            $message = "Produkt wurde angelegt.";
+                            $messageType = "success";
+                        } else {
+                            $message =
+                                "Produkt konnte nicht gespeichert werden.";
+                            $messageType = "error";
+                        }
                     } else {
                         $updated = false;
                         foreach ($products as &$product) {
@@ -233,13 +238,18 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
                         unset($product);
 
                         if ($updated) {
-                            saveProducts($products);
-                            logAccess("Admin updated product", [
-                                "product_id" => $productId,
-                                "product_name" => $record["name"],
-                            ]);
-                            $message = "Produkt wurde aktualisiert.";
-                            $messageType = "success";
+                            if (saveProducts($products)) {
+                                logAccess("Admin updated product", [
+                                    "product_id" => $productId,
+                                    "product_name" => $record["name"],
+                                ]);
+                                $message = "Produkt wurde aktualisiert.";
+                                $messageType = "success";
+                            } else {
+                                $message =
+                                    "Produkt konnte nicht gespeichert werden.";
+                                $messageType = "error";
+                            }
                         } else {
                             $message = "Produkt nicht gefunden.";
                             $messageType = "error";
@@ -263,13 +273,17 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
                     return (int) $product["id"] !== $productId;
                 }),
             );
-            saveProducts($products);
-            logAccess("Admin deleted product", [
-                "product_id" => $productId,
-                "product_name" => $productName,
-            ]);
-            $message = "Produkt wurde gelöscht.";
-            $messageType = "success";
+            if (saveProducts($products)) {
+                logAccess("Admin deleted product", [
+                    "product_id" => $productId,
+                    "product_name" => $productName,
+                ]);
+                $message = "Produkt wurde gelöscht.";
+                $messageType = "success";
+            } else {
+                $message = "Produkt konnte nicht gelöscht werden.";
+                $messageType = "error";
+            }
         }
     }
 }

+ 8 - 4
admin/settings.php

@@ -29,10 +29,14 @@ if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_POST["save_settings"])) {
             ),
         ];
 
-        saveSystemSettings($settings);
-        logAccess("Admin updated system settings");
-        $message = "Einstellungen wurden gespeichert.";
-        $messageType = "success";
+        if (saveSystemSettings($settings)) {
+            logAccess("Admin updated system settings");
+            $message = "Einstellungen wurden gespeichert.";
+            $messageType = "success";
+        } else {
+            $message = "Einstellungen konnten nicht gespeichert werden.";
+            $messageType = "error";
+        }
     }
 }
 

+ 10 - 0
config.sample.php

@@ -46,5 +46,15 @@ define('UPLOADS_URL', SITE_URL . '/data/uploads');
 
 // Session settings
 if (session_status() === PHP_SESSION_NONE) {
+    $isHttps =
+        (!empty($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] !== "off") ||
+        (isset($_SERVER["SERVER_PORT"]) &&
+            (int) $_SERVER["SERVER_PORT"] === 443);
+
+    ini_set("session.use_strict_mode", "1");
+    ini_set("session.cookie_httponly", "1");
+    ini_set("session.cookie_secure", $isHttps ? "1" : "0");
+    ini_set("session.cookie_samesite", "Lax");
+
     session_start();
 }

+ 8 - 7
includes/functions.php

@@ -325,7 +325,7 @@ function saveAdminAccounts($accounts)
     }
 
     ksort($result);
-    writeJsonFile(ADMINS_FILE, ["admins" => $result]);
+    return writeJsonFile(ADMINS_FILE, ["admins" => $result]);
 }
 
 function getDefaultCategories()
@@ -413,7 +413,7 @@ function getCategories()
 
 function saveCategories($categories)
 {
-    writeJsonFile(CATEGORIES_FILE, [
+    return writeJsonFile(CATEGORIES_FILE, [
         "categories" => normalizeCategories($categories),
     ]);
 }
@@ -658,7 +658,7 @@ function saveProducts($products)
         }
     }
 
-    writeJsonFile(PRODUCTS_FILE, ["products" => array_values($normalized)]);
+    return writeJsonFile(PRODUCTS_FILE, ["products" => array_values($normalized)]);
 }
 
 function getFaqFilePath(): string
@@ -694,9 +694,9 @@ function getFaqContent(): string
     return $data["content"];
 }
 
-function saveFaqContent(string $markdown): void
+function saveFaqContent(string $markdown): bool
 {
-    writeJsonFile(getFaqFilePath(), ["content" => (string) $markdown]);
+    return writeJsonFile(getFaqFilePath(), ["content" => (string) $markdown]);
 }
 
 function renderFaqInlineMarkdown(string $text): string
@@ -904,7 +904,7 @@ function getOrganizations($onlyActive = false)
 
 function saveOrganizations($organizations)
 {
-    writeJsonFile(ORGANIZATIONS_FILE, [
+    return writeJsonFile(ORGANIZATIONS_FILE, [
         "organizations" => normalizeOrganizations($organizations),
     ]);
 }
@@ -1006,7 +1006,7 @@ function getSystemSettings()
 
 function saveSystemSettings($settings)
 {
-    writeJsonFile(SETTINGS_FILE, [
+    return writeJsonFile(SETTINGS_FILE, [
         "settings" => normalizeSystemSettings($settings),
     ]);
 }
@@ -1137,6 +1137,7 @@ function saveOrders($orders)
             "order_count" => count($normalized),
         ]);
     }
+    return (bool) $result;
 }
 
 function generateOrderId()