Verbindliche Entwicklungsstandards für MY-Province.de
Diese Richtlinien dokumentieren sämtliche Sicherheitsmaßnahmen und Code-Standards, die für MY-Province.de (Stand 18. April 2026) eingeführt wurden. Sie gelten als verbindlich für alle zukünftigen Änderungen am Projekt.
Basierend auf den OWASP Top 10 und den spezifischen Anforderungen des Projekts.
Jede PHP-Datei, die Daten verarbeitet oder anzeigt, MUSS eine Session-Prüfung enthalten. Keine Ausnahmen.
Prepared Statements oder (int)-Cast für ALLE Datenbankabfragen. Kein String-Concat mit User-Input.
Alle Ausgaben von Datenbankinhalten oder Benutzereingaben mit htmlspecialchars() escapen.
Datenverändernde Operationen benötigen CSRF-Tokens. AJAX-Calls müssen POST verwenden.
E-Mail-Header dürfen keine unkontrollierten Benutzereingaben enthalten. CRLF-Prüfung obligatorisch.
Sensible Verzeichnisse (config/, tools/, Legacy-Code) müssen per .htaccess gesperrt sein.
Jede PHP-Datei im admin/-Verzeichnis MUSS diesen Block enthalten:
<?php
session_start();
if (!isset($_SESSION['ZUGANG']) || !isset($_SESSION['USER'])) {
http_response_code(403);
die('Zugriff verweigert');
}
?>
require_once __DIR__ . '/core/classes/SessionManager.php';
SessionManager::start();
if (!SessionManager::isLoggedIn()) {
header('Location: /dashboard/public/login.php');
exit;
}
| Einstellung | Wert | Zweck |
|---|---|---|
session.cookie_httponly | true | JavaScript-Zugriff auf Session-Cookie verhindern |
session.cookie_secure | true | Cookie nur über HTTPS senden |
session.cookie_samesite | Strict | CSRF-Schutz auf Cookie-Ebene |
session_regenerate_id(true) | Nach Login | Session-Fixation verhindern |
| Rate Limiting | 5 Versuche / 5 Min. | Brute-Force-Schutz |
| Passwort-Hashing | PASSWORD_ARGON2ID | Moderner Hash-Algorithmus |
$_SESSION['ZUGANG'] wird als bin2hex(random_bytes(32))
gesetzt (String, nicht Boolean). Auth-Checks müssen !isset() verwenden, NICHT !== true.
Jede Variable, die in HTML-Kontext ausgegeben wird, MUSS escaped werden:
// ❌ VERBOTEN – Direkte Ausgabe
echo $row['NAME'];
echo $_POST['field'];
value="<?php echo $row['EMAIL']; ?>"
// ✅ RICHTIG – Escaped Ausgabe
echo htmlspecialchars($row['NAME'] ?? '', ENT_QUOTES, 'UTF-8');
value="<?php echo htmlspecialchars($row['EMAIL'] ?? '', ENT_QUOTES, 'UTF-8'); ?>"
| Kontext | Methode |
|---|---|
| HTML-Inhalt | htmlspecialchars($var, ENT_QUOTES, 'UTF-8') |
| HTML-Attribute | htmlspecialchars($var, ENT_QUOTES, 'UTF-8') |
| IDs in Attributen | (int)$var für numerische IDs |
| JavaScript | json_encode($var) |
| URLs | urlencode($var) |
// ✅ Dashboard – PDO Prepared Statement
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$userId]);
// ✅ Admin CRM – Integer-Cast für IDs
$id = (int)($_POST['ID'] ?? 0);
$result = $db->select('CLIENT', '*', "ID = '".$id."'");
// ❌ VERBOTEN – String-Konkatenation mit User-Input
$result = $db->select("CLIENT", "*", "ID = '".$_POST['id']."'");
$sql = "SELECT * FROM users WHERE name = '" . $username . "'";
// ❌ VERBOTEN – Unkontrollierte DB-Werte in Queries
$result = $db->select("SECTOR", "*", "ID = '".$row['SECTOR_TYP']."'");
// ✅ RICHTIG – Cast auch bei DB-Werten (Second-Order SQLi)
$result = $db->select("SECTOR", "*", "ID = '".(int)$row['SECTOR_TYP']."'");
(int) gecastet werden,
bevor sie in weitere Queries einfließen.
| Verzeichnis | Schutz | Methode |
|---|---|---|
config/ | Vollständig gesperrt | .htaccess: Deny from all |
dashboard/config/ | Vollständig gesperrt | .htaccess: Deny from all |
dashboard/tools/ | Vollständig gesperrt | .htaccess: Deny from all |
survey/ | PHP-Dateien gesperrt | .htaccess: Files *.php Deny |
web-work/ | Legacy – gesperrt | .htaccess: Deny from all |
admin/mysql/ | Backend deaktiviert | mysql.php: die() |
<Files> matched NUR Dateinamen,
KEINE Pfade! <Files "config/*"> funktioniert NICHT.
Stattdessen .htaccess direkt ins zu schützende Verzeichnis legen.
# Gefährliche Dateitypen blockieren
<FilesMatch "\.(sql|bak|old|log|env)$">
Deny from all
</FilesMatch>
# Sensible PHP-Dateien blockieren
<FilesMatch "^(mysql|myDB|database|config)\.(php|inc)$">
Deny from all
</FilesMatch>
| Header | Wert | Schutz gegen |
|---|---|---|
X-Frame-Options | DENY | Clickjacking |
X-Content-Type-Options | nosniff | MIME-Type-Sniffing |
X-XSS-Protection | 1; mode=block | Reflektiertes XSS (Legacy-Browser) |
Referrer-Policy | strict-origin-when-cross-origin | Information Leakage |
Strict-Transport-Security | max-age=31536000; includeSubDomains | Downgrade-Angriffe / MITM |
Content-Security-Policy | default-src 'self'; ... | XSS, Data Injection |
// CRLF-Injection verhindern bei E-Mail-Headern
if (preg_match('/[\r\n%0a%0d]/i', $email)) {
die('Ungültige Eingabe erkannt.');
}
Diese Regeln gelten projektübergreifend und sichern Wartbarkeit, Lesbarkeit und Sicherheit.
.css-Dateien.js-Dateienstyle="..." in HTML-Elementen.feature-card-*, .card-title-white.js-Dateien statt <script>-Blöckeonclick="..." bei neuem Code (Event-Listener)loadExample()-Pattern.css()-Aufrufedisplay_errors = 0 in Produktion$_POST['key'] ?? 0 mit Null-Coalescing$row['FIELD'] ?? '' für DB-Ergebnisse@-Error-Suppression nutzenheader.php, footer.phpproject-components.css*-old.php-Dateien löschen.htaccess sperren| Aspekt | Richtlinie | Beispiel |
|---|---|---|
| Encoding | Immer UTF-8 | <meta charset="UTF-8"> |
| Sprache | UI + Kommentare auf Deutsch | // Benutzer authentifizieren |
| Variablen | camelCase für lokale Variablen | $clientId, $resultSector |
| Klassen | PascalCase | Database, SessionManager |
| Konstanten | UPPER_SNAKE_CASE | DB_HOST, DASHBOARD_INIT |
| DB-Spalten | UPPER_SNAKE_CASE (bestehend) | CLIENT_STATUS, SECTOR_TYP |
| Einrückung | Tabs in PHP, Spaces in CSS/JS | Konsistent pro Datei |
| String-Quotes | Einfache Quotes bevorzugt | 'text' statt "text" |
/* Komponentenbasierte Klassen */
.feature-card-success /* Grüne Erfolgskarte */
.feature-card-primary /* Blaue Hauptkarte */
.feature-card-warning /* Orange Warnkarte */
.feature-card-info /* Lila Infokarte */
/* Inhaltsklassen */
.card-title-white /* Weiße Kartentitel */
.card-text-white /* Weiße Kartentexte */
/* Utility-Klassen */
.responsive-image /* max-width: 100% */
.hidden /* display: none !important */
.text-center /* Textausrichtung */
| Sprache | Prefix | Beispiel |
|---|---|---|
| C# | cs-* | .cs-keyword, .cs-class, .cs-string |
| JavaScript | js-* | .js-keyword, .js-function |
| SQL | sql-* | .sql-keyword, .sql-string |
| PHP | php-* | .php-keyword, .php-variable |
<!-- Standard-Seitenstruktur -->
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="...">
<title>Titel - MyProvince.de</title>
<link rel="stylesheet" href="/web/css/style.css">
</head>
<body>
<?php include 'includes/header.php'; ?>
<main> <!-- Inhalt --> </main>
<?php include 'includes/footer.php'; ?>
<script src="/web/js/script.js"></script>
</body>
</html>
// ✅ Standard AJAX-Muster für Admin-Operationen
$.ajax({
type: 'POST', // IMMER POST für Datenänderungen
url: '/admin/api.php',
data: {
action: 'update',
table: 'CLIENT',
csrf_token: csrfToken, // CSRF-Token mitsenden
id: clientId,
name: clientName
},
success: function(response) { /* ... */ }
});
Chronologische Übersicht aller durchgeführten Sicherheitsmaßnahmen.
| Datum | Kategorie | Maßnahme | Status |
|---|---|---|---|
| 17.04.2026 | Auth | Session-Prüfung in 10x admin/formular/*.php | Erledigt |
| 17.04.2026 | Auth | Auth-Check clientList.php, setting_sectorList.php | Erledigt |
| 17.04.2026 | Auth | SessionManager-Auth für db-schema-export.php | Erledigt |
| 17.04.2026 | Auth | Auth-Logik Fix: !== true → !isset() (10 Dateien) | Erledigt |
| 17.04.2026 | SQLi | (int)-Cast für IDs in Formular-Dateien | Erledigt |
| 17.04.2026 | SQLi | Second-Order SQLi Fix in clientList.php | Erledigt |
| 17.04.2026 | SQLi | Prepared Statements in survey/ | Erledigt |
| 17.04.2026 | XSS | htmlspecialchars() in allen Formular-Ausgaben | Erledigt |
| 17.04.2026 | XSS | Reflected XSS Fix setting_sector_edit.php | Erledigt |
| 17.04.2026 | CRLF | Header-Injection-Schutz contact_process.php | Erledigt |
| 17.04.2026 | Access | .htaccess für survey/, web-work/, tools/ | Erledigt |
| 17.04.2026 | Access | Root .htaccess: Kaputte Files-Direktiven entfernt | Erledigt |
| 17.04.2026 | Headers | HSTS + verbesserte CSP hinzugefügt | Erledigt |
| 17.04.2026 | Cleanup | 6x *-old.php Debug-Dateien gelöscht | Erledigt |
| 17.04.2026 | Info Leak | Temp-Passwort aus Browser-Anzeige entfernt | Erledigt |
| 17.04.2026 | Info Leak | debug-image.php deaktiviert (403) | Erledigt |
| 17.04.2026 | Deprecation | FILTER_SANITIZE_STRING → htmlspecialchars() | Erledigt |
| 18.04.2026 | XSS | htmlspecialchars() in *_edit.php (30+ Felder) | Erledigt |
| 18.04.2026 | Config | .gitignore für .vscode/, Logs, Temp | Erledigt |