El TecnoBaúl de Kiquenet

Kiquenet boring stories

Archive for the ‘Security’ Category

Manage Credentials programmatically using C#

Posted by kiquenet en 2 enero 2015

Credential Manager

CredentialManagement
http://nuget.org/packages/CredentialManagement/

http://credentialmanagement.codeplex.com/SourceControl/latest

CredMan.ps1
https://gallery.technet.microsoft.com/scriptcenter/PowerShell-Credentials-d44c3cde

        [TestMethod]
        public void Set_Credentials_for_older_domain_whe_migration_to_new_domain()
        {
            var accesos = new List<string> {
            "intranet",
            "intranet.xxxxx.net",
            "intranet.zzzzzzzz.com",
            "intranetescritorio.zzzzzzzz.net",
            "more…",
            };

            accesos.ForEach(acceso => SaveCredential(acceso));
        }

        private static Credential SaveCredential(string CredentialName)
        {
            var UserName = @"OLDERDOMAIN\user";
            var Password = "pass";

            var cm = new Credential { Target = CredentialName, Type = CredentialType.DomainPassword };
            if (cm.Exists())
            {
                cm.Load();
                Console.WriteLine("Credential " + cm.Target + ". Data: " + cm.Username + " " + cm.Password);

                //if (cm.Type == CredentialType.Generic)  cm.Delete();

                return cm;
            }

            cm = new Credential
            {
                Target = CredentialName,
                Type = CredentialType.DomainPassword,
                PersistanceType = PersistanceType.Enterprise,
                Username = UserName,
                Password = Password
            };
            cm.Save();
            return cm;
        }

Tools useful: PromptForCredentials Builder and Credential Set Manager by Kenny Kerr (Microsoft)

Windows 8 – New API Windows.Security
http://msdn.microsoft.com/en-us/library/windows/apps/windows.security.credentials.aspx
https://code.msdn.microsoft.com/windowsapps/PasswordVault-f01be74a

[void][Windows.Security.Credentials.PasswordVault,Windows.Security.Credentials,ContentType=WindowsRuntime]
(new-object Windows.Security.Credentials.PasswordVault).RetrieveAll() | % { $_.RetrievePassword(); $_ }

It only displays data from the Web Credentials store, not the Windows Credentials

The new api has no way to access the Windows Credentials

http://stackoverflow.com/questions/14813370/how-to-access-the-stored-credentials-passwordvault-on-win7-and-win8

Sources:

http://msdn.microsoft.com/en-us/library/aa480470.aspx#cred_topic5

http://stackoverflow.com/questions/9221245/how-do-i-store-and-retrieve-credentials-from-the-windows-vault-credential-manage

http://stackoverflow.com/questions/17741424/retrieve-credentials-from-windows-credentials-store-using-c-sharp

Anuncios

Posted in .NET, Security, Seguridad | Etiquetado: | Leave a Comment »

UAC, Run As Administrator, Elevated Process

Posted by kiquenet en 22 agosto 2014

cmd.RedirectStandardInput = true;
cmd.RedirectStandardOutput = true;
cmd.RedirectStandardError = true;
cmd.UseShellExecute = false; // true ???
cmd.Verb = “runas”

The Verb only works with UseShellExecute set to true

You must use ShellExecute. ShellExecute is the only API that knows how to launch Consent.exe in order to elevate.
In C#, the way you call ShellExecute is to use Process.Start along with UseShellExecute = true:






const int ERROR_CANCELLED = 1223; //The operation was canceled by the user. ProcessStartInfo info = new ProcessStartInfo(@"C:\Windows\Notepad.exe"); info.UseShellExecute = true; info.Verb = "runas"; try { Process.Start(info); } catch (Win32Exception ex) { if (ex.NativeErrorCode == ERROR_CANCELLED) MessageBox.Show("Why you no select Yes?"); else throw; }

You can indicate the new process should be started with elevated permissions by setting the Verb property of your startInfo object to ‘runas’, as follows:

startInfo.Verb = "runas";

This will cause Windows to behave as if the process has been started from Explorer with the "Run as Administrator" menu command.

This does mean the UAC prompt will come up and will need to be acknowledged by the user: if this is undesirable (for example because it would happen in the middle of a lengthy process), you’ll need to run your entire host process with elevated permissions by embedding the appropriate manifest in your application to require the ‘highestAvailable’ execution level: this will cause the UAC prompt to appear as soon as your app is started, and cause all child processes to run with elevated permissions without additional prompting.

