.net - usuario - ver contraseñas de credenciales de windows
Iniciar otro proceso con elevación utilizando diferentes credenciales de usuario. (5)
Estoy intentando iniciar un proceso elevado desde un proceso no elevado, pero también debo proporcionar el nombre de usuario y la contraseña de un usuario con credenciales administrativas. He probado tanto el método de "runas"
para la elevación como el uso de un manifiesto, pero ambos producen errores diferentes.
Por ejemplo, si hago esto (sin usar un manifiesto que requiere elevación):
ProcessStartInfo info = new ProcessStartInfo(path);
info.UseShellExecute = false;
info.UserName = username;
info.Password = securePwd;
info.Domain = "MyDomain";
info.Verb = "runas";
var proc = Process.Start(info);
El proceso se inicia sin mostrar el cuadro de diálogo de confirmación de UAC y falla al intentar ejecutar el comando que requiere permisos de administrador (solo estoy tratando de escribir un archivo de prueba en el directorio Archivos de programa).
Si agrego un manifiesto a la aplicación de destino que indica que requiere elevación, obtengo una Win32Exception
que indica que la operación requiere elevación.
El problema parece estar configurando UseShellExecute
en false
(ya que ambos enfoques funcionan bien cuando este no es el caso), pero tengo que configurarlo en falso para iniciar el proceso con una cuenta de usuario diferente.
¿Cómo puedo iniciar un proceso elevado desde un proceso no elevado y proporcionar el nombre de usuario y la contraseña manualmente?
EDICIÓN EN BOUNTY: Si bien no se le puede pedir al usuario que ingrese las credenciales de administrador, un diálogo de error de UAC es perfectamente aceptable. No estoy buscando pasar por alto UAC aquí.
Me sorprendió que no haya manera de hacer esto, hasta que encontré una entrada en el blog de Chris Jackson:
¿Por qué no puedo elevar mi aplicación para que se ejecute como administrador mientras uso CreateProcessWithLogonW?
Necesitas un bootstrapper. Algún proceso que le permitirá hacer la transición al usuario alternativo, que podría ser responsable de ejecutar la aplicación requireAdministrator. Entonces, podrías diseñar algo como esto:
¿Por qué no creamos la API
ShellExecuteWithLogonW
? Nunca diré nunca, y podríamos en algún momento. Pero hoy, los casos de uso para estas API han sido casos de uso donde ha habido un diseño alternativo que es superior.La solicitud más común es para personas que escriben software de implementación de software propio, donde les gustaría codificar las credenciales directamente en la aplicación y elevar su propio proceso. El problema real aquí no es la falta de la API, es que tiene credenciales de administrador codificadas en su aplicación para que el mundo las lea.
Por lo tanto, la solución requiere ShellExecute
, es el único que sabe cómo activar un diálogo de consentimiento .
Trae un buen punto: ¿Qué estás haciendo con la contraseña de una persona ya?
Bonus Chatter
No hay UAC en Server Core porque no hay ventanas para mostrar un aviso de consentimiento.
Según la documentación de MSDN:
Cuando UseShellExecute es falso, puede iniciar solo los ejecutables utilizando el objeto Process.
Noté su declaración var proc = Process.Start(info);
no está utilizando el Process
como el tipo de clase.
También asegúrese de que la path
parámetro sea la ruta completa al ejecutable. Por ejemplo, "c://directory//contains//process_to_be_started//executable.exe"
Según la documentación de MSDN esto es importante:
La propiedad WorkingDirectory debe establecerse si se proporcionan UserName y Password. Si la propiedad no está establecida, el directorio de trabajo predeterminado es% SYSTEMROOT% / system32.
Intentaría el código siguiente para ejecutar el proceso de destino con privilegios elevados (con derechos de administrador).
ProcessStartInfo info = new ProcessStartInfo(path);
info.UseShellExecute = false;
info.UserName = username;
info.Password = securePwd;
info.Domain = "MyDomain";
info.Verb = "runas";
info.WorkingDirectory = "c://directory//contains//process_to_be_started"
''var proc = Process.Start(info);
Process proc = Process.Start(info);
Si está creando una aplicación de Windows Installer (MSI) y la está actualizando con MSP, Windows Installer tiene soporte integrado para su escenario exacto: - revise las revisiones de Control de cuentas de usuario (UAC) .
Funciona básicamente así:
- Cuando crea el MSI original, genera un certificado y pone su clave pública (o algo así) en el MSI.
- El administrador de la máquina de destino instala el MSI en la máquina.
- Usted crea una actualización (MSP) y la firma con el certificado.
- Cualquier usuario en la máquina de destino ahora puede instalar la actualización: Windows Installer validará el certificado con la clave pública en el MSI original y aceptará instalarlo si es así. No creo que obtendrás un aviso de UAC, aunque no estoy seguro.
No puedes elevar un proceso ya en ejecución. Por lo tanto, debe refactorizar su aplicación para que sea separada en operaciones de administración y no de administración, ejecutando la aplicación predeterminada con privilegios normales e iniciando otro proceso elevado para cada operación administrativa.
Trabajemos con eso, asumiendo que usted solicita derechos de administrador desde el principio en los procesos que los requieren . Basado en el contexto que ha proporcionado:
El problema parece estar configurando
UseShellExecute
enfalse
(ya que ambos enfoques funcionan bien cuando este no es el caso), pero tengo que configurarlo en falso para iniciar el proceso con una cuenta de usuario diferente.
Como mencionó, exactamente como se indica en la documentación de UseShellExecute
:
UseShellExecute debe ser falso si la propiedad UserName no es Nothing o una cadena vacía, o se lanzará una InvalidOperationException cuando se llame al método Process.Start (ProcessStartInfo).
Ahora sabemos que está ejecutando su programa directamente en lugar de utilizar un shell. Esta es una información valiosa.
Backpathing a través de la documentación, los documentos para ProcessStartInfo
llevan la siguiente nota de seguridad:
Esta clase contiene una demanda de enlace a nivel de clase que se aplica a todos los miembros. Se emite una excepción SecurityException cuando la persona que llama de inmediato no tiene permiso de plena confianza. Para obtener detalles sobre las demandas de seguridad, consulte las Demandas de enlaces .
Por lo tanto, no tiene la demanda de enlace correcta. Mientras intentaba resolver su problema de permisos, creó involuntariamente otro problema de permisos.
El resultado es que necesita decorar su método de llamada con la demanda de seguridad adecuada, que debería ser FullTrust
. Puede hacer esto declaratively o declaratively dentro de su código.
ProcessStartInfo.Verb="runas"
es solo para Windows Vista y superior, por lo que debe solicitar el nivel del sistema y no hacer la elevación para XP.
Creo que si elige ProcessStartInfo.Verb="runas"
, no debe especificar el nombre de usuario ni la contraseña.
Si UAC es de, entonces se supone que debe tener éxito de todos modos, no debería ser un problema.