Looking for suggestions on how to go about the following, i.e what would be the best language to do it in etc, third party tools are a no :(
I've been tasked to create some sort of windows shell/command line interface that will allow a standard users to install a specific set of applications (configurable by administrators) (installation requires Admin/UAC elevation) due to security restrictions the user cannot have elevated privileges so they'll be able to run the shell as a standard user and it would have hidden/encrypted credentials built in to run the installs as.
Some of the requirements are as follows:
It would need to work on Server 2008 R2, 2012 r1 and 2012 r2
The credentials used to perform the install would have to be hidden (encrypted) from the end user.
Ideally it could work by us providing some config to it prior to handing that server over to the customer and limit what it could be used to install to a particular .exe or .msi (so we know of a need to install an app, we are advised of the name of the install and can logon and can enter it into a form maybe so only that app can be installed, then hand the server over to the customer who runs the same utility or shell extension or whatever and can then install their app.
Even more ideally it was more intelligent than that and some means of ensuring any .msi was indeed installing the application that the msi name related to (seems unlikely but just in case a normal user created an .msi to grant himself further admin access as per http://blogs.technet.com/b/fdcc/archive/2011/01/25/alwaysinstallelevated-is-equivalent-to-granting-administrative-rights.aspx )
Ideally its lifespan would be limited in terms of time (unsure if this could be for example to x number of days).
Any pointers on how to go about this, seems like a good challenge :)
Thanks for reading all that!
Mike
Thanks for the responses,
I managed to do this in C#, with no prior experience in the language :)
The application has 2 parts to it, a GUI and a service. It works by having the application send an install command via IPC to it's counterpart elevated service. (Thanks Hans Passant for pointing me in the right direction there). The service initiates the installer under it's own elevated account but displays the installer GUI on the users session. Files are HMACSHA1 checksum validated prior to install, on both the app and the service.
Thanks,
Mike
If a user requires the ability to install application in the Program Files folder, then instruct the domain administrator to give Full Control of the Program Files folder to Everyone:
Just because the default setting forbids standard users from modifying programs, doesn't mean you have to keep it that way. Windows is a secure operating system that gives you the capability to keep it secure.
If your administrator only wants some users to be able to modify the contents of the Program Files folder, then only give that permission to certain users.
The better solution is to re-design the applications so that they do not install in a (by default) protected location. Have them instead install in:
%APPDATA_LOCAL%\Contoso\Frobber\Grob.exe
e.g.
D:\Users\Ian\AppData\Local\Contoso\Frobber\Grob.exe
A user is always allowed to write anything in their own profile folder.
Related
We are writing an installer for our Windows tool. As our tool uses an updater (wyUpdate) and we want that users WITHOUT Administator rights can performs updates. Which is the right directory to install the app to? The standard C:\Program Files requires Administrator rights, so we have discarded this option. After reading a bit on the Web, we have chosen AppData, i.e. C:\Users\USERNAME\AppData\Local.
Is this best practice? Or should we use another directory?
If you do not want to allow your users to mess with the installed program, you have to install it to a folder that needs Administrator privileges.
To allow an automatic update of such application, you need to develop/install a service that runs with Administrator privileges, which will update the installation. This is what Windows Update, Mozilla Maintenance Service, Google Chrome Elevation Service, Adobe Acrobat Update Service and similar services do.
If you do not want to implement a service, but you want the application to be used by all users of the machine, you need to install it to a folder that can be accessed by all users, yet does not need Administrator privileges. You can for example use C:\Users\Public. See also Is there a shared folder in Windows to which non-elevated users have write access?. You can use PUBLIC environment variable to resolve that path.
If the application is to be used by one user only, then you are ok with using C:\Users\Username\AppData\Local – {userappdata} in Inno Setup.
Related question: Deploying application with .NET framework without admin privileges
I'm building an installer with WiX to install a program, per machine (not per user), and it gives them the option to register the program. Registration involves entering user name and organization (or accepting some defaults from Windows settings), and entering a valid registration key. When the registration key is validated, I write registry settings in the HKEY_LOCAL_MACHINE area with this information. Under Windows, when one runs the MSI, it prompts automatically for an admin password to be able to set registry values in HKEY_LOCAL_MACHINE. So far life is good...
I am including an option in the MSI to give the user the option to defer registration until a later point in time. However, if the user is a normal user and they are running the application, if I have a dialog in the app which prompts for name/org/product-key, Windows doesn't the app to write the information to HKEY_LOCAL_MACHINE. So a user cannot use the application itself, running as a normal user, to perform a registration per-machine as the MSI does after prompting for admin credentials.
My thought then was, for post-installation registration, to either (a) find a way from within the application to elevate privileges, with a prompt for admin credentials, allowing it to write HEKY_LOCAL_MACHINE (is this possible?), (b) include an option in the installer that, when run and the app is already installed and not registered, walks through the registration as it would during a normal install. It would then prompt for the admin credentials and life is good again. Alternatively, (c) create a separate MSI that just does registration, install this with the program, and call this MSI from the program when the user selects the "Register..." command in the program.
I've not seen either of these approaches done by any applications before, so I'm not sure either is a good approach. Other than that, however, I'm not sure how, post-installation, I can conveniently allow the user to do a per-machine app registration. Ideally, I'd like to be able to do it from a command within the app, but re-running the installation MSI would be minimally acceptable.
How is this normally done? Or are per-machine installations even normally accompanied by per-machine registrations?
Very good question - I have dealt with this issue many times myself. No ideal solutions, but several options (as you have already discovered).
Before answering, I want to point out that I have a strong aversion against doing too much registration and configuration in the setup itself. It is error prone, and much better done in the application itself for a plethora of reasons: Installer with Online Registration for Windows Application (recommended quick read - tidbits from real life experience).
Writing to HKCU
As you already know, one option is to keep the license key and registration in HKCU only. This is often acceptable unless you want to share a license key between many users on the box. The license key, if added to HKCU, will also generally roam with the user to other computers - which can be helpful or desirable.
Personally, this is the option I prefer: not registering anything in the setup, but writing to HKCU or the user-profile from the application (as explained in the link above as well). As stated, the only drawback is that you can't write a shared license key to HKLM so it applies to all users and not just a single user. This appears to be the core of the problem you are describing.
Writing to HKLM
Setup writes HKLM: Write the HKLM license key (and registration) during the setup to HKLM as Phil has described above using the default Windows Installer properties (just listing this as an option - which you already know about). This should work OK in my opinion - but your issue seemed to be to allow the "deferred registration".
Custom HKLM ACL permissioning: In order to write to HKLM from your non-elevated application, one way to do it is to use your setup to apply custom ACL permissions to the location in HKLM where you want to write the shared registry key from your application. Your application can then freely update this specific location in HKLM at any time without elevated rights. You simply add ACL write access for "Users".
WiX supports this, but I don't have a sample for you available, please check the WiX documentation for permissioning.
Using custom permissioning is generally frowned upon (and I agree it is not ideal design), but it allows any user to add a license key to HKLM without any elevation after the install (and also allows any users to delete it - which can be a problem).
See section 14 here for a quick description of why custom permissioning is not generally recommended: How do I avoid common design flaws in my WiX / MSI deployment solution?
In summary, I don't generally suggest setting custom permissions, but it will definitely work. I have done it myself when client requirements are such that this is the only thing they will accept. It will violate logo requirements for Windows applications, but it should be less serious than the security issues that result from option 3 below.
Run app as admin: If you don't want to apply ACL permissions, I believe you can prompt the user for admin rights for your application as described here (I believe this is what Phil referred to in his comment if I understand correctly):
How do I force my .NET application to run as administrator? (the legendary Hans Passant - one more answer).
This is most definitely not recommended (but we want to show people what is possible too). Your whole application will run with admin rights all the time, which is not a good idea at all.
Doing this will violate a key part of logo requirements for Windows applications and you will also open your application up to attack from malware.
Definitely try to make your users understand the consequences of this "easy fix". I would make sure to put all responsibility on the client if they go for this option - they must understand what they are doing.
Note that you should be able to use this manifest approach to launch a separate EXE with elevated rights to do only the registration. See next bullet point.
Elevate app on demand: I am not familiar with the technical details of elevating your application on demand whilst it is running - as you invoke a dialog or feature that needs HKLM access. Perhaps Phil knows a way to achieve this? I found some links though:
Elevating during runtime (from Code Project)
How to elevate privileges only when required? (good read)
Skimming the linked content above, it seems like you can launch a separate EXE with elevated rights to do your registration - a known option for you I assume.
Would love to hear back if this is something you decide to try. Could be useful for all of us.
Internet validation: Just throwing an option out there: what I often want to do is to put the whole registration license key validation online from within the application (never, ever try this from the setup, just so that is mentioned - a setup that tries to access the Internet might be the biggest deployment anti-pattern of all - at least for now).
I write the license key from the setup, and the validation of it takes place on application launch against a server on the Internet. Then there is no validation code in your application or your setup to crack.
You need an Internet "handshake" and you can repeat this process per user - allowing you to tightly control who is using your license key.
Nothing is ever easy, and proxy server issues could cause problems. Corporate deployment would also mean that such "online activation" is frowned upon. They want applications fully installed after deployment.
Separate registration MSI: I would prefer not to create a separate MSI just for the registration process as you mention in your question. This just seems like unnecessary complexity that can break easily. For one thing you get a dual source problem that must be permanently maintained. I would guess that this could become a classic support issue.
Re-run original MSI: I am honestly not sure if re-running your original setup to do the registration will launch it elevated or not. I think it will be elevated (should be, can't see any reason why it shouldn't - the MSI database stores a flag to determine if elevation is required "Word Count"), and then you should be able to add your registration details provided you access the registration dialog from the setups "modify" or "repair" modes.
This kind of registration is usually done using the standard Windows Installer properties so it just works.
If you have a verification key then it's typically associated (in the dialog) with the standard PIDKEY property which then after validation becomes the ProductId property.
https://msdn.microsoft.com/en-us/library/windows/desktop/aa370826(v=vs.85).aspx
Similarly the user name and company name are associated in the dialog with the USERNAME and COMPANYNAME properties.
After this, they're available through (Win32) MsiGetProductInfo () by asking for RegOwner etc:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa370130(v=vs.85).aspx
or similar APIs (WMI does some of this).
So generally speaking you just set the properties from the dialogs and it all just works with no need for you to write them to the registry.
A customer installing my companies software package has no problem installing the package silently when running as an admin account. The software and the service both install correctly and start up post installation. However - they need to push this application to all the computers in a particular group.
They are using SCCM (I do not know the version) and the software package is a InstallShield .exe packaged .msi.
When they try to use the NT Authority\System user to push the package to their test device, the installation fails soon after the 3rd party software package that is included completes. The error log displays that it is a SDDL error 1943. Any idea why this would occur on the NTA\System account and not on a local admin account for a given machine?
The silent install string we are using is setup.exe /s /v" /qn AgreeToLicense=Yes SetupType=Typical"
I'm not a dev, so I dont have direct access to any code in the software, simply a tier 3 tech support working with customers.
Sounds like your MSI is using the MsiLockPermissionsEx table to specify an SDDL string on some resource its installing or configuring (either file, directory, service or registry entry). Either the SDDL string is misconfigured (unlikely if it works from one account but not another) or the ACL on the target directory/service/registry key have become corrupted, which isn't completely unheard of.
You could try getting the customer to deploy a domain account as local admin to the computers and then set SCCM to run the package with this account. I wouldn't recommend this though as it carries inherent security risks of its own.
I'm afraid this may be one that your developers (or whoever created the MSI) need to work out with the customers to find out which resources are at fault and progress the diagnosis.
Sorry I couldn't be of further help.
I think I have found the issue. During install the .msi writes a file to the desktop to be read for configuration settings for the service as being installed. I had the file (and I am sure the customer did as well) already written to the desktop when I tried to invoke the System User for install. This does seem to be an ACL issue, in reference to the System User read/writing to a local user desktop. When the file was deleted, I received error 1406, that it could not write the value of a key. Looking on the desktop, the file had also never been written to the local desktop. When the file was already there (as such with a previous install) I get the error in the original post. At this point I am moving forward testing this as an ACL error and notifying the devs of my findings.
Many Windows programs are able to run an update when they start, without an admin prompt. Similarly, my program needs to update itself, without any user input. Any user who logs in needs to be able to use the program.
My program can already find new updates, download them, and run them, but the NSIS installer/updater requires admin rights.
What would I need to do to implement this using Free Pascal and NSIS, short of giving all users access to the installation directory?
Is your application that important that you need to do this? How often do you actually plan to push out updates?
Most applications can probably get away with just elevating with UAC each time it needs to install a update.
If you absolutely feel that you need to "bypass UAC" then you can do what Firefox does; install a NT Service. You don't start this service in the installer but you must call GetNamedSecurityInfo+SetNamedSecurityInfo so you can add SERVICE_START access for the Everyone group to the ACL. Your application running as a normal user can then start this service when there is an update and the service does the updating.
From a security standpoint there are some dangers here because the service runs with full access to the system so you must make sure that your updates are signed so it does not become an easy to use backdoor if someone is able to pull off a man in the middle attack.
I personally think that you should consider doing per-user installations if your program is not too big...
To get Windows users to log on as regular users instead of admin, I need to check that all their applications run OK with limited rights.
Is there an application specifically aimed at checking that an application can run with limited rights, or is SysInternals' Process Monitor what everyone uses for this purpose?
Thank you.
Create a test account that has the permissions as the domain users of your application Login in as this user on a non-development computer. Preferrably a computer with a new operating system installation and all of the other "standard" company software. Install the software and run. This is the only way to really test your application.
Make sure you exercise the entire application.
Make sure install and uninstall work as expected and do not leave any artifacts behind.
Having the ability to restore the operating-system and software on the test computer to its original state is a great help.
Use the Permission Calculator Tool to make sure you handle obvious issues before performing this test.
I'm not sure if it would help since I never used it but I know there's a Permission Calculator Tool (Permcalc.exe) at http://msdn.microsoft.com/en-us/library/ms165077%28VS.80%29.aspx.
Permission Calculator Tool
(Permcalc.exe)
The Minimum Grant Set Determination
tool (Permcalc.exe) is used to
estimate the permissions callers must
be granted to access the public entry
points of an assembly. This tool is
new in the .NET Framework version 2.0.
It is intended for use by advanced
users.
Run this application on Windows 7/Vista with access control enabled. You may consider Windows 7 as such testing application :)
It is recommended to use non-administrator account with activated access control on a developer computer, when you write and debug the program. This creates some problems, and Windows developers hate this, turning off access control or using administrator account. However, working on Linux/Unix, we don't have administrator rights, and this is OK.