Edit: I see just just edited your question to state that "runas" didn’t work for you. That’s really strange, as it should (and does for me in several production apps). Requiring the parent process to run with elevated rights by embedding the manifest should definitely work, though.

Manifest for Application: http://msdn.microsoft.com/en-us/library/bb756929.aspx

<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />

Executable: IsUserAdmin.exe 
Manifest:IsUserAdmin.exe.manifest
Sample application manifest file:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> 
  <assemblyIdentity version="1.0.0.0"
     processorArchitecture="X86"
     name="IsUserAdmin"
     type="win32"/> 
  <description>Description of your application</description> 
  <!-- Identify the application security requirements. -->
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel
          level="requireAdministrator"
          uiAccess="false"/>
        </requestedPrivileges>
       </security>
  </trustInfo>
</assembly>

Update: The app manifest way is preferred:

Right click project in visual studio, add, new application manifest file, change the file so you have requireAdministrator set as shown in the above.

(Properties Project –> Application –> Resources –> Icon and manifest (embed, first add it and then select)

How to set UAC settings in manifest (VS 2008)

http://justinyue.wordpress.com/2008/12/19/how-to-set-uac-settings-in-manifest-for-vs-2008/

if (IsAdministrator() == false)
{
    // Restart program and run as admin
    var exeName = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
    ProcessStartInfo startInfo = new ProcessStartInfo(exeName);
    startInfo.Verb = "runas";
    System.Diagnostics.Process.Start(startInfo);
    Application.Current.Shutdown();
    return;
}

private static bool IsAdministrator()
{
    WindowsIdentity identity = WindowsIdentity.GetCurrent();
    WindowsPrincipal principal = new WindowsPrincipal(identity);
    return principal.IsInRole(WindowsBuiltInRole.Administrator);
}


// To run as admin, alter exe manifest file after building.
// Or create shortcut with "as admin" checked.
// Or ShellExecute(C# Process.Start) can elevate - use verb "runas".
// Or an elevate vbs script can launch programs as admin.
// (does not work: "runas /user:admin" from cmd-line prompts for admin pass)


this error

The Process object must have the UseShellExecute property set to false in order to redirect IO streams.

The Process object must have the UseShellExecute property set to false in order to start a process as a user

you cannot have it both ways. UAC prevents an unelevated process from hi-jacking the capabilities of an elevated one. The only way you can redirect is to elevate yourself first.

You need to set UseShellExecute to true for the Verb to be respected and it must be set to ‘false’ to redirect standard output. You can’t do both.

I’m pretty sure Windows also won’t allow you to redirect standard input/output/error across the admin/non-admin security boundary. You’ll have to find a different way to get output from the program running as admin.

According to this article, only ShellExecute checks the embedded manifest and prompts the user for elevation if needed, while CreateProcess and other APIs don’

http://www.codeproject.com/KB/vista-security/UAC__The_Definitive_Guide.aspx

  • UAC – What. How. Why.. The architecture of UAC, explaining that CreateProcess cannot do elevation, only create a process. ShellExecute is the one who knows how to launch Consent.exe, and Consent.exe is the one who checks group policy options.


Check out this code (I was inspired by the code here, but I’ve improved it – in my version there is no directory created and removed to check for admin privileges):

:::::::::::::::::::::::::::::::::::::::::

:: Automatically check & get admin rights

:::::::::::::::::::::::::::::::::::::::::

@echo off

CLS

ECHO.

ECHO =============================

ECHO Running Admin shell

ECHO =============================

:checkPrivileges

NET FILE 1>NUL 2>NUL

if '%errorlevel%' == '0' ( goto gotPrivileges ) else ( goto getPrivileges )

:getPrivileges

if '%1'=='ELEV' (shift & goto gotPrivileges) 
ECHO.

ECHO **************************************

ECHO Invoking UAC for Privilege Escalation

ECHO **************************************

setlocal DisableDelayedExpansion

set "batchPath=%~0"

setlocal EnableDelayedExpansion

ECHO Set UAC = CreateObject^("Shell.Application"^) > "%temp%\OEgetPrivileges.vbs"

ECHO UAC.ShellExecute "!batchPath!", "ELEV", "", "runas", 1 >> "%temp%\OEgetPrivileges.vbs"

"%temp%\OEgetPrivileges.vbs"

exit /B

:gotPrivileges

::::::::::::::::::::::::::::

:START

::::::::::::::::::::::::::::

setlocal & pushd .

REM Run shell as admin (example) - put here code as you like

cmd /k

The script takes advantage of the fact that NET FILE requires admin privilege and returns errorlevel 1 if you don’t have it. The elevation is achieved by creating a script which re-launches the batch file to obtain privileges. This causes Windows to present the UAC dialog and asks you for the admin account and password.

I have tested it with Windows 7 and with Windows XP – works fine for both. Advantage is, after the start point you can place anything that requires admin privileges, e.g. if you intend to re-install and re-run a Windows service for debugging purpose (assumed that mypackage.msi is a service installer package):

msiexec /passive /x mypackage.msi
msiexec /passive /i mypackage.msi
net start myservice

Without this privilege elevating script UAC would ask you three times for your admin user and password – now you’re asked only once at the beginning, and only if required.


Update: If your script just needs to show an error message and exit if there are no admin privilegesinstead of auto-elevating, this is even simpler: You can achieve this by adding the following at the beginning of your script:

@ECHO OFF & CLS & ECHO.
NET FILE 1>NUL 2>NUL & IF ERRORLEVEL 1 (ECHO You must right-click and select &
  ECHO "RUN AS ADMINISTRATOR"  to run this batch. Exiting... & ECHO. & 
  PAUSE & EXIT /D)
REM ... proceed here with admin rights ...

This way, the user has to right-click and select "Run as administrator". The script will proceed after the REM statement if it detects admin rights, otherwise exit with an error. If you don’t require the PAUSE, just remove it. Important: NET FILE [...] EXIT /D) must be in the same line, it is displayed here in multiple lines for better readability!


