PowerShell, UAC und Exchange
Für einige Aktionen benötigen Skripte lokale Admin-Berechtigungen, die aber dank User Account Control (UAC) nicht immer vorhanden sind. UAC ist wichtig, um Systeme zu schützen aber stört wieder Prozesse, die erhöhte Rechte brauchen.
Auslöser: Exchange Management Shell auf DC
Wie wissen sicher seit dem Artikel Recipient Management PowerShell und Exchange Management Rolle, dass Sie mit einer lokalen Exchange PowerShell ganz ohne Exchange Server und RBAC die Exchange Eigenschaften im lokalen Active Directory verwalten können. Über diesen Weg konnten Firmen seit April 2022 die Exchange Online Eigenschaften über das lokale AD ohne lokalen Exchange Server verwalten. Sie installieren die Exchange Management Shell und laden einfach das Recipient Management Shell Snapin mit:
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.RecipientManagement
Bei einem Projekt mit einem Provisioning-Service ist aber aufgefallen, das ich als Administrator problemlos ein "Enable-RemoteMailbox" ausführen konnte aber das Dienstkonto dabei einen Fehler generiert hat.

Ich tippe mal darauf, dass die Exchange Powershell beim Weglassen der "PrimarySmtpAddress" versucht hat, selbst eine gültige Adresse zu ermitteln und dazu die "inproxy.dll" dynamisch nachladen will und das als "nicht lokaler Admin" nicht möglich ist. Diese DLL nutzt Exchange OnPremises, um anhand der Empfängerrichtlinien eine primäre SMTP-Adresse zu vergeben.
Es hilft übrigens nicht, das Feld "mail" mit einer primären Adresse zu versehen. Siehe dazu auch Provisioning mit IsExchangeCloudManaged und ADSync mit Exchange Online Only
Den Fehler haben wir schon früher mit Exchange 2010 gehabt, wo diese DLL wohl mal verloren gegangen ist. Aber in meinem Beispiel gab es gar keinen Server, sondern nur die Exchange Management Rolle
- ADSync mit Exchange Online Only
- Exchange Management Rolle
- Provisioning mit IsExchangeCloudManaged
- Exchange Server 2013 teilt die inproxy.dll-Datei
https://support.microsoft.com/de-de/topic/exchange-server-2013-teilt-die-inproxy-dll-datei-f6c38b09-693b-82f4-0d48-06e696d1045a - Unable to generate the e-mail address (Exchange Server)
https://www.alitajran.com/unable-to-generate-the-e-mail-address/ - Exchange 2010 Probleme beim Anlegen neuer Postfächer
https://www.nobbysweb.de/index.php?thread/16038-exchange-2010-probleme-beim-anlegen-neuer-postf%C3%A4cher/
Je nach Umgebung bekommen Sie vielleicht och andere Fehler, wie:
#Englische Fehlermeldung Enable-RemoteMailbox: No provisioning handler is installed. #Deutsche Fehlermeldung Enable-RemoteMailbox: kein bereitstellungshandler installiert
Sobald ich aber die PowerShell als "Administrator" gestartet habe, waren die Fehler weg.

Die Befehle "Set-RemoteMailbox" und haben ohne Fehler funktioniert.
Damit war meine Neugier geweckt, wie ich denn z.B. aus einem Provisioning-Skript gezielt eine AdminPowerShell starten kann und wann Windows überhaupt die Unterscheidung macht.
UAC und Admin PowerShell
Ich habe erst mal eine Testserie gemacht, bei der verschiedene Benutzer sich auf einem Windows Server 2016 lokal angemeldet und eine PowerShell gestartet haben. UAC war wie folgt eingestellt.

