Sicherheitsüberlegungen: Windows-Benutzeroberfläche
Dieser Artikel enthält Informationen zu Sicherheitsüberlegungen im Zusammenhang mit der Windows-Benutzeroberfläche. Er umfasst nicht alle Informationen, die Sie in Bezug auf Sicherheitsprobleme kennen sollten. Betrachten Sie den Artikel stattdessen als Ausgangspunkt und Referenz für diesen Technologiebereich.
Durch die zunehmende Vernetzbarkeit von Computern müssen sich Entwickler*innen jetzt mit der Anwendungssicherheit befassen. Die Sicherheit verbessert jedoch auch die allgemeine Anwendungssicherheit und Stabilität. Daher stellt dies eine andere Möglichkeit für Entwickler*innen dar, eine optimale Nutzung zu ermöglichen. In den folgenden Abschnitten werden einige potenzielle Sicherheitsbedenken bei Verwendung der Windows-Benutzeroberfläche erläutert.
Überlegungen zu Zeichenfolgen
Viele Funktionen, Meldungen und Makros verwenden Zeichenfolgen in ihren Parametern. Häufig wird jedoch nicht die Länge von Zeichenfolgen überprüft bzw. ermittelt, ob diese mit NULL abgeschlossen werden. Ein verwandtes Problem besteht darin, die Länge einer Zeichenfolge oder eines Puffers falsch zu berechnen. In beiden Fällen kann dies zu einem Pufferüberlauf oder dem Abschneiden von Daten führen, was sich negativ auf Ihre Anwendung auswirken kann. Weitere Informationen zu Pufferüberläufen und anderen Sicherheitsbedenken finden Sie in Writing Secure Code von Michael Howard und David Leblanc, Microsoft Press, 2002.
Gehen Sie wie folgt vor, um Zeichenfolgen auf sichere Weise zu behandeln:
- Überprüfen Sie die Zeichenfolgen entsprechend auf ihre Länge, und ermitteln Sie, ob sie mit NULL abgeschlossen werden.
- Achten Sie besonders darauf, die Länge einer Zeichenfolge oder eines Puffers zu bestimmen (insbesondere wenn TCHAR-Werte enthalten sind).
- Wenn Sie eine Zeichenfolge erstellen oder eine zuvor verwendete Zeichenfolge nutzen, initialisieren Sie sie nach Bedarf auf 0, oder fügen Sie entsprechend ein NULL-Abschlusszeichen ein.
Darüber hinaus sollten Sie bei Zeichenfolgen die StrSafe-Funktionen verwenden. Diese Funktionen sind so konzipiert, dass Zeichenfolgen sicher verarbeitet werden.
Benutzereingaben
Die Windows-Benutzeroberfläche ist zuständig für das Abrufen von und Reagieren auf Informationen von Benutzer*innen. Benutzer*innen, die falsche Daten eingeben, können Ihre Anwendung jedoch stören, unabhängig davon, ob sie dies beabsichtigen. Daher besagt eine Grundregel, dass alle Eingaben überprüft werden müssen.
Den wichtigsten Aspekt stellen Zeichenfolgendaten dar, die unter Überlegungen zu Zeichenfolgen erläutert werden. Alle Eingabetypen sollten jedoch überprüft werden, bevor sie von Ihrer Anwendung verwendet werden. Ein weiteres Problem besteht darin, dass Daten an einem Punkt überprüft werden, vor der Verwendung aber geändert werden (z. B. beim Empfangen von Meldungen, die die Textlänge angeben). Wenn also die Möglichkeit besteht, dass Daten geändert werden, sollten Sie diese vor der Verwendung überprüfen.
Sicherheitswarnungen
In der folgenden Tabelle sind Features aufgeführt, die bei falscher Verwendung die Sicherheit Ihrer Anwendungen gefährden können.
Funktion | Abmilderung |
---|---|
GetAtomName | Seien Sie beim Angeben der Größe des Puffers vorsichtig. |
GlobalGetAtomName | Globale Zeichenfolgenatome sind für jede Anwendung zugänglich. Eine andere Anwendung könnte die Referenzanzahl jedoch falsch interpretieren und löschen. Sie sollten stattdessen die Verwendung globaler ganzzahliger Atome in Betracht ziehen. |
ImpersonateDdeClientWindow | Wenn die Funktion fehlschlägt, werden nachfolgende Clientanforderungen im Sicherheitskontext des Aufrufvorgangs gestellt. Dies kann ein Problem sein, wenn der Aufrufvorgang mit einem hoch privilegierten Konto ausgeführt wird. Wenn der Aufruf fehlschlägt oder einen Fehler auslöst, sollten Sie die Ausführung der Clientanforderung daher nicht fortsetzen. |
DdeImpersonateClient | Wenn die Funktion fehlschlägt, werden nachfolgende Clientanforderungen im Sicherheitskontext des Aufrufvorgangs gestellt. Dies kann ein Problem sein, wenn der Aufrufvorgang mit einem hoch privilegierten Konto ausgeführt wird. Wenn der Aufruf fehlschlägt oder einen Fehler auslöst, sollten Sie die Ausführung der Clientanforderung daher nicht fortsetzen. |
GetClipboardFormatName | Eine Fehlberechnung der richtigen Größe des lpszFormatName-Puffers (insbesondere bei Verwendung der Anwendung in ANSI- und Unicode-Versionen) kann zu einem Pufferüberlauf führen. Beachten Sie außerdem, dass die Zeichenfolge abgeschnitten wird, wenn sie länger als der cchMaxCount-Parameter ist, was zu einem Informationsverlust führen kann. |
GetMenuString | Der lpString-Parameter ist ein TCHAR-Puffer, und nMaxCount ist die maximale Länge der Menüzeichenfolge in TCHARs. Eine falsche Größenanpassung kann dazu führen, dass die Zeichenfolge abgeschnitten wird, was wiederum Datenverluste zur Folge haben kann. Eine falsche Größenanpassung dieser Parameter kann dazu führen, dass die Zeichenfolge abgeschnitten wird, was zu Datenverlusten führen kann. |
GetStringTypeA, GetStringTypeEx, GetStringTypeW | Um einen Pufferüberlauf zu vermeiden, legen Sie die Größe des lpCharType-Puffers richtig fest. |
LoadLibrary | Die falsche Verwendung von LoadLibrary kann die Sicherheit Ihrer Anwendung gefährden, indem die falsche DLL geladen wird. |
LoadString | Das Angeben einer falschen Größe im nBufferMax-Parameter stellt eine falsche Verwendung dar. Beispielsweise gibt „sizeof(lpBuffer)“ die Größe des Puffers in Bytes an, was zu einem Pufferüberlauf bei der Unicode-Version der Funktion führen kann. Pufferüberlaufsituationen sind die Ursache vieler Sicherheitsprobleme in Anwendungen. In diesem Fall wird bei Verwendung von sizeof(lpBuffer)/sizeof(TCHAR) die richtige Größe des Puffers angegeben. |
lstrcat | Diese Funktion verwendet die strukturierte Ausnahmebehandlung (Structured Exception Handling, SEH), um Zugriffsverletzungen und andere Fehler abzufangen. Wenn diese Funktion SEH-Fehler erfasst, gibt sie NULL zurück, wobei die Zeichenfolge nicht mit NULL abgeschlossen und der Aufrufer nicht über den Fehler benachrichtigt wird. Der Aufrufer kann nicht davon ausgehen, dass nicht genügend Speicherplatz die Ursache für den Fehler ist. Das erste Argument (lpString1) muss lang genug sein, um lpString2 und das abschließende Element „\0“ zu enthalten. Andernfalls kann ein Pufferüberlauf auftreten. Pufferüberläufe können zu einem Denial-of-Service-Angriff auf die Anwendung führen, wenn eine Zugriffsverletzung auftritt. Im schlimmsten Fall wird es Angreifern durch einen Pufferüberlauf ermöglicht, ausführbaren Code in Ihren Prozess einzufügen (insbesondere dann, wenn lpString1 ein stapelbasierter Puffer ist). Erwägen Sie die Verwendung einer der folgenden Alternativen: StringCbCat oder StringCchCat. |
lstrcpy | Diese Funktion verwendet die strukturierte Ausnahmebehandlung (Structured Exception Handling, SEH), um Zugriffsverletzungen und andere Fehler abzufangen. Wenn diese Funktion SEH-Fehler erfasst, gibt sie NULL zurück, wobei die Zeichenfolge nicht mit NULL abgeschlossen und der Aufrufer nicht über den Fehler benachrichtigt wird. Der Aufrufer kann nicht davon ausgehen, dass nicht genügend Speicherplatz die Ursache für den Fehler ist. Das erste Argument (lpString1) muss lang genug sein, um lpString2 und das abschließende Element „\0“ zu enthalten. Andernfalls kann ein Pufferüberlauf auftreten. Pufferüberläufe können zu einem Denial-of-Service-Angriff auf die Anwendung führen, wenn eine Zugriffsverletzung auftritt. Im schlimmsten Fall wird es Angreifern durch einen Pufferüberlauf ermöglicht, ausführbaren Code in Ihren Prozess einzufügen (insbesondere dann, wenn lpString1 ein stapelbasierter Puffer ist). Erwägen Sie stattdessen die Verwendung von StringCchCopy. |
lstrcpyn | Diese Funktion verwendet die strukturierte Ausnahmebehandlung (Structured Exception Handling, SEH), um Zugriffsverletzungen und andere Fehler abzufangen. Wenn diese Funktion SEH-Fehler erfasst, gibt sie NULL zurück, wobei die Zeichenfolge nicht mit NULL abgeschlossen und der Aufrufer nicht über den Fehler benachrichtigt wird. Der Aufrufer kann nicht davon ausgehen, dass nicht genügend Speicherplatz die Ursache für den Fehler ist. Wenn lpString1 nicht groß genug ist, um die kopierte Zeichenfolge zu enthalten, besteht die Gefahr eines Pufferüberlaufs. Beachten Sie außerdem beim Kopieren einer gesamten Zeichenfolge, dass sizeof die Anzahl der Bytes anstelle von Zeichen (WCHAR) zurückgibt, was für die Unicode-Version dieser Funktion falsch ist. Pufferüberläufe können zu einem Denial-of-Service-Angriff auf die Anwendung führen, wenn eine Zugriffsverletzung auftritt. Im schlimmsten Fall wird es Angreifern durch einen Pufferüberlauf ermöglicht, ausführbaren Code in Ihren Prozess einzufügen (insbesondere dann, wenn lpString1 ein stapelbasierter Puffer ist). Erwägen Sie stattdessen die Verwendung von StringCchCopy. |
lstrlen | lstrlen geht davon aus, dass es sich bei lpString um eine Zeichenfolge handelt, die mit NULL abgeschlossen wird. Wenn dies nicht der Fall ist, kann dies zu einem Pufferüberlauf oder einem Denial-of-Service-Angriff auf Ihre Anwendung führen. Erwägen Sie die Verwendung einer der folgenden Alternativen: StringCbLength oder StringCchLength. |
wsprintf | Es ist nicht garantiert, dass die in lpOut zurückgegebene Zeichenfolge mit NULL abgeschlossen wird. Vermeiden Sie außerdem das %s-Format, da es zu einem Pufferüberlauf führen kann. Wenn eine Zugriffsverletzung auftritt, führt dies zu einem Denial-of-Service-Angriff auf Ihre Anwendung. Im schlimmsten Fall können Angreifer ausführbaren Code einfügen. Erwägen Sie die Verwendung einer der folgenden Alternativen: StringCbPrintf, StringCbPrintfEx, StringCbVPrintf, StringCbVPrintfEx, StringCchPrintf, StringCchPrintfEx, StringCchVPrintf oder StringCchVPrintfEx. |
wvsprintf | Es ist nicht garantiert, dass die in lpOutput zurückgegebene Zeichenfolge mit NULL abgeschlossen wird. Vermeiden Sie außerdem die Verwendung des %s-Formats, da es zu einem Pufferüberlauf führen kann. Dies kann zu einem Denial-of-Service-Angriff führen, wenn eine Zugriffsverletzung vorliegt. Zudem ist es möglich, dass Angreifer ausführbaren Code einfügen. Erwägen Sie die Verwendung einer der folgenden Alternativen: StringCbPrintf, StringCbPrintfEx, StringCbVPrintf, StringCbVPrintfEx, StringCchPrintf, StringCchPrintfEx, StringCchVPrintf oder StringCchVPrintfEx. |
Zugehörige Themen