Update: On some machines, I’ve encountered issues, which are solved in the new version above already. One was due to different double quote handling, the other issue was due to the fact that UAC was disabled (set to lowest level) on a Windows 7 machine, hence the script calls itself again and again.

I have fixed this now by stripping the quotes in the path and re-adding them later and I’ve added an extra parameter which is added when the script re-launches with elevated rights.

The double quotes are removed by the following (details are here):

setlocal DisableDelayedExpansion
set "batchPath=%~0"
setlocal EnableDelayedExpansion

You can then access the path by using !batchPath!, it contains no double quotes so it is safe to say "!batchPath!" later in the script.

The line

if '%1'=='ELEV' (shift & goto gotPrivileges)  

checks if the script has already been called by the VBS to elevate rights, hence avoiding endless recursions. It removes the parameter using shift.


Mt.exe Tool

Common Errors:

Exited with code 9009 (Post Build Event)

Values of attribute "name" not equal in different manifest snippets. mt.exe


http://stackoverflow.com/questions/4677055/visual-studio-post-build-event-mt-exe-command-fails-with-code-9009?rq=1#4865696

"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\mt.exe"
"C:\Program Files\Microsoft SDKs\Windows\v7.0A\bin\mt.exe" -manifest "$(ProjectDir)$(TargetName).exe.manifest" -updateresource:"$(TargetDir)$(TargetName).exe;#1"

References:

http://stackoverflow.com/questions/8690552/run-elevated-process

http://stackoverflow.com/questions/16926232/run-process-as-administrator-from-a-non-admin-application/20872219#20872219

http://stackoverflow.com/questions/133379/elevating-process-privilege-programatically

http://msdn.microsoft.com/en-us/magazine/cc163486.aspx

http://stackoverflow.com/questions/7044985/how-can-i-auto-elevate-my-batch-file-so-that-it-requests-from-uac-admin-rights?answertab=votes#tab-top

http://justinyue.wordpress.com/2008/12/19/how-to-set-uac-settings-in-manifest-for-vs-2008/

Posted in .NET, Scripts, Security | Etiquetado: , , , , | Leave a Comment »

The Perils and Pitfalls of Launching a Process Under New Credentials by Asprosys

Posted by kiquenet en 9 mayo 2014

This isn’t a common need but it also isn’t that rare, so I thought I had better post this step by step guide to troubleshooting the launching of a process under impersonated credentials. This is based on using the Start method of the .Net Process class but it is also applicable to the underlying API calls: CreateProcessWithLogonW and CreateProcessWithTokenW.

