LUA: Proxy für Admin-Token
In einer Software von mir verwende ich ein und dieselbe Anwendung für Verschiedene Aufgaben. Die Anwendung ist (je nach Kommandozeilen-Option) Client, Server, Sprach-Resource, Log-Browser und startet/stoppt auch den Server.
Besitzt der angemeldete Benutzer ein Recht nicht, fordert die Anwendung zur Eingabe berechtigter Benutzerdaten auf und startet sich evtl. auch selbst mit diesen Daten neu.
Zum starten und stoppen der Serverkomponente muss man immer Administrator sein. Ist man das nicht, fordert das Programm zum Eingeben von Benutzernamen und Passwort ein und startet sich mit diesen Informationen mit CreateProcessWithLogonW neu.
Unter Windows Vista mit aktiviertem LUA (Least-Privilege User Account) gibt es damit jedoch Probleme, weil CreateProcessWithLogonW meine Anwendung immer mit eingeschränkten Rechten startet und weil man für CreateProcessAsUser einen User-Token braucht, den nur ein laufender Service mit LogonUser erzeugen kann kann! 😕
Kurzer Ausflug in LUA (Least-Privilege User Account):
Wenn sich an ein Windows NT (2000, XP, 2003, Vista etc.) ein Benutzer anmeldet, wird ein User-Token generiert. Dieser wird allen Prozessen zugeordnet, die der Benutzer startet. Der Token ist vergleichbar mit einem Schlüssel. Wenn man auf eine gesicherte Resource zugreift (z.B. auf eine Datei), prüft das Betriebssystem den dem Prozess eigenen User-Token auf dessen Berechtigung und etscheidet über Erlaubnis oder Verweigerung des Zugriffs.
Unter Vista gibt es ein neues Sicherheitsmodell: LUA (Least-Privilege User Account). Jeder Administrator besitzt einen sogenannten Split-Token. Ein Split-Token besteht aus zwei User-Token, einem administrativen und einem eingeschränkten. Meldet sich ein User mit Split Token am System an, bekommen Programme die man startet automatisch den eingeschränkten User Token. Ein Programm kann sich nur auf zwei Weisen Administrator-Rechte verschaffen:
- Ist ein Programm mit einem Manifest speziell als administrativ markiert, fragt Vista in einem separaten Desktop nach, ob der Benutzer zustimmt, dass es mit dem administrativen Token gestartet wird.
- Stellt ein Programm ein speziell markiertes COM-Interface bereit, kann dieses COM-Interface (nach „Abnicken das man will“) administrative Aufgaben erfüllen.
Beide Methoden waren für mich ungeeignet, (1.) da mein Programm als Client auch mit eigeschränkten Rechten laufen muss und (2.) weil der Progamm-Umfang mit 130.000 Zeilen Quelltext nicht wesentlich komplexer werden soll.
Also entschied ich mich dafür, eine Proxy-Anwendung zu schreiben.
Die Proxy-Anwendung ist mit einem Manifest als administratives Programm markiert. Sie nimmt ihre eigenen Komandozeilenparameter als Befehl für CreateProcess.
Wenn der Proxy mit ShellExecute gestartet wird, bekommt er nach „Abnicken das man will“ den administrativen Token und alle von ihm gestarteten Prozesse auch.
Hier noch mal in Punkten, was passiert:
- Programm erfordert Admin-Rechte, hat die aber nicht
-> CreateProcessWithLogonW ( GetCommandLine() ) - Programm hat eingeschränkten Split-Token (GetTokenInformation mit TOKEN_ELEVATION_TYPE lifert das)
-> CreateProcess ( Proxy + GetCommandLine() ) - Proxy wird mit administrativen Rechten gestartet
-> CreateProcess ( PathGetArgs( GetCommandLine() ) ) - Programm läuft jetzt mit Admin-Rechten
Der Proxy ist UPX-Komrimiert gerade mal 3K groß und wird von mir aus einer Resource im Programm dynamisch auf Platte gespeichert und automatisch wieder gelöscht.