Erste Version vom Implementierungshandbuch angelegt
parent
8d31b172dc
commit
78165248f7
737
Implementierungshandbuch-IIS-PHP-AD.-.md
Normal file
737
Implementierungshandbuch-IIS-PHP-AD.-.md
Normal file
@ -0,0 +1,737 @@
|
||||
|
||||
# Technisches Implementierungshandbuch: PHP-basierte Active Directory-Verwaltung mit IIS auf Windows Server 2025
|
||||
|
||||
---
|
||||
|
||||
## Zusammenfassung
|
||||
|
||||
Dieses Dokument beschreibt die detaillierte, produktionsreife Implementierung einer PHP-Webanwendung auf einem Windows Server 2025 Datacenter, die über die Internet Information Services (IIS) bereitgestellt wird.
|
||||
|
||||
Die Anwendung erfüllt folgende hoch privilegierte Aufgaben:
|
||||
|
||||
- Authentifizierung von Administratoren über LDAP
|
||||
- Abfrage von Servermetriken über SNMP
|
||||
- Erstellung von Active-Directory-(AD)-Benutzern (einzeln und als CSV-Massenimport)
|
||||
|
||||
Die AD-Benutzererstellung wird durch die sichere Ausführung von PowerShell-Skripten aus PHP heraus realisiert. Die Skripte verarbeiten sowohl Einzelbenutzer als auch CSV-Massenimporte.
|
||||
|
||||
Der Schwerpunkt dieses Handbuchs liegt auf der Konfiguration einer robusten und sicheren Architektur nach dem **Least-Privilege-Prinzip**, um Risiken durch Web-basierten Zugriff auf AD und Serverdienste zu minimieren.
|
||||
|
||||
---
|
||||
|
||||
## Teil 1: Einrichtung der Basisinfrastruktur (IIS, PHP & FastCGI)
|
||||
|
||||
Dieser Abschnitt legt das Fundament für die Webanwendung durch die Installation und Konfiguration des Webservers und der PHP-Laufzeitumgebung auf einem sauberen Windows Server 2025.
|
||||
|
||||
### 1.1 Installation der IIS-Serverrolle
|
||||
|
||||
1. Öffnen des Server-Managers.
|
||||
2. Auswahl von **Verwalten → Rollen und Features hinzufügen**.
|
||||
3. Im Assistenten zur Seite **Serverrollen** navigieren.
|
||||
4. **Webserver (IIS)** auswählen.
|
||||
5. Im erscheinenden Pop-up auf **Features hinzufügen** klicken.
|
||||
6. Zur Seite **Rollendienste** fortfahren.
|
||||
7. Unter **Webserver → Anwendungsentwicklung** den Knoten erweitern.
|
||||
8. Das Kontrollkästchen **CGI** aktivieren.
|
||||
|
||||
**Technische Erläuterung:**
|
||||
Die Auswahl von **CGI** ist entscheidend. Diese Option installiert nicht nur klassisches CGI, sondern auch das moderne **FastCGI-Modul**, das für die performante und stabile Anbindung von PHP an IIS erforderlich ist. Ohne FastCGI kann IIS nicht mit `php-cgi.exe` kommunizieren.
|
||||
|
||||
9. Den Assistenten abschließen und die Installation abwarten.
|
||||
|
||||
---
|
||||
|
||||
### 1.2 Installation der PHP-Laufzeitumgebung
|
||||
|
||||
Die Installation von PHP erfolgt manuell, da der Web Platform Installer (WPI) nicht mehr unterstützt wird.
|
||||
|
||||
#### Voraussetzung: Visual C++ Redistributable
|
||||
|
||||
PHP unter Windows benötigt das **Microsoft Visual C++ 2015–2022 Redistributable (x64)**.
|
||||
|
||||
1. Neueste x64-Version von Microsoft herunterladen (`vc_redist.x64.exe`).
|
||||
2. Installation ausführen und abschließen.
|
||||
|
||||
#### PHP-Download
|
||||
|
||||
1. Zur offiziellen Download-Seite für PHP unter Windows wechseln:
|
||||
`https://windows.php.net/download/`
|
||||
2. Die **x64 Non-Thread Safe (NTS)** Version der gewünschten PHP-Version (z.B. PHP 8.3) im **Zip-Format** auswählen.
|
||||
|
||||
**Technische Erläuterung:**
|
||||
Die NTS-Version ist für den Betrieb mit IIS + FastCGI optimiert. FastCGI übernimmt das Prozess-Pooling, daher ist Thread-Safety in PHP selbst nicht erforderlich. Die Verwendung einer Thread-Safe-Version (TS) kann hier zu Performance- und Stabilitätsproblemen führen.
|
||||
|
||||
#### PHP-Installation
|
||||
|
||||
1. Ein Verzeichnis für PHP erstellen, z.B.:
|
||||
`C:\PHP`
|
||||
2. Das heruntergeladene ZIP-Archiv nach `C:\PHP` entpacken.
|
||||
|
||||
---
|
||||
|
||||
### 1.3 Konfiguration von IIS für PHP (Handler Mapping)
|
||||
|
||||
Nun muss IIS angewiesen werden, wie `.php`-Dateien behandelt werden. Dies erfolgt über eine **Handler-Zuordnung**.
|
||||
|
||||
1. IIS-Manager starten (`inetmgr`).
|
||||
2. Im linken Bereich **Verbindungen** den Servernamen (oberste Ebene) auswählen.
|
||||
3. Im mittleren Bereich auf **Handlerzuordnungen** doppelklicken.
|
||||
4. Im rechten Bereich unter **Aktionen** auf **Modulzuordnung hinzufügen…** klicken.
|
||||
5. Felder wie folgt ausfüllen:
|
||||
|
||||
- **Anforderungspfad:** `*.php`
|
||||
- **Modul:** `FastCgiModule`
|
||||
- **Ausführbare Datei:** `C:\PHP\php-cgi.exe` (Pfad ggf. anpassen)
|
||||
- **Name:** z. B. `PHP via FastCGI`
|
||||
|
||||
6. Mit **OK** bestätigen.
|
||||
7. Die Nachfrage, ob eine FastCGI-Anwendung angelegt werden soll, mit **Ja** bestätigen.
|
||||
|
||||
---
|
||||
|
||||
### 1.4 Konfiguration der „Default Web Site“
|
||||
|
||||
1. Im IIS-Manager im linken Bereich **Websites** erweitern.
|
||||
2. Rechtsklick auf **Default Web Site** → **Verwalten der Website → Erweiterte Einstellungen…**
|
||||
3. Die Eigenschaft **Physischer Pfad** suchen.
|
||||
4. Den Standardpfad (z.B. `%SystemDrive%\inetpub\wwwroot`) ändern auf den `public`-Ordner des Projekts, z.B.:
|
||||
`C:\Web\AdAdminPanel\public`
|
||||
5. Mit **OK** bestätigen.
|
||||
|
||||
Ab jetzt leitet IIS Anfragen an `http://localhost/` in das Verzeichnis `C:\Web\AdAdminPanel\public`.
|
||||
|
||||
---
|
||||
|
||||
### 1.5 Validierung der Basisinstallation
|
||||
|
||||
1. Eine neue Textdatei `phpinfo.php` in
|
||||
`C:\Web\AdAdminPanel\public` erstellen.
|
||||
2. Folgenden Inhalt einfügen:
|
||||
|
||||
```php
|
||||
<?php
|
||||
phpinfo();
|
||||
```
|
||||
|
||||
3. Im Browser `http://localhost/phpinfo.php` aufrufen.
|
||||
|
||||
Wenn alles korrekt ist, erscheint die PHP-Info-Seite mit allen Konfigurationsdetails.
|
||||
|
||||
**Wichtig:**
|
||||
Den Wert bei **Loaded Configuration File (php.ini) Path** notieren. Dieser Pfad ist wichtig für die Konfiguration in **Teil 3**.
|
||||
|
||||
**Sicherheit:**
|
||||
Die Datei `phpinfo.php` nach der Validierung wieder löschen.
|
||||
|
||||
---
|
||||
|
||||
## Teil 2: Konfiguration der Host-Dienste (SNMP & Active Directory)
|
||||
|
||||
Bevor die PHP-Anwendung konfiguriert wird, müssen die Zieldienste auf dem Server (SNMP) und in der Domäne (Active Directory) vorbereitet werden.
|
||||
|
||||
### 2.1 Aktivierung und Konfiguration des SNMP-Dienstes
|
||||
|
||||
#### Installation des SNMP-Dienstes
|
||||
|
||||
Unter Windows Server 2025 erfolgt die Installation bevorzugt über PowerShell:
|
||||
|
||||
```powershell
|
||||
Install-WindowsFeature SNMP-Service,SNMP-WMI-Provider -IncludeManagementTools
|
||||
```
|
||||
|
||||
#### Konfiguration des SNMP-Dienstes
|
||||
|
||||
1. `services.msc` öffnen.
|
||||
2. Den Dienst **SNMP Service** suchen und **Eigenschaften** öffnen.
|
||||
|
||||
**Registerkarte „Agent“:**
|
||||
|
||||
- Optional **Kontakt** und **Standort** eintragen.
|
||||
- Unter **Dienst** passende Kategorien aktivieren (z.B. *Physisch*, *Anwendungen*, *Internet*).
|
||||
|
||||
**Registerkarte „Sicherheit“ (kritischer Schritt):**
|
||||
|
||||
- Unter **Akzeptierte Communitynamen** → **Hinzufügen…**
|
||||
- Rechte: **SCHREIBGESCHÜTZT (READ ONLY)**
|
||||
- Community-Name, z.B. `public_ro` (nicht `public` verwenden).
|
||||
- Unter **SNMP-Pakete von diesen Hosts annehmen** → **Hinzufügen…**
|
||||
- `127.0.0.1` eintragen.
|
||||
|
||||
**Technische Erläuterung:**
|
||||
Die Beschränkung auf `127.0.0.1` stellt sicher, dass nur lokale Prozesse (z.B. PHP) den SNMP-Dienst abfragen können. Anfragen anderer Hosts werden verworfen.
|
||||
|
||||
Den SNMP-Dienst nach der Konfiguration neu starten.
|
||||
|
||||
---
|
||||
|
||||
### 2.2 Vorbereitung von Active Directory (OU und Dienstkonto)
|
||||
|
||||
#### Organisationseinheit (OU) erstellen
|
||||
|
||||
1. **Active Directory-Benutzer und -Computer** (`dsa.msc`) öffnen.
|
||||
2. Rechtsklick auf die Domäne → **Neu → Organisationseinheit**.
|
||||
3. Namen vergeben, z.B. `WebAppUsers`.
|
||||
|
||||
Diese OU dient als isolierter Container für alle Benutzer, die über die PHP-Anwendung erstellt werden. Dort wird später die Rechte-Delegierung vorgenommen.
|
||||
|
||||
#### Dienstkonto (Service Account) erstellen
|
||||
|
||||
1. Einen neuen Standard-Domänenbenutzer erstellen, z.B.:
|
||||
- Benutzername: `svc_iis_php_ad`
|
||||
2. Keiner administrativen Gruppe (z.B. *Domänen-Admins*) hinzufügen.
|
||||
3. Ein langes, komplexes Kennwort vergeben (25+ Zeichen).
|
||||
4. Kontooptionen:
|
||||
- **Kennwort läuft nie ab** aktivieren.
|
||||
- **Benutzer kann Kennwort nicht ändern** aktivieren.
|
||||
- **Benutzer muss Kennwort bei der nächsten Anmeldung ändern** deaktivieren.
|
||||
|
||||
Dieses Konto wird später als Identität des IIS-Anwendungspools verwendet.
|
||||
|
||||
---
|
||||
|
||||
## Teil 3: Erweiterte PHP-Konfiguration (LDAP und SNMP aktivieren)
|
||||
|
||||
Nun werden die PHP-Erweiterungen aktiviert, die für LDAP-Authentifizierung und SNMP-Abfragen benötigt werden.
|
||||
|
||||
### 3.1 Bearbeitung der `php.ini`
|
||||
|
||||
1. Zum PHP-Installationsverzeichnis wechseln, z.B. `C:\PHP`.
|
||||
2. Falls keine `php.ini` existiert:
|
||||
- `php.ini-production` nach `php.ini` kopieren.
|
||||
3. `php.ini` mit einem Editor (z.B. Notepad++ als Administrator) öffnen.
|
||||
|
||||
### 3.2 Aktivierung der PHP-Erweiterungen
|
||||
|
||||
1. In der `php.ini` nach `extension_dir` suchen und sicherstellen, dass es auf das `ext`-Verzeichnis zeigt:
|
||||
|
||||
```ini
|
||||
extension_dir = "ext"
|
||||
```
|
||||
|
||||
2. Folgende Zeilen aktivieren (Semikolon am Zeilenanfang entfernen):
|
||||
|
||||
```ini
|
||||
extension=ldap
|
||||
extension=snmp
|
||||
extension=openssl
|
||||
```
|
||||
|
||||
- **ldap**: für Administrator-Authentifizierung via LDAP
|
||||
- **snmp**: für SNMP-Abfragen (Servermetriken)
|
||||
- **openssl**: u. a. für LDAPS (LDAP über SSL/TLS)
|
||||
|
||||
### 3.3 Behebung von Windows-spezifischen DLL-Abhängigkeiten
|
||||
|
||||
Erweiterungen wie `php_ldap.dll` benötigen zusätzliche DLLs (z.B. `libsasl.dll`, `libcrypto-*.dll`, `libssl-*.dll`), die sich im PHP-Stammverzeichnis befinden.
|
||||
|
||||
**Typische Symptome:**
|
||||
|
||||
- In `phpinfo()` fehlen die Sektionen `ldap` oder `snmp`.
|
||||
- In der Ereignisanzeige oder in IIS-Logs erscheinen PHP-Startwarnungen.
|
||||
|
||||
**Lösung (Best Practice):**
|
||||
|
||||
1. Systemsteuerung → **System → Erweiterte Systemeinstellungen**.
|
||||
2. **Umgebungsvariablen…** öffnen.
|
||||
3. Unter **Systemvariablen** die Variable `Path` bearbeiten.
|
||||
4. **Neu**: `C:\PHP` hinzufügen.
|
||||
5. Alle Fenster mit **OK** schließen.
|
||||
|
||||
**Erforderlicher Schritt:**
|
||||
|
||||
- Vollständigen Neustart des Servers durchführen
|
||||
**oder** zumindest die Dienste **W3SVC** und **WAS** neu starten, damit der IIS-Prozess `w3wp.exe` den aktualisierten `PATH` übernimmt.
|
||||
|
||||
### 3.4 Überprüfung der geladenen Module
|
||||
|
||||
- `phpinfo.php` erneut aufrufen.
|
||||
- Mit `Strg+F` nach `ldap` und `snmp` suchen.
|
||||
|
||||
Sind separate Konfigurationsblöcke für `ldap` und `snmp` sichtbar, wurden die Module korrekt geladen.
|
||||
|
||||
#### Tabelle 1: Erforderliche PHP-Erweiterungen und Abhängigkeiten
|
||||
|
||||
| Erweiterung | `php.ini`-Eintrag | Wichtige DLLs (im PHP-Stammverzeichnis) | Zweck |
|
||||
|------------|---------------------|--------------------------------------------------------|--------------------------------------------------------|
|
||||
| LDAP | `extension=ldap` | `libsasl.dll`, `libcrypto-*.dll`, `libssl-*.dll` | Administrator-Authentifizierung (Login) |
|
||||
| SNMP | `extension=snmp` | (i. d. R. keine zusätzlichen DLLs) | Abfrage von Serverinformationen (CPU, RAM, Uptime) |
|
||||
| OpenSSL | `extension=openssl` | `libcrypto-*.dll`, `libssl-*.dll` | LDAPS/HTTPS-Funktionalität |
|
||||
|
||||
---
|
||||
|
||||
## Teil 4: Die PowerShell-Automatisierungsebene
|
||||
|
||||
Die AD-Operationen werden über PowerShell-Skripte ausgeführt, die als sichere, parametrisierte Schnittstelle zwischen PHP und Active Directory dienen.
|
||||
|
||||
**Pfad für Skripte:**
|
||||
`C:\Web\AdAdminPanel\scripts\powershell\`
|
||||
|
||||
### 4.1 Skript für einzelne Benutzererstellung (`Create-ADUser.ps1`)
|
||||
|
||||
```powershell
|
||||
# C:\Web\AdAdminPanel\scripts\powershell\Create-ADUser.ps1
|
||||
|
||||
param(
|
||||
[Parameter(Mandatory=$true)][string]$Username,
|
||||
[Parameter(Mandatory=$true)][string]$Password,
|
||||
[Parameter(Mandatory=$true)][string]$GivenName,
|
||||
[Parameter(Mandatory=$true)][string]$Surname,
|
||||
[Parameter(Mandatory=$true)][string]$OUPath
|
||||
)
|
||||
|
||||
try {
|
||||
Import-Module ActiveDirectory -ErrorAction Stop
|
||||
|
||||
# Kritisch: Konvertierung des Klartext-Passworts in einen SecureString
|
||||
$SecurePassword = ConvertTo-SecureString -String $Password -AsPlainText -Force
|
||||
|
||||
$userParams = @{
|
||||
Name = "$GivenName $Surname"
|
||||
GivenName = $GivenName
|
||||
Surname = $Surname
|
||||
SamAccountName = $Username
|
||||
UserPrincipalName = "$Username@yourdomain.com" # "yourdomain.com" anpassen
|
||||
AccountPassword = $SecurePassword
|
||||
Path = $OUPath
|
||||
Enabled = $true
|
||||
ChangePasswordAtLogon = $true
|
||||
}
|
||||
|
||||
New-ADUser @userParams
|
||||
|
||||
Write-Output "Erfolg: Benutzer $Username wurde in der OU $OUPath erstellt."
|
||||
}
|
||||
catch {
|
||||
Write-Error "Fehler bei der Benutzererstellung für $Username: $($_.Exception.Message)"
|
||||
exit 1
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4.2 Skript für CSV-Massenimport (`Bulk-Create-ADUsers.ps1`)
|
||||
|
||||
```powershell
|
||||
# C:\Web\AdAdminPanel\scripts\powershell\Bulk-Create-ADUsers.ps1
|
||||
|
||||
param(
|
||||
[Parameter(Mandatory=$true)][string]$CsvPath,
|
||||
[Parameter(Mandatory=$true)][string]$OUPath
|
||||
)
|
||||
|
||||
$domainSuffix = "@yourdomain.com" # Anpassen
|
||||
|
||||
try {
|
||||
Import-Module ActiveDirectory -ErrorAction Stop
|
||||
|
||||
# Erwartete Spalten: SamAccountName, GivenName, Surname, Password
|
||||
$users = Import-Csv -Path $CsvPath
|
||||
|
||||
if ($null -eq $users) {
|
||||
Write-Warning "Die CSV-Datei unter $CsvPath ist leer oder konnte nicht gelesen werden."
|
||||
exit 0
|
||||
}
|
||||
|
||||
foreach ($user in $users) {
|
||||
try {
|
||||
$SecurePassword = ConvertTo-SecureString -String $user.Password -AsPlainText -Force
|
||||
|
||||
$userParams = @{
|
||||
Name = "$($user.GivenName) $($user.Surname)"
|
||||
GivenName = $user.GivenName
|
||||
Surname = $user.Surname
|
||||
SamAccountName = $user.SamAccountName
|
||||
UserPrincipalName = "$($user.SamAccountName)$domainSuffix"
|
||||
AccountPassword = $SecurePassword
|
||||
Path = $OUPath
|
||||
Enabled = $true
|
||||
ChangePasswordAtLogon = $true
|
||||
}
|
||||
|
||||
New-ADUser @userParams
|
||||
Write-Output "Erfolg (Bulk): Benutzer $($user.SamAccountName) wurde erstellt."
|
||||
}
|
||||
catch {
|
||||
Write-Warning "Fehler bei Benutzer $($user.SamAccountName): $($_.Exception.Message)"
|
||||
}
|
||||
}
|
||||
|
||||
Write-Output "Massenimport abgeschlossen."
|
||||
}
|
||||
catch {
|
||||
Write-Error "Schwerwiegender Fehler beim Massenimport: $($_.Exception.Message)"
|
||||
exit 1
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Teil 5: Sicherheitsarchitektur (IIS, PHP und PowerShell)
|
||||
|
||||
Die größte Herausforderung ist die sichere Verbindung zwischen der IIS-Webanwendung (niedrige Vertrauensstellung) und Active Directory (hohe Vertrauensstellung).
|
||||
|
||||
### 5.1 Analyse des Sicherheitsproblems
|
||||
|
||||
`shell_exec()` in PHP wird im Sicherheitskontext des IIS-Anwendungspool-Benutzers ausgeführt. Standardmäßig ist dies ein virtuelles Konto wie `IIS APPPOOL\DefaultAppPool` mit sehr wenigen Rechten. Dieses Konto darf weder:
|
||||
|
||||
- das AD-PowerShell-Modul nutzen,
|
||||
- noch AD-Objekte erstellen,
|
||||
- noch sich an Domänencontrollern authentifizieren.
|
||||
|
||||
**Falsche Lösung:** Dem AppPool Domänen-Admin-Rechte geben → massive Sicherheitslücke.
|
||||
|
||||
**Korrekte Lösung:** Verwendung des dedizierten Dienstkontos `svc_iis_php_ad` (Least Privilege) und gezielte Rechte-Delegierung.
|
||||
|
||||
---
|
||||
|
||||
### 5.2 Konfiguration der IIS-Anwendungspool-Identität
|
||||
|
||||
1. IIS-Manager öffnen.
|
||||
2. **Anwendungspools** auswählen.
|
||||
3. Rechtsklick → **Anwendungspool hinzufügen…**
|
||||
- Name: `PHP_AD_AppPool`
|
||||
- .NET CLR-Version: **Kein verwalteter Code**
|
||||
4. Auf die Website (z.B. **Default Web Site**) wechseln → **Basis-Einstellungen…** bzw. **Standardeinstellungen…** und den Anwendungspool auf `PHP_AD_AppPool` umstellen.
|
||||
5. In der Liste der Anwendungspools:
|
||||
- `PHP_AD_AppPool` markieren → **Erweiterte Einstellungen…**
|
||||
- Unter **Prozessmodell → Identität** → **Benutzerdefiniertes Konto** auswählen.
|
||||
- **Festlegen…** → Anmeldeinformationen für `IHREDOMÄNE\svc_iis_php_ad` eintragen.
|
||||
|
||||
Ab jetzt läuft der AppPool im Kontext des Dienstkontos.
|
||||
|
||||
---
|
||||
|
||||
### 5.3 Delegierung von AD-Berechtigungen
|
||||
|
||||
1. Auf einem Domänencontroller `dsa.msc` öffnen.
|
||||
2. Rechtsklick auf OU **WebAppUsers** → **Objektverwaltung zuweisen…**
|
||||
3. Im Assistenten:
|
||||
- **Weiter** → **Hinzufügen…** → Konto `svc_iis_php_ad` auswählen.
|
||||
- **Weiter** → **Eine benutzerdefinierte Aufgabe zum Zuweisen erstellen**.
|
||||
- Objekttyp: **Nur die folgenden Objekttypen im Ordner** → **Benutzerobjekte** aktivieren.
|
||||
- Berechtigungen:
|
||||
- **Diese Objekte im Ordner erstellen** (ggf. auch löschen).
|
||||
- **Alle Eigenschaften schreiben**
|
||||
- **Kennwort zurücksetzen**
|
||||
- **Kennwort ändern**
|
||||
|
||||
**Ergebnis:**
|
||||
`svc_iis_php_ad` kann nur Benutzerobjekte innerhalb der OU `WebAppUsers` erstellen/ändern – und sonst nichts.
|
||||
|
||||
---
|
||||
|
||||
### 5.4 PowerShell-Ausführungsrichtlinie
|
||||
|
||||
Standardmäßig gilt `Restricted`. Statt die Richtlinie global zu ändern, wird sie pro Aufruf übergangen mit:
|
||||
|
||||
```powershell
|
||||
-ExecutionPolicy ByPass -NoProfile
|
||||
```
|
||||
|
||||
Dies wird in den PHP-Skripten beim Aufruf von `powershell.exe` verwendet.
|
||||
|
||||
---
|
||||
|
||||
### 5.5 Dateisystemberechtigungen (NTFS)
|
||||
|
||||
Dem Dienstkonto `svc_iis_php_ad` werden nur die minimal erforderlichen NTFS-Rechte gewährt:
|
||||
|
||||
- `C:\PHP` → Lesen & Ausführen
|
||||
- `C:\Web\AdAdminPanel\public` → Lesen
|
||||
- `C:\Web\AdAdminPanel\scripts\powershell` → Lesen & Ausführen
|
||||
- `C:\Web\AdAdminPanel\storage\uploads` → Ändern/Schreiben (für CSV-Uploads)
|
||||
|
||||
---
|
||||
|
||||
## Teil 6: Implementierung der PHP-Anwendungslogik
|
||||
|
||||
Die folgenden PHP-Dateien liegen im Web-Stammverzeichnis, z.B.:
|
||||
`C:\Web\AdAdminPanel\public`
|
||||
|
||||
### 6.1 Modul 1: Administrator-Authentifizierung (LDAP-Login)
|
||||
|
||||
**Datei:** `login.php`
|
||||
|
||||
```php
|
||||
<?php
|
||||
// login.php
|
||||
session_start();
|
||||
$error = '';
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
// Domänencontroller und Domäne anpassen
|
||||
$ldap_server = "ldap://dc01.yourdomain.com";
|
||||
$domain = "@yourdomain.com";
|
||||
|
||||
// Anmeldung mit UPN
|
||||
$ldap_user_dn = $_POST['username'] . $domain;
|
||||
$ldap_pass = $_POST['password'];
|
||||
|
||||
$ldap_conn = ldap_connect($ldap_server);
|
||||
if (!$ldap_conn) {
|
||||
$error = "Fehler: Verbindung zum LDAP-Server fehlgeschlagen.";
|
||||
} else {
|
||||
ldap_set_option($ldap_conn, LDAP_OPT_PROTOCOL_VERSION, 3);
|
||||
ldap_set_option($ldap_conn, LDAP_OPT_REFERRALS, 0);
|
||||
|
||||
// @ unterdrückt Warnungen bei fehlerhaftem Login
|
||||
if (@ldap_bind($ldap_conn, $ldap_user_dn, $ldap_pass)) {
|
||||
$_SESSION['admin_user'] = $ldap_user_dn;
|
||||
header("Location: dashboard.php");
|
||||
exit;
|
||||
} else {
|
||||
$error = "LDAP-Bind fehlgeschlagen: Ungültiger Benutzername oder Passwort.";
|
||||
}
|
||||
|
||||
ldap_close($ldap_conn);
|
||||
}
|
||||
}
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Admin Login</title>
|
||||
</head>
|
||||
<body>
|
||||
<h2>Admin Login</h2>
|
||||
<?php if ($error): ?>
|
||||
<p style="color:red;"><?php echo htmlspecialchars($error); ?></p>
|
||||
<?php endif; ?>
|
||||
<form method="post" action="login.php">
|
||||
Benutzername: <input type="text" name="username"><br>
|
||||
Passwort: <input type="password" name="password"><br>
|
||||
<input type="submit" value="Anmelden">
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 6.2 Modul 2: Server-Monitoring (SNMP)
|
||||
|
||||
**Datei:** `dashboard.php`
|
||||
|
||||
```php
|
||||
<?php
|
||||
// dashboard.php
|
||||
session_start();
|
||||
if (!isset($_SESSION['admin_user'])) {
|
||||
header("Location: login.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
// SNMP-Konfiguration
|
||||
$community = 'public_ro';
|
||||
$host = '127.0.0.1';
|
||||
|
||||
snmp_set_quick_print(true);
|
||||
snmp_set_oid_output_format(SNMP_OID_OUTPUT_NUMERIC);
|
||||
|
||||
// CPU-Last (erster Kern, Beispiel)
|
||||
$cpu_oid = '.1.3.6.1.2.1.25.3.3.1.2.1';
|
||||
$cpu_load = @snmpget($host, $community, $cpu_oid, 1000000, 2);
|
||||
|
||||
// System Uptime
|
||||
$uptime_oid = '.1.3.6.1.2.1.25.1.1.0';
|
||||
$uptime_raw = @snmpget($host, $community, $uptime_oid);
|
||||
$uptime = $uptime_raw ? ($uptime_raw / (100 * 60 * 60 * 24)) . " Tage" : "Fehler";
|
||||
|
||||
// RAM (statisches Beispiel mit Index 5)
|
||||
$ram_total_oid = '.1.3.6.1.2.1.25.2.3.1.5.5';
|
||||
$ram_used_oid = '.1.3.6.1.2.1.25.2.3.1.6.5';
|
||||
$ram_alloc_units_oid = '.1.3.6.1.2.1.25.2.3.1.4.5';
|
||||
|
||||
$ram_total_raw = @snmpget($host, $community, $ram_total_oid);
|
||||
$ram_used_raw = @snmpget($host, $community, $ram_used_oid);
|
||||
$ram_units = @snmpget($host, $community, $ram_alloc_units_oid);
|
||||
|
||||
if ($ram_total_raw && $ram_used_raw && $ram_units) {
|
||||
$ram_total_gb = ($ram_total_raw * $ram_units) / (1024 ** 3);
|
||||
$ram_used_gb = ($ram_used_raw * $ram_units) / (1024 ** 3);
|
||||
$ram_percent = ($ram_used_gb / $ram_total_gb) * 100;
|
||||
}
|
||||
?>
|
||||
<h2>Admin Dashboard</h2>
|
||||
<p>Angemeldet als: <?php echo htmlspecialchars($_SESSION['admin_user']); ?></p>
|
||||
|
||||
<h3>Server-Status (SNMP)</h3>
|
||||
<p>CPU-Last (Kern 1): <?php echo $cpu_load ?: "Fehler bei Abfrage"; ?>%</p>
|
||||
<p>System Uptime: <?php echo $uptime; ?></p>
|
||||
<p>RAM-Auslastung:
|
||||
<?php echo isset($ram_percent) ? number_format($ram_percent, 2) . "%" : "Fehler bei Abfrage"; ?>
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
<p><a href="create_single_user.php">Einzelnen Benutzer erstellen</a></p>
|
||||
<p><a href="bulk_create_users.php">Benutzer per CSV importieren</a></p>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 6.3 Modul 3: Einzelne Benutzererstellung
|
||||
|
||||
**Datei:** `create_single_user.php`
|
||||
|
||||
```php
|
||||
<?php
|
||||
// create_single_user.php
|
||||
session_start();
|
||||
if (!isset($_SESSION['admin_user'])) {
|
||||
header("Location: login.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
$output = '';
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$ps_script = 'C:\\Web\\AdAdminPanel\\scripts\\powershell\\Create-ADUser.ps1';
|
||||
|
||||
if (empty($_POST['username']) || empty($_POST['password'])) {
|
||||
$output = "Fehler: Benutzername und Passwort sind erforderlich.";
|
||||
} else {
|
||||
// Kritisch: Maskierung aller Shell-Argumente (Schutz vor Command Injection)
|
||||
$username = escapeshellarg($_POST['username']);
|
||||
$password = escapeshellarg($_POST['password']);
|
||||
$givenname = escapeshellarg($_POST['givenname']);
|
||||
$surname = escapeshellarg($_POST['surname']);
|
||||
$oupath = escapeshellarg("OU=WebAppUsers,DC=yourdomain,DC=com");
|
||||
|
||||
$command = "powershell.exe -ExecutionPolicy ByPass -NoProfile -File $ps_script " .
|
||||
"-Username $username -Password $password -GivenName $givenname " .
|
||||
"-Surname $surname -OUPath $oupath";
|
||||
|
||||
// STDERR nach STDOUT umleiten (2>&1)
|
||||
$output = shell_exec($command . " 2>&1");
|
||||
}
|
||||
}
|
||||
?>
|
||||
<h2>Neuen AD-Benutzer erstellen</h2>
|
||||
<form method="post" action="create_single_user.php">
|
||||
Benutzername (SamAccountName): <input type="text" name="username"><br>
|
||||
Temporäres Passwort: <input type="text" name="password"><br>
|
||||
Vorname: <input type="text" name="givenname"><br>
|
||||
Nachname: <input type="text" name="surname"><br>
|
||||
<input type="submit" value="Benutzer erstellen">
|
||||
</form>
|
||||
|
||||
<?php if ($output): ?>
|
||||
<h3>Ausgabe:</h3>
|
||||
<pre><?php echo htmlspecialchars($output); ?></pre>
|
||||
<?php endif; ?>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 6.4 Modul 4: CSV-Massenimport
|
||||
|
||||
**Datei:** `bulk_create_users.php`
|
||||
|
||||
```php
|
||||
<?php
|
||||
// bulk_create_users.php
|
||||
session_start();
|
||||
if (!isset($_SESSION['admin_user'])) {
|
||||
header("Location: login.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
$output = '';
|
||||
|
||||
if (isset($_FILES['user_csv'])) {
|
||||
$upload_dir = 'C:\\Web\\AdAdminPanel\\storage\\uploads\\';
|
||||
$temp_csv_path = $upload_dir . uniqid('users_') . '.csv';
|
||||
|
||||
if (move_uploaded_file($_FILES['user_csv']['tmp_name'], $temp_csv_path)) {
|
||||
$ps_script = 'C:\\Web\\AdAdminPanel\\scripts\\powershell\\Bulk-Create-ADUsers.ps1';
|
||||
$csv_path_arg = escapeshellarg($temp_csv_path);
|
||||
$oupath_arg = escapeshellarg("OU=WebAppUsers,DC=yourdomain,DC=com");
|
||||
|
||||
$command = "powershell.exe -ExecutionPolicy ByPass -NoProfile -File $ps_script " .
|
||||
"-CsvPath $csv_path_arg -OUPath $oupath_arg";
|
||||
|
||||
$output = shell_exec($command . " 2>&1");
|
||||
|
||||
// Temporäre CSV mit Klartext-Passwörtern löschen
|
||||
unlink($temp_csv_path);
|
||||
} else {
|
||||
$output = "Fehler beim Hochladen der Datei.";
|
||||
}
|
||||
}
|
||||
?>
|
||||
<h2>AD-Benutzer per CSV-Massenimport erstellen</h2>
|
||||
<p>Die CSV-Datei muss die Spaltenüberschriften <code>SamAccountName</code>, <code>GivenName</code>, <code>Surname</code> und <code>Password</code> enthalten.</p>
|
||||
|
||||
<form method="post" action="bulk_create_users.php" enctype="multipart/form-data">
|
||||
CSV-Datei auswählen: <input type="file" name="user_csv" accept=".csv"><br>
|
||||
<input type="submit" value="Import starten">
|
||||
</form>
|
||||
|
||||
<?php if ($output): ?>
|
||||
<h3>Import-Ergebnis:</h3>
|
||||
<pre><?php echo htmlspecialchars($output); ?></pre>
|
||||
<?php endif; ?>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Teil 7: Abschließendes Sicherheits-Audit und Risikobewertung
|
||||
|
||||
Die Lösung ist mächtig, aber sensibel, da sie eine Brücke zwischen Web und Active Directory bildet. Die folgenden Risiken und Gegenmaßnahmen sind zentral:
|
||||
|
||||
### Risiko: Command Injection
|
||||
|
||||
**Beschreibung:**
|
||||
Ein Angreifer könnte versuchen, über Formulare Befehle einzuschleusen, z.B.:
|
||||
`username; Remove-ADUser -Identity 'Administrator'`
|
||||
|
||||
**Gegenmaßnahme:**
|
||||
|
||||
- Konsequente Verwendung von **`escapeshellarg()`** für alle Parameter, die an `powershell.exe` übergeben werden.
|
||||
- Dadurch werden Eingaben als einzelne, harmlose Zeichenkette behandelt und nicht als eigenständiger Befehl interpretiert.
|
||||
|
||||
---
|
||||
|
||||
### Risiko: Eskalation von Berechtigungen
|
||||
|
||||
**Beschreibung:**
|
||||
Eine Schwachstelle in der PHP-Anwendung könnte genutzt werden, um die Rechte des Webserverkontos zu missbrauchen.
|
||||
|
||||
**Gegenmaßnahme:**
|
||||
|
||||
- AppPool läuft als **`svc_iis_php_ad`** mit minimal notwendigen Rechten.
|
||||
- AD-Delegierung beschränkt das Konto auf das Erstellen/Ändern von Benutzern in der OU `WebAppUsers`.
|
||||
- Keine Mitgliedschaft in administrativen Gruppen, kein Zugriff auf andere OUs oder Systeme.
|
||||
|
||||
---
|
||||
|
||||
### Risiko: Klartext-Passwörter
|
||||
|
||||
**Beschreibung:**
|
||||
|
||||
- Passwörter liegen im Klartext in Formularen und CSV-Dateien vor.
|
||||
- Übergabe an PowerShell erfolgt im Klartext.
|
||||
- Temporäre CSV-Dateien enthalten Klartext-Passwörter auf der Festplatte.
|
||||
|
||||
**Gegenmaßnahmen:**
|
||||
|
||||
- **HTTPS erzwingen:** Die gesamte Weboberfläche muss über TLS gesichert werden.
|
||||
- **Schnelle Konvertierung**: PowerShell wandelt Klartext-Passwörter sofort in `SecureString` um.
|
||||
- **Löschung der CSV-Dateien:** Temporäre CSV-Dateien werden nach der Verarbeitung gelöscht (`unlink()`).
|
||||
- **Passwortwechsel erzwingen:** `ChangePasswordAtLogon = $true` zwingt Benutzer zur Passwortänderung bei der ersten Anmeldung.
|
||||
|
||||
---
|
||||
|
||||
### Risiko: Fehlende Fehlerbehandlung
|
||||
|
||||
**Beschreibung:**
|
||||
|
||||
- PowerShell-Fehler (z.B. Kennwort-Komplexität) landen auf STDERR, das von `shell_exec()` standardmäßig ignoriert wird.
|
||||
|
||||
**Gegenmaßnahme:**
|
||||
|
||||
- Anhängen von `2>&1` an alle Befehle im `shell_exec()`-Kontext, damit Fehlermeldungen im `$output`-String landen und im Webinterface angezeigt werden können.
|
||||
|
||||
---
|
||||
|
||||
**Ende des Dokuments**
|
||||
Loading…
Reference in New Issue
Block a user