Access Denied – The first attempt and an access denied exception right off the bat. This is the most common initial problem and is caused by the fact that the service is running under the LOCAL SYSTEM account. Strangely, the SYSTEM account is the most powerful account on the computer but one of the few things it cannot do is launch a process using CreateProcessWithLogonW which is the API underlying the call to Process.Start. So change your service account to Local Service, it’s probably the more appropriate account anyway.

Access Denied Again – Aargh, I thought we solved this. Oops, double check the permissions on the application that you are trying to launch. Remember that the system tries to access the application file as the user account that the process will be running under, not the service account.

Invalid Directory Error – What? All the paths are correct. All the directories are spelled correctly, no invalid characters. This is an incredibly annoying error and is not very consistent. Usually when we run a process we don’t bother setting the WorkingDirectory property and just accept the default from the parent process. When starting a process with new credentials you can’t do that, you must explicitly set a path for the WorkingDirectory or you’ll get a "The directory name is invalid." Win32Exception.

Failure: No Error? – Process.Start handles the creation of the Environment block for the new process for you quite well. So this is a problem only if you are using the underlying API. When calling one of the CreateProcess* APIs it is normal to leave the lpEnvironment parameter as NULL and have the system use the default of copying the block from the parent process. But when launching under new credentials you must create an environment block explicitly, either manually or using CreateEnvironmentBlock. What makes this worse is, if you leave this out the CreateProcess* call will fail but GetLastError will return ERROR_SUCCESS and if you make an error creating your environment block there will be no error but the process may just not run at all.

Application Failed to Initialize Properly – No more exceptions, you’ve solved all the problems and the process has been launched. Oops again, where is the process? Check the event log (or you may have received an Application Error pop-up). There should be an entry for Application Error that says that your process was the faulting application, either user32.dll or kernel32.dll was the faulting module and the exception was: 0xC0000142. There may be some minor variation in this but basically it is saying that your application could not initialize. The reason for this is that on initialization, before any application code is run, all processes are attached to a Window Station and all threads are attached to a Desktop but the user you are launching under does not have permission to access the Window Station and Desktop in which your process is being launched, ergo it can’t initialize. The security descriptors for the Window Station and Desktop must be adjusted to give AllAccess permission to the user the process is being launched under. This is a devil to do directly in .Net, so you might find the security wrapper classes here useful.

No More Errors – Really, no more errors, your process should be running smoothly now. There may be some variations in what you need to do based on who the user is (for instance an administrator will already have the correct permissions in some cases) or what kind of session you are launching in. But following these steps should make your life smooth and easy (well maybe not your whole life).

Solution:

I had to add a reference to AsproLock.dll and associated code in order to permit the user account to have access to the running resource.

            //The following security adjustments are necessary to give the new 
            //process sufficient permission to run in the service's window station
            //and desktop. This uses classes from the AsproLock library also from 
            //Asprosys.
            IntPtr hWinSta = NativeMethods.GetProcessWindowStation();
            WindowStationSecurity ws = new WindowStationSecurity(hWinSta,
              System.Security.AccessControl.AccessControlSections.Access);
            ws.AddAccessRule(new WindowStationAccessRule(userPassDto.Usuario,
                WindowStationRights.AllAccess, System.Security.AccessControl.AccessControlType.Allow));
            ws.AcceptChanges();

            IntPtr hDesk = NativeMethods.GetThreadDesktop(NativeMethods.GetCurrentThreadId());
            DesktopSecurity ds = new DesktopSecurity(hDesk,
                System.Security.AccessControl.AccessControlSections.Access);
            ds.AddAccessRule(new DesktopAccessRule(userPassDto.Usuario,
                DesktopRights.AllAccess, System.Security.AccessControl.AccessControlType.Allow));
            ds.AcceptChanges();

[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr GetProcessWindowStation();

[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr GetThreadDesktop(int dwThreadId);

[DllImport("kernel32.dll", SetLastError = true)]
public static extern int GetCurrentThreadId();


References

http://asprosys.blogspot.com.es/2009/03/perils-and-pitfalls-of-launching.html

http://stackoverflow.com/questions/17488220/wcf-service-process-start-under-network-service-account-impersonating-as-a-diffe

Aspro Lock – Access Control

Code Samples

Creating New Process Under Alternate Credentials (createprocessasuser)

processstart-hangs

Posted in .NET, Security | Etiquetado: , , , | Leave a Comment »