- 1 Abschnitt
- 11 Lektionen
- Um den Kurs in deinem Profil zu hinterlegen klicke oben auf Starten
- Software & Security12
- 1.1Einführung in die Software-Sicherheit
- 1.2Sicherheitsarchitekturen und -modelle
- 1.3Sichere Softwareentwicklung (Secure Software Development Lifecycle – SSDLC)
- 1.4Bedrohungsanalyse und Risikomanagement
- 1.5Sichere Programmierung
- 1.6Authentifizierung und Autorisierung
- 1.7Kryptographie
- 1.8Sicherheitsprüfungen und -tests
- 1.9Datenschutz und Compliance
- 1.10Software & Security9 Fragen
- 1.11Aufgaben
- 1.12Lösungen
Sichere Programmierung
Sichere Programmierung ist ein wesentlicher Bestandteil der Softwareentwicklung, um Sicherheitslücken zu vermeiden und robuste Anwendungen zu erstellen. Dieser Abschnitt bietet einen umfassenden Überblick über Techniken und Best Practices zur sicheren Programmierung.
1. Input-Validierung
Beschreibung: Die Validierung von Benutzereingaben ist entscheidend, um sicherzustellen, dass nur erwartete und sichere Daten in die Anwendung gelangen.
Techniken:
- Whitelisting: Erlaubt nur spezifizierte Eingaben.
- Blacklisting: Blockiert bekannte unsichere Eingaben.
- Reguläre Ausdrücke: Verwenden von Mustern zur Überprüfung der Eingaben.
Beispiel:
import re
def validate_username(username):
# Erstelle ein reguläres Ausdrucksmuster für gültige Benutzernamen
pattern = re.compile("^[a-zA-Z0-9_]{3,20}$")
# Überprüfe, ob der Benutzername dem Muster entspricht
return pattern.match(username) is not None
# Test
print(validate_username("valid_user123")) # True
print(validate_username("invalid user!")) # False
Veranschaulichung:
+--------------+-------------------+----------------+
| Eingabe | Whitelisting | Blacklisting |
+--------------+-------------------+----------------+
| abc | Erlaubt | Erlaubt |
| <script> | Blockiert | Blockiert |
| 123 | Erlaubt | Erlaubt |
| username! | Blockiert | Blockiert |
+--------------+-------------------+----------------+
2. Fehlerbehandlung
Beschreibung: Fehler sollten sicher und informativ behandelt werden, ohne sicherheitsrelevante Informationen preiszugeben.
Best Practices:
- Generische Fehlermeldungen: Keine Details über die internen Systeme.
- Protokollierung: Detaillierte Fehlerprotokolle für Entwickler und Administratoren.
- Fehlerseiten: Benutzerfreundliche und sichere Fehlerseiten.
Beispiel:
def process_request(data):
try:
# Verarbeitung der Daten (Platzhalter für tatsächliche Logik)
pass
except ValueError as e:
# Protokolliere den Fehler und gib eine generische Fehlermeldung zurück
log_error(e)
return "Ein Fehler ist aufgetreten. Bitte versuchen Sie es später erneut."
except Exception as e:
# Protokolliere unerwartete Fehler und gib eine generische Fehlermeldung zurück
log_error(e)
return "Ein unerwarteter Fehler ist aufgetreten."
def log_error(error):
# Schreibe den Fehler in eine Fehlerprotokolldatei
with open('error_log.txt', 'a') as log_file:
log_file.write(f"{error}\n")
Veranschaulichung:
+---------------------+---------------------------+
| Fehlerfall | Benutzerfehlermeldung |
+---------------------+---------------------------+
| Datenvalidierungsfehler | "Ein Fehler ist aufgetreten." |
| Unbekannter Fehler | "Ein unerwarteter Fehler ist aufgetreten." |
+---------------------+---------------------------+
3. Speichersicherheit
Beschreibung: Vermeidung von Speicherproblemen wie Pufferüberläufen und Speicherlecks, die Sicherheitslücken verursachen können.
Techniken:
- Pufferüberlauf-Vermeidung: Verwendung sicherer Funktionen zur Speicherverwaltung.
- Speicherlecks-Vermeidung: Regelmäßige Überprüfung und Freigabe von nicht mehr benötigtem Speicher.
Beispiel (C):
#include <string.h>
// Funktion zur sicheren Kopie eines Strings in einen Puffer
void safe_copy(char *dest, const char *src, size_t size) {
// Überprüfe, ob die Quelle kleiner ist als die Größe des Ziels
if (strlen(src) < size) {
// Kopiere den gesamten String
strcpy(dest, src);
} else {
// Kopiere nur so viel wie passt und füge ein Nullbyte hinzu
strncpy(dest, src, size - 1);
dest[size - 1] = '\0';
}
}
int main() {
char buffer[10];
// Kopiere einen sicheren Text in den Puffer
safe_copy(buffer, "sicherer text", sizeof(buffer));
return 0;
}
Veranschaulichung:
+---------------+--------------------------------+
| Problem | Lösung |
+---------------+--------------------------------+
| Pufferüberlauf| Verwendung sicherer Funktionen |
| Speicherlecks | Regelmäßige Speicherfreigabe |
+---------------+--------------------------------+
4. Authentifizierung und Autorisierung
Beschreibung: Sichere Methoden zur Verifizierung der Identität von Benutzern und zur Steuerung ihrer Zugriffsrechte.
Techniken:
- Multi-Faktor-Authentifizierung (MFA): Kombination mehrerer Authentifizierungsmethoden.
- Role-Based Access Control (RBAC): Zugriffskontrolle basierend auf Benutzerrollen.
Beispiel (Pseudo-Code):
# Funktion zur Authentifizierung eines Benutzers
authenticate_user(username, password, token):
# Überprüfe Benutzername und Passwort sowie den MFA-Token
if verify_password(username, password) and verify_token(token):
return True
return False
# Funktion zur Autorisierung eines Benutzers für eine Aktion
authorize_user(user, action):
# Hole die Rollen des Benutzers
roles = get_user_roles(user)
# Hole die Berechtigungen für die Aktion
permissions = get_permissions_for_action(action)
# Überprüfe, ob die Rollen des Benutzers die notwendigen Berechtigungen enthalten
if roles intersect permissions:
return True
return False
Veranschaulichung:
+-----------------------+-------------------------+
| Authentifizierung | Autorisierung |
+-----------------------+-------------------------+
| Benutzername & Passwort| Benutzerrollen & Rechte |
| MFA (Token) | RBAC (Rollenbasiert) |
+-----------------------+-------------------------+