Wenn ich etwas tue, wozu administrative Berechtigungen erforderlich sind, dann kommt eine Rückfrage. zumindest habe ich das gedacht.
User |
Lokale Rechte |
Shell als Admin |
|---|---|---|
Dom/Administrator (SID endet auf 500) |
Administratoren |
Ja ohne Rückfrage! |
./Administrator (SID endet auf 500) |
Administratoren |
Ja ohne Rückfrage! |
Dom/Admin (SID endet nicht auf 500) |
Administratoren |
"Als Admin Starten" und Rückfrage |
./Admin (SID endet nicht auf 500) |
Administratoren |
"Als Admin Starten" und Rückfrage |
./User (SID |
Benutzer |
"Als Admin Starten" + Credentials |
Domain/User |
Benutzer über DomainUser |
"Als Admin Starten" + Credentials |
Das Verhalten war mir vorher gar nicht so aufgefallen. Vermutlich liegt es allein daran, dass ich die "BuildIn"-Administratoren, sei es lokal oder in der Domain eigentlich nie nutze.
Als Buildin-Admin habe ich auf die Schnelle auch keinen Weg gefunden, eine PowerShell oder CMD-Shell ohne Adminrechte zu starten. Das geht wohl nicht.
Ich interpretiere die Ergebnisse derart, dass die "Default Administratoren" mit der SID selbst bei aktiviertem UAC keine Rückfrage bekommen, sondern immer direkt eine PowerShell oder CMD-Shell als Administrator starten. Hier wirkt UAC also gar nicht. Nur Konten, die auch in der direkt oder über eine Domaingruppe in der lokalen Gruppe der Administratoren Mitglied sind und sich damit Admin-Rechte geben könnten, werden durch UAC entsprechend kurz darauf aufmerksam gemacht, dass ein Prozess hier privilegierte Berechtigungen anfordert. Benutzer, die keine Admin-Rechte haben, können natürlich auch ein "als Administrator starten" versuchen aber werden dann nach Anmeldedaten gefragt.
Ist ihnen das auch schon aufgefallen, dass UAC im Standard für Buildin-Administratoren nicht wirkt?
Das Exchange Problem war damit gelöst aber ich habe noch ein paar Informationen zu UAC gesammelt.
- User Account Control: Admin Approval Mode for the Built-in Administrator
account
https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-10/security/threat-protection/security-policy-settings/user-account-control-admin-approval-mode-for-the-built-in-administrator-account
UAC Status ermitteln
Ob auf einem Windows Computer der Schutz per UAC aktiv ist, kann ich per PowerShell einfach durch Lesen des entsprechenden Registrierungsschlüssels ermitteln.
(Get-ItemProperty "HKLM:\Software\Microsoft\Windows\CurrentVersion\Policies\System") ` | fl ConsentPromptBehaviorAdmin,ConsentPromptBehaviorUser,PromptOnSecureDesktop,EnableLUA

Die Werte je nach Einstellung:
Einstellung |
ConsentPromptBehaviorAdmin |
ConsentPromptBehaviorUser |
PromptOnSecureDesktop |
EnableLUA |
|---|---|---|---|---|
Immer benachrichtigen (App Installation und Windows Setting) |
2 |
3 |
1 |
1 |
Benachrichten bei App Installation (Default) |
5 |
3 |
1 |
1 |
Benachrichten bei App Installation (Desktop nicht ausblenden |
5 |
3 |
0 |
1 |
Nicht benachrichtigen |
0 |
3 |
0 |
1 |
Die Benachrichtigung kommt natürlich immer nur beim Start des Prozesses aber nie während der Prozess schon läuft. Das Betriebssystem überwacht also nicht alle Aktionen des Programms während der Laufzeit sondern nur, wenn ein neuer Prozess gestartet wird.
Habe ich Admin Rechte?
Ein laufendes PowerShell-Script kann sehr einfach prüfen, ob es mir administrativen Berechtigungen gestartet wurde. Wir holen uns in der PowerShell direkt den aktuellen Benutzer und prüfen die Rolle:
$ich = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent()) $ich.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
Ein einfaches "True" zeigt an, dass dieses Skript zumindest lokaler Administrator ist.
Eine Abfrage mit "RunAs /ShowTrustLevels" hat bei mir immer nur Folgendes geliefert. Das galt selbst für den "Default Domain Administrator" auf dem Domain Controller in einer AdminPowershell

Ich könnte ja ein Programm mit "RunAs" und dem Parameter "/trustlevel" privilegiert starten. Aber wenn ich einen Benutzer mit angebe, möchte er acuh immer ein Kennwort.
UAC für Skripte anfordern
Ich möchte UAC als wichtige Schutzfunktion auf Servern ungern abschalten aber ich möchte genauso wenig meine Skripte und Code als "Buildin DomainAdmin" oder "Buildin LocalAdmin" starten. Ein eigenes Dienstkonto ist OnPremises immer noch eine gute Idee und das Konto kann ja gerne in der lokalen Gruppe der Administratoren sein, wenn der Prozess auf dem Server dies benötigt. Aber dann muss ich mir überlegen, wie ich den Prozess oder das Skript direkt mit Admin-Berechtigungen starten kann. Mit der Maus ein "Run as Admin" kann ein anderer Code ja nicht anklicken. Aber es gibt Optionen.
- LNK-Datei
Ich muss garnicht direkt die EXE oder das Script starten. Ich kann genauso eine LNK-Datei anlegen, welche auf den Code verweist und dort "Ausführen als Admin" angeben.

Allerdings umgehen wir damit nicht das UAC-Prompt - Geplanter Task
Wenn Sie ihr Skript im Taskplaner anlegen, dann können Sie schon beim Anlegen des Tasks ein "Run with highest privileges" auswählen

Das Skript oder Programm startet dann dann tatsächlich mit vollen Admin-Rechten ohne UAC-Rückfrage - Windows Service
Bei der dritten Variante nutzen sie einen Windows Service mit einem Dienstkonto. Hier können Sie zwar keine Checkbox für "Run as Admin" setzen, aber die benötigen Sie auch nicht. Beim Start als Dienst kommt nach meinen Versuchen keine UAC-Abfrage aber das Skript oder Programm hat auch Admin-Rechte.
Wenn ein Programm schon mal Adminrechte hat, kann es auch weitere Prozesse starten, die ebenfalls die Berechtigungen ohne weitere UAC-Abfrage vererbt bekommen.
Seit PowerShell 4 kann ich mit einer Direktive vorgeben, dass ich Administrator sein muss. Hier ein kleines Beispielskript:
#Requires -RunAsAdministrator Write-Host "testadmin"
Der erste Aufruf erfolgt noch ohne "Requires" und läuft durch. Für den zweiten Aufruf habe ich das Skript entsprechend ergänz und wenn ich kein Admin bin, dann bricht das Skript sofort ab:

Das ist keine Lösung um UAC zu umgehen, sondern nur ein Weg, wie Sie dem aufrufenden Benutzer einfach darauf hinweisen, dass er das Skript als Admin starten muss.
- PowerShell is fun :)Using the #Requires
statement in PowerShell
https://powershellisfun.com/2023/04/24/using-the-requires-statement-in-powershell/
Skript als Admin mit "RunAs" starten
Aber es gibt doch einen Weg, wie Sie aus einem PowerShell-Skript sich die Admin-Rechte beschaffen können. Wenn ich im Grund schon Administrator bin, aber UAC die Admin-Rechte nicht in meinem Session-Token hinterlegt habe, dann kann ich in der PowerShell einfach eine neue Shell starten
Start-Process PowerShell -Verb RunAs
Das dahinterliegende Fenster hat das vordere Fenster gestartet.

Sie können natürlich auch aus einer CMD-Shell direkt eine PowerShell als Admin starten.
Powershell.exe -command "Start-Process PowerShell" -Verb "RunAs"

In allen Fällen kommt aber der UAC-Dialog hoch. Es ist so nicht möglich, mal heimlich einen Prozess mit privilegierten Rechten zu starten. Aber sie können einen Administrator natürlich das Leben etwas einfacher machen, indem ihr Skript prüft, ob es schon die erforderlichen Rechte hat und dann sich selbst einfach noch einmal neu startet. Hier ein Auszug
$identity = [System.Security.Principal.WindowsIdentity]::GetCurrent()
$principal = New-Object System.Security.Principal.WindowsPrincipal($identity)
if (! $principal.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)) {
# Skript als Admin neu starten
$scriptfile = Resolve-Path $Script:MyInvocation.MyCommand.Path
$arguments = @("-NoProfile", "-NoLogo", "-ExecutionPolicy", "RemoteSigned",
"-File", "$scriptfile")
Start-Process pwsh -ArgumentList $arguments -Verb RunAs -Wait -PassThru
#Aktuelles Skript beenden
Exit
}
UAC umgehen Sie damit aber nicht und denken Sie daran, dass Sie auch die Parameter neu mit übergeben müssen. Eine Verarbeitung über eine Pipeline gelingt so auch nicht.
Ich bin dann eher der Freund das Skript direkt zu beenden, damit der Administrator gleich eine PowerShell als Admin ausführt.
- Erstellen von Runspaces
https://learn.microsoft.com/de-de/powershell/scripting/developer/hosting/creating-runspaces - PowerShell.Create Method
https://learn.microsoft.com/en-us/dotnet/api/system.management.automation.powershell.create - p0wnedShell -
PowerShell Runspace Post Exploitation Toolkit
https://github.com/Cn33liz/p0wnedShell
UAC mit __COMPAT_LAYER unterdrücken?
Bei der Recherche bin ich auf die Umgebungsvariable "__COMPAT_LAYER" gestoßen. Ich kann in einer Shell diese Variable setzen, so das nachfolgend gestartete Prozesse dann in diese im "Kompatibilitätsmode" ausgeführt werden. Mögliche Werte sind:
RUNASADMIN Das Programm wird mit Administratorberechtigung und der UAC-Eingabeaufforderung ausgeführt. RUNASINVOKER Das Programm wird mit den Berechtigungen eines übergeordneten Prozesses ohne UAC-Eingabeaufforderung ausgeführt. RUNASHIGHEST Das Programm wird mit der höchsten Berechtigungsstufe des Benutzers ausgeführt (die UAC-Eingabeaufforderung wird angezeigt). WIN8RTM Kompatibilitätsmodus für Windows 8 WIN7RTM Kompatibilitätsmodus für Windows 7 VISTARTM Kompatibilitätsmodus für Windows Vista VISTASP1 Kompatibilitätsmodus für Windows Vista (Service Pack 1) VISTASP2 Kompatibilitätsmodus für Windows Vista (Service Pack 2) WINXPSP3 Kompatibilitätsmodus für Windows XP (Service Pack 3) WIN2000 Kompatibilitätsmodus für Windows 2000 NT4SP5 Kompatibilitätsmodus für Windows NT 4.0 (Service Pack 5) WIN98 Kompatibilitätsmodus für Windows 98 WIN95 Kompatibilitätsmodus für Windows 95 256Color Mit 256 Farben ausführen 640x480 Bildschirmauflösung 640x480 DisableThemes Visuelle Design deaktivieren
Mehrere Werte können durch Leerzeichen getrennt angegeben werden.
# Setzen des RunAsInvoker in PowerShell
[Environment]::SetEnvironmentVariable("__COMPAT_LAYER", "RunAsInvoker")
REM Setzen des RunAsInvoker in der Eingabeaufforderung set __COMPAT_LAYER=RunAsInvoker
Bei EXE, COM und einigen anderen Dateierweiterungen können Sie diese Konfiguration direkt im Windows Explorer an der Datei vornehmen:
Aber auch hier kommt natürlich UCA zum Einsatz. Es hilft ihnen also nicht, dass ein Programm UAC-Dialoge umgehen kann.
- Application Compatibility Toolkit (ACT)
https://learn.microsoft.com/de-de/windows/win32/win7appqual/application-compatibility-toolkit--act- - Tipps - Eingabeaufforderung - Anwendungen im Kompatibilitätsmodus ausführen
https://www.windowspage.de/tipps/022879.html
Zusammenfassung
Wir kommen auf den ersten Abschnitt zurück, bei dem ein "Enable-RemoteMailbox" eine INPROXY-DLL nachladen wollte, was nicht ohne administrative Berechtigungen geht. In dem Fall gibt es mehrere Alternativen:
- Enable-RemoteMailbox mit mehr Parametern ohne Admin-Rechte
In meinem Fall habe ich einfach noch den Parameter "-PrimarySMTPAddress" addiert, so dass der Exchange Code keine DLL mehr zur Generierung dieser Adresse gebraucht hat. So konnte ich mit einem Dienstkonto die Aktion ohne privilegierte Rechte auf dem Computer selbst ausführen. - Ausführen als Task
Ich könnte den Code als Task im Windows Taskplaner ohne Zeitplan aber mit "Run as Administrator" einrichten. Um die Funktion auszuführen könne ich die gewünschten Parameter in eine XML/JSON-Datei ablegen und dann den Task anstarten. Das Skript müsste dann nur die Informationen quasi aus der "Job-Datei" auslesen und ausführen. - Logik als Dienst implementieren
Wenn ich gleich richtig programmieren möchte, dann kann ich ihn auch als Dienst umsetzen, welcher die privilegierten Tätigkeiten umsetzt. Ich brauche dann auch nur eine Schnittstelle, über die eine weniger privilegierte Software mit dem Dienst kommunizieren kann. Der Dienst sollte natürlich genau die übergebenen Informationen prüfen. Das ist im Grund das gleiche, was auch Exchange mit RBAC - Role Based Access Control macht. Als nicht direkt berechtigter Benutzer beauftrage ich Exchange etwas für mich zu tun. Exchange prüft dann meine Rollen, ehe er die Aktion umsetzt - UAC abschalten
Der schlechteste Option wäre es aber, UAC abzuschalten, nur damit alle Skripte mit höheren Berechtigungen gestartet werden. Leider kann ich keine Skripte oder Programme explizit als "vertrauenswürdig" einstufen, so dass diese keine UAC-Abfrage triggern.
Mein Exchange Problem in meiner Testumgebung konnte ich so lösen, dass ich einfach alle Daten komplett selbst generiert und mitgegeben habe. Damit musste die Recipient Management PowerShell gar nicht mehr eine DLL in ihren Prozessraum nachladen, was den UAC-Dialog angetriggert hat.
Weitere Links
- Recipient Management PowerShell
- Exchange Management Rolle
- ADSync mit Exchange Online Only
- Provisioning mit IsExchangeCloudManaged
- How User Account Control works
https://learn.microsoft.com/en-us/windows/security/application-security/application-control/user-account-control/how-it-works - User Account Control settings and configuration
https://learn.microsoft.com/en-us/windows/security/application-security/application-control/user-account-control/settings-and-configuration - Disable User Account Control (UAC) - Windows Server
https://learn.microsoft.com/en-us/troubleshoot/windows-server/windows-security/disable-user-account-control - Security - Inside Windows Vista User Account Control - Mark Russinovich
https://learn.microsoft.com/en-us/previous-versions/technet-magazine/cc138019(v=msdn.10) - Check for Admin Credentials in a PowerShell Script
https://web.archive.org/web/20150711220515/http://blogs.technet.com/b/heyscriptingguy/archive/2011/05/11/check-for-admin-credentials-in-a-powershell-script.aspx - UAC | Skripte unter Windows | Windows SBS and Essentials Blog
https://sbsland.me/2024/05/01/uac-skripte-unter-windows-2/ - UC Unleashed » Functions: Get-UACStatus Set-UACStatus – PowerShell Functions
for Getting and Setting UAC Status
https://www.ucunleashed.com/1026 - PowerShell Run As: Mastering Elevated Commands
https://powershellcommands.com/powershell-run-as - Continue dialog box for folder access in Windows Explorer when user only has
access with elevated token - Windows Server
https://learn.microsoft.com/en-us/troubleshoot/windows-server/windows-security/dont-have-permission-access-folder - Run application without elevation ('Run As Administrator')
https://www.nirsoft.net/articles/run_application_without_elevation.html
Mit der Umgebungsvariable "__COMPAT_LAYER=RunAsInvoker" können Sie die UAC automatisch unterbinden und mit Nein antworten - Runas, UAC, Fast User Switching: Als Administrator mit Standardrechten
arbeiten
https://www.windowspro.de/wolfgang-sommergut/runas-uac-fast-user-switching-als-administrator-standardrechten-arbeiten















