Showing posts with label Security. Show all posts
Showing posts with label Security. Show all posts

Sunday, July 31, 2005

Trouble ahead for time computations?

I was just reading an article about the new U.S. Energy Bill that intends to extend Daylight Savings Time an additional month (starting in 2007). I wonder what the impact of this is on the Computer Science front. There has not been any chatter on my normally read blogs, but perhaps there will be soon. I have no facts to back up my theory here, but lets play along with my conspiracy theory and possibly learn something about static and dynamic linking of DLLs.

Think about this from the Microsoft C/C++ developer perspective: the date functions are implemented in the C standard library, MSVCRT.DLL (or its post VC6 brethren MSVC*.dll). Lets assume (although I am guessing) that the "rules" for the current daylight savings time are implemented in this same DLL (NOTE: Please see comments). One of these functions is called mktime(). Let me quote from MSDN:

When specifying a tm structure time, set the tm_isdst field to 0 to indicate that standard time is in effect, or to a value greater than 0 to indicate that daylight savings time is in effect, or to a value less than zero to have the C run-time library code compute whether standard time or daylight savings time is in effect. (The C run-time library assumes the United States's rules for implementing the calculation of Daylight Saving Time).
So if we developers assumed that the runtime would take care of conversions for us, and we statically linked to the library, we may have to recompile against a newer link library (with the revised code) for our applications to continue working if this change actually happens. On the other hand, had the developer dynamically linked to this DLL and not copied the pre-dst-updated MSVCRT.DLL to the application folder or application current directory (Remember that in Windows Server 2003 and possibly Windows XP the rules have changed), the DLL can be updated once in the system32 directory (perhaps through Windows Update) and our preexisting applications will be none the wiser and work just fine with the change.

This is more food for thought on the debate of static vs. dynamic linking that could help sway some developers into a different line of thought - I prefer dynamic linking, but in some cases for some applications I do not practice what I preach. For the installation folks, please read the previous link (and the comments - good stuff there on merge modules) - this is why you need to be sure that you are following proper version replacement and marking shared DLL's as shared - otherwise you can cause grief for other applications or your own.

[UPDATE: 10/4/2005 - fix formatting and errant character]

Monday, April 25, 2005

Installing an Internet Explorer ActiveX Control Part II

In part I of this article, I expressed concern over the various methods of installing an ActiveX control normally distributed and/or updated in a CAB file via Internet Explorer. This follow-up post addresses some concerns of a commenter to that last post, and describes what my solution was.

The comment made by Troy was from the perspective of a repackaging solution. Troy is quite correct - using pre and post installation snapshots will grab the changes to the ModuleUsage subkey. However, this solution fails to achieve the other goals for this particular installation. We still have the issue of a later update coupled with the MSI repair (or self-repair) operation. A point I failed to mention but Troy unintentionally reminded me of is compatibility across versions of IE. With the type of software this is, it may have a shelf life that would include IE7. Are the changes made to the system under IE6 applicable to all versions of IE under all OS's? I don't know. Using the API to install the control alleviates most (but not all) of the potential future incompatibility concerns.

I especially like how he disliked option #3 - changing the IE security settings to assure a successful installation, calling the API, and resetting them. I laughed as I wrote this option, as I could not imagine anyone doing this. In the middle of last week, I came across the "Get In the Zone" section of an issue of "Web Team Talking." They actually suggest and provide code for doing just that - although in a different context for a slightly different reason. I happen to agree with the KISS directive - "Keep it Simple, Stupid" - but sometimes to assure a successful operation you need to handle the corner cases.

The last part of his comment - "[this is] why many enterprise customers choose to repackage installations from ISVs" is a completely different blog post. I cannot tell you how true this statement is - and it is usually caused by setup developers, either intentionally or unintentionally. I'll add this one to the list of future topics for sure.

For the sake of discussion we were using the Crystal Reports Web Viewer which can generically be replaced with any properly signed cab file that works in the normal deployment mechanism of IE using the OBJECT tag. I have not tried this with unsigned controls, but I tested the approach using Macromedia's Flash player. You can play along by visiting the Macromedia's Flash download page and getting the CLSID from the OBJECT tag in the page's source. I then downloaded the swflash.cab file from the codebase attribute of the object tag and stored it on my local disk. The example below is going to use this flash cab file and the flash Class ID. Additionally, I am going to assume the reader is familiar with COM, C++, and MFC. The code is a bit lengthy to post here, but using the steps below a reasonable Windows developer should be able to complete this exercise in an hour or two.

I chose MFC since we need to implement IBindStatusCallback. This is easily accomplished by deriving a class from CCmdTarget. Make sure the implementations of QueryInterface(), AddRef(), and Release() call the External...() base class implementations. GetPriority() and OnLowResource() can simply return E_NOTIMPL. All the other methods can return S_OK. Since this is an async callback we need to have an event handle member variable, initialized in the Constructor, and have the event set in the OnObjectAvailable() method. That's the essential plumbing for the callback class. The callbacks for download progress can be implemented for the progress bars in the MSI.

Before we continue, let's make sure we have all the data we need to install the control.

  • The class id of the control is {D27CDB6E-AE6D-11cf-96B8-444553540000}. It needs to be in this format as a string (with the braces) so we can call CLSIDFromString to convert it to a CLSID type.
  • We are going to use major and minor versions of 0xFFFFFFFF to assure it is always installed.
  • Finally, we need a codebase - or place to "download" the cab file from. Since we are installing the cab file locally, the CA needs to be appropriately place in the sequence and we need to get the local path to the file. The path needs to be in appropriate format - for a local disk where the file is at C:\swflash.cab, we need to make it file://c:\\swflash.cab

The entry point code needs to hook up the plumbing - instantiate the IBindStatusCallback implementation class, call ExternalQueryInterface() on it to get the interface pointer. Then we need to create and register the binding context by calling CreateBindCtx() and RegisterBindStatusCallback().

The meat of what we are doing is a call to CoGetClassObjectFromURL() with the parameters described above. The two common returns from this call will be
MK_S_ASYNCHRONOUS, S_OK, or an error. If S_OK is returned, the object is already installed. If the async value is returned, we need to loop until the event in the callback class is set or some predefined timeout elapses. After the event is set, check to see that the object was created based on what was set in the OnObjectAvailable() method.

Based on testing, this method appears to work all of the time, regardless of the various IE security zone settings. This is likely due to using the file:// protocol. Remember that we are dealing with a signed control - with unsigned controls, your mileage may vary. This method was not tested in IE with Server 2003 in Enhanced Security Configuration, so all bets are off there as well.

If you wish to have the installation always grab the "latest" version of the code from a URL, you will need to implement the code to change and restore the IE security settings from the article linked to above and also implement the download callbacks to move the MSI progress bar. Be sure to alert the user that you will be temporarily altering the IE security settings, and make sure when handling a cancel button press from the MSI that you restore the settings. This particular corollary to the problem can be useful if you want to refresh the clients using a simple repair/maintainence/reinstall option after the server-side control was updated without having Bob the network admin do much extra work (or having to release client side patches).

Sunday, April 17, 2005

Installing an Internet Explorer ActiveX Control

This post is different from my usual posts, mainly because I have no idea what I am talking about! Well, at least I am admitting it this time!

I am tasked with creating an installation for an intranet type application. I need to create a shortcut to a URL and install a client side ActiveX control. For the sake of argument lets make it a fairly common one, such as the Crystal ActiveX viewer control. Sounds pretty simple, eh?

Let's go over a typical usage scenario. Hopefully, when designing applications and their deployment packaging you have some made-up profiles of typical users. Lets make up a few for our purposes. "Bob the system admin," "Mary the power user," and "Joe the restricted user" should be good enough. We can be a bit more specific and cover XP SP2 users, users with severely restricted ActiveX Browser settings, and non-IE browser users as well, but lets ignore these for now.

Essentially, Joe has a problem. We can give him the URL to the web application or even create a shortcut and/or favorite for him. The problem is, the first time he tries to run a Crystal Report, he gets a security warning, and the Crystal ActiveX control does not install. Of course, it is because he has no permissions to install software, even if everything else we ignored above is in good shape. Incidentally, if we can't figure out that Joe's problem is that he is a limited user, you can try the CDLLogViewer application to find out why.

Bob and Mary never have issues with the system. In fact, if Bob and/or Mary perform the same steps as Joe everything works, and Joe logs in later on, even Joe can view and print reports. The problem is that Bob and Mary would never run reports on the system. Heck, Bob doesn't even launch the application. Bob may even deploy the install package using SMS or Group Policy.

In the corporate network world, pretty much everyone is a Joe. There are a few Privileged Mary's, and even less Bob's. To make all this work, Bob needs to install applications for the likes of Joe. This behavior is not only acceptable, but practically expected.

So how would Steve, our installation guru, make all this work? He would not only need it to work, but be practically bulletproof.

Option 1: The easiest approach. 99% of the time, this is synonymous with the wrong approach. We can extract the Crystal Reports ActiveX viewer cab file, read the .inf file to figure out what it is doing, add the files to a MSI project selecting the proper registration options, create the shortcut file, and be done with the project in under 20 minutes.

Why it doesn't work: Since Joe is not the only user of the machine (remember Mary and Bob?), any updates to the control will cause the MSI-based installation to screw up at some point. If the control is updated by Mary, and Bob uninstalls the application, the component/reference count then causes havoc with Mary by possibly removing the file on uninstall. Effectively, we have precluded the normal installation/updating/removal of the ActiveX Viewer by repackaging it in an MSI. More information on the hazards of this approach can be found on MSDN in the "Registry Details" page. Bad stuff.

Option 2: Install the shortcuts as in Option 1. Call the appropriate API's to install the CAB file from the web server. In this case, (after a bit of digging through MSDN I see this process is called "Internet Component Download" or ICD for short) we need to call CoGetClassObjectFromURL.

Why it doesn't work: Referring to the ICD link above, we assume the web server is up and running at installation time - #1 in the "Download and install process". We also assume that WinVerifyTrust returns a value that is compatible with the setting for ActiveX controls for the Zone in which the server we are pulling the cab file from resides - #2 in the "Download and install process". Last, but not least, we are assuming that good old Bob didn't muck with the CODEBASE setting of the Internet Search Path.

Option 3: Completely decimate the user's machine by querying the IE Security Settings, saving them, adding the server to a trusted zone, modifying the zone parameters to set the ActiveX settings appropriately, call CoGetClassObjectFromURL, after it succeeds, set everything back to the way it was.

This seems like a heck of a lot of work, but it appears to be the only way to bulletproof an installation of an ActiveX component. Plus, we ignored several issues. If the default browser was (or will be) Firefox or even Lynx, a shortcut to this URL will always fail to display the reports. To solve this problem, an EXE wrapper would need to be written to host the IE control to assure that IE is actually the browser engine used to access the page. Joel, the API war is far from over - it just made things more complicated!

Of course, I'll get to play around with these API's and see if installing the cab file from a file:// UNC path changes anything. I'll report back what I find. If anyone else has already "solved" this problem using an approach I haven't considered, please let me know. In all likelihood, I'll end up calling CoGetClassObjectFromURL, and if it fails, try to provide some meaningful feedback to the user as to why the installation can not succeed and let Bob worry about the corner cases. After all, he ultimately created them.

UPDATE: Please see Part II of this post!

Saturday, March 12, 2005

Application Preloading at System Startup

Sometimes I wonder if we (as software developers) should have some form of a code of ethics, where violations can get you barred from writing software in the future. Mainly, this would apply to the spyware/malware developers (or perhaps the ethical violation is more directable to those who bundle the spyware).

If this ethical code existed, I would add a violation for any application that did not inform and offer a choice to the user at install time that some startup or background task will always be running. Some typical offenders are QuickTime, Real, Adobe, Microsoft Office, Microsoft Messenger, printer driver "status monitors", and more. These startup applications increase boot time and memory/pagefile requirements. Most of the time, I don't use these applications each time I boot the PC.

If the goal is to make your application start up faster (or appear to start up faster) there are ways of accomplishing this. Rebasing your DLL's, background/on demand loading of plugins, delay loading dependent DLL's, etc. are a few common tricks that can be used. The utility "Adobe Reader SpeedUp" accomplishes a magnificent improvement in load times, and this doesn't involve rewriting any of Adobe's code. If you wrote one of these startup applications anyway, at least offer the user the option at install time if they wish to use it.

Monday, November 15, 2004

Insane security

Raymond Chen posted about some questions better left unanswered because the answer is unreliable. This quote cracked me up:

"You cannot reliably reason about the security of a system from within the system itself. It's like trying to prove to yourself that you aren't insane."

Although the quote is funny, he makes several points about security that developers should heed. Commenters have taken the post a bit out of context - but the side point he makes is valid. Since most of my audience is setup/installation developers, I'll direct my comments towards that community.

The next time you are given a design document for installing a service, please make sure to ask about the security level required for the service. Make sure to raise objections to installing a service with access to the desktop without good reason (read comments to this post for more information related to the shatter attack) . Ask if LocalSystem access for the service can be reduced to a more restrictive account (HINT: There is a sample for creating user accounts within an MSI in the Platform SDK). Most of all, insist that scoping of installation/deployment design is best when it is done with the scoping of the feature or application - not after. This way, the application developer can develop in an environment closest to that which will ultimately be deployed to customers in the installation with no surprises looming at the end of a development cycle.

In case you haven't noticed, Windows XP SP2 and Windows Server 2003 have tightened up security in these areas. Instead of blindly loosening up the default restrictions this brings, take the application to the next level by understanding why the restriction is now the default in the first place, and learn how to program taking into account this more secure environment. As a setup developer, your customer is the end user. Make sure you are on the side of the customer when it comes to security.

Wednesday, September 22, 2004

Running as Non-administrator

Along with the recent security frenzy, many people have suggested running as a non-administrator on Windows 2000/XP. I attended an MSDN event for developers dealing with ASP.net several months ago, and was surprised that the presenter was running as non-admin. He also gave some great tips on how to make it easier.

First off, you should read Aaron Margosis' blog in its entirety. If you need convinced that you should run as a non-admin, start with this post. Then read all the others. They start back in June. If you already read them, skip the rest of this paragraph, as I will summarize the info you can get there. I like the "easiest way" for non-techie people. Its rather simple, but effective. Pay attention to the "update" mentioned, where he suggests making the admin desktop easily distinguished from the non-admin desktops. For the more tech-savvy, I prefer the shortcut with RunAs setup. I change the color of windows such as explorer, when running them as administrator, and suggest you do the same. Alternatively, PrivBar can be used, but I have not installed or used it myself.

Ok, so it should be about 15-20 minutes later since you read all the above stuff, right? Normal people can go off and read their next blog now after they made the necessary changes to their system - but I have a special message for you developers...

I blogged about pet peeves in installation programs and applications. Refresh your memory regarding items #20, 19, and 18. (Do you see a trend? I already covered #9 in a previous post). Hopefully you are starting to see another connection forming between non-admin users and where installations and applications put and use their files. To reinforce this connection read Larry Osterman's post from today talking about running as non-admin. This stuff is applicable to us.

Make sure your testing staff is running as non-admin to catch these issues. Not mentioned in the article is that you should make sure you are using XP Professional with NTFS disks so you can catch the strange permissions problems that can add.

Other test paths include installing the application as administrator for "all users" and logging in as a different, unprivileged user and make sure everything operates correctly. MSI Developers - don't ignore the ICE warning about mixing per-user and per-machine entries in a single component. Lastly, make sure the settings in your application are user profile aware. I recall trying to figure out how to make a media player work on my Uncle's PC with different profiles. For good reason, my uncle didn't want to share a playlist with his son - but that wasn't possible. Bye-bye old software vendor, hello new software vendor...

If you are a developer that doesn't work for Microsoft, you can go onto the next blog now, unless you are a real glutton for punishment:)

At my company, the IT department is pretty lenient to the developers. They give us admin privs to our own machines. The problem is I don't want admin privileges all the time, just when I'm doing stuff that requires it. One solution is to give me a local account admin account to use when I need to admin my box, and only normal rights at the domain level. The problem with this approach is I can't access network shares using my domain account when I am running as local admin for tasks like installing software. Having two domain accounts is a nightmare. I don't know what the solution is - perhaps a flag to make the account have normal user privs, and when administrative privileges are required have the security subsystem prompt me for explicit permission to elevate that process. I guess I'd call it the "Admin Masquerade" group for lack of a better term.

Tuesday, September 21, 2004

GDI Plus Vunerability Information for Setup Developers

Stefan Krueger from InstallSite.org has posted a very well-written article about the GDI+ vunerability and how setup developers should respond to it. Please read it ASAP, it is a great consolidation of all the available information, and should be acted upon quickly.

If you haven't subscribed to Stefan's RSS feed, here is the link. If you don't know what RSS is, try this link.

Sunday, September 19, 2004

Top 20 Installation Pet Peeves and How to Avoid Making Them

This Top-20 list of pet-peeves/annoyances is presented in no specific order and pertains to all installations, however, some items and examples directly relate to MSI based installations.

Am I missing your top pet-peeves? Are you guilty of any of the below and care to admit it? Please leave feedback in the comments!

20. Security and profile unaware installations. Can the application be installed or used by a non-administrator? Use the principle of least-privilege to ascertain what the real limitations are and make installations compliant with it. Respect user profile settings. Is the installation storing sensitive information unencrypted (such as passwords) in your log files, registry/INI files, or MSI files?

19. Installing to a location other than "Program Files" by default. This also applies to installations that assume "Program Files" is located on the C:\ drive. I recommend testing installations and applications on systems that have Windows installed to a drive other than the default C: drive with a Windows directory name other than Windows or WINNT to catch these assumptions.

18. Non-application file storing directories sharing the application directory. No application should store configuration information or user data (by default) to a directory other than the current user's documents and settings directory. Similarly, if the installation is creating a shared folder, virtual directory, or a directory that will have security implications/working data in it (such as file-sharing or database), the user should be able to select this directory separately (and it should be defaulted to a non-Program Files directory). The rationale for this is simple: Applications are restorable by reinstalling the software. User data isn't. Make it easy for the user to back up these items by default.

17. Not providing a merge module if this software will be redistributed by other vendors. I absolutely despise running an executable from my installation to install a 3rd party component. Not only do I have no idea if the sub-installation succeeded or failed, but automatic reference counting is impossible. If I repackage it, other vendors could do the same and we have out of whack component codes and keyfiles causing endless automatic repair cycles, maintenance, and removal nightmares. This also adds an easy way to assure a common method of distributing patches if the third-party software is found to have a security vulnerability.

16. Full screen installations are evil. Why does the entire screen need to be used for an install whose UI is 640x480 or less? Can't I do anything else while the install is in progress? Conversely, if the install requires a screen resolution greater than 800 x 600, my parents can't install it (or worse yet your help desk will be overwhelmed by my parents and their friends).

15. Product Serial Numbers are usually a pain. If the installation is using the Microsoft style dash separated product keys, don't also suffer from same problem that prevents a simple one step cut and paste from a registration email into the install UI. Also, try to prevent the use of commonly confused digits in the registration code, as it is font and eye-strength dependent when trying to figure out if the code is a capital O or a 0, a lower case l or a 1. If millions of codes are not needed, consider axing the U and V as well.

14. Multiple level start menu shortcuts. If a folder in the start menu only has one option in it, please do not put it into a folder. Also, make sure the folder name makes sense to the majority of end users. If I'm looking for a program "Ink Blot" am I going to think to look in the folder "Joe Schmo Software" first?

13. Unintelligent replacement of system or other redistributable files. Are you using a merge module for redistributables if one exists? Does the install check file versions/dates before replacing them? Is reference counting (shared dlls for legacy installations) being set properly? Are all required redistributables included?

12. Unnecessary Reboots. The converse is also true, where reboots are required but not asked for. Also in this category is detection of running software that makes a reboot necessary prior to running the guts of the install. Please let the user know if they can do something that will prevent a reboot at the end. If it is an older version of the installed application that is running that will require the reboot, do what is required to prevent the reboot (as long as you tell the user first). See Pet-Peeve #3.

11. Upgrades that require an uninstallation of the old version first. If this is truly required, is it being handled automatically?

10. Asking useless questions. If the installation behaves identically regardless of the install type (minimum/typical/custom) why is that dialog there? If there is a difference, is the text on that dialog accurate and/or does it make sense in the context of your application? Also in this category are error messages such as "Unable to do something important. Would you like to continue?" when "something important" is essential to the functionality of the application. This can also extend to the age-old useless "shared file no longer in use, should I delete" question.

9. Status bars that are not accurate (or present). I realize that writing status bar code is incredibly difficult. If we are talking InstallScript, VBScript, or JScript installations/actions threading is impossible, so the author can't give a moving status bar when performing a synchronous operation (like creating a database). If an alternate method is not possible, another strategy is to put a message up saying "Busy doing [something long] which may take up to 10 minutes, started at xx:xx". If you are using a C++ custom action that can be threaded to perform the synchronous action, determine the maximum time on the slowest PC meeting your system requirements and provide a time-based incrementing progress bar.

8. Allowing free-text user inputs when choices can be given. As an example, let's say the installation upgrades a database. Presenting a free-text input box for the old database name is a recipe for disaster. Instead, the install can perform a SQL query of the database server to get a list of databases. If the upgrade is applicable only to a specific type or version of database, it can then query each existing database to determine which ones the upgrade can be performed on and populate a selection list. In silent mode, any UI level checks will not be run, so validation should be performed on any command line parameters as well. See pet-peeve #1 and #6.

7. Requests for source media. If I am on my laptop (and more people are each day), and especially if I am out of the office (or a remote employee) it is practically impossible to get the source media at a moment's notice. This is especially true for installations of patches where a security vulnerability is in the wild and users need to patch immediately. Make sure nothing is being done that would prompt for source media if possible, and try to assure that the MSI and support files is going to be available by caching locally by default. Office 2003 made significant headway in this department.

6. Non-working silent installations. Make sure silent installations work properly. This includes checking properties set on the command line as you would user input in the UI, and failing with some meaningful error posted to a log if required parameters are bad or not present. Are all user interface elements able to be passed in via the command line? Failure to provide a silent installation means IT departments will grumble heavily or look for an alternative if they need to deploy your application.

5. Repair/Maintenance/Uninstallation/Rollback doesn't work. If the install is not going to provide anything useful for maintenance mode, get rid of the option. Make sure all custom setup properties are cached somewhere and pulled back in for the repair operation to succeed. Does auto-repair work correctly (delete the install directory, run from the shortcut, and see if it works)? Does an uninstallation remove everything, including cached copies of the installation? Does an error near or at the end of the installation properly rollback the changes (Throw in a deferred custom action that simply fails prior to InstallFinalize)? If altering a DB, is it being backed up before running the portions of the installation that alter it so the previous version can be restored in a failure case?

4. Assumptions that are not checked. If an installation adds a database to SQL Server 2000, is the system checked for the presence of a running SQL server before it allows the user to start the installation? Think about a system that has SQL Server installed, but the service set to disabled or is currently stopped. Similar comparisons can be made to installations that rely on web servers, messenger service, BITS, etc. If the service is not started or set to disabled, is the installation violating pet-peeve #3?

3. Modifying a system globally without asking or telling the user. This is a huge category with security implications. If the installation adds a network share or internet accessible directory, is the user being told this up-front? Take as an example the .NET framework installation. Is the user asked/told if I want ASP.NET installed to the IIS server? The answer is no. A mention of this or other types of global system changes in the documentation alone (especially since most documentation is installed with the product) is unacceptable. Note that most modern media player installations ask the user if he or she wants to associate file types with it. Installations were not always this nice to your system.

2. Not checking return codes. When running a command that is supposed to do something essential for a successful installation, does the installation check the return code and handle the error? A great example of this problem is found in many database installations, where the result of a SQL script is not checked. The application does not work after a reported "successful" installation, and it takes a tremendous amount of time and effort to determine why.

1. Not validating user input. The install allows the user to free-text something in where choices can not be predetermined (see pet-peeve #8); let's say a timeout value or something that is essential for the installation to succeed or the application to function. The user types in "10h" by accident. The install doesn't verify the input is a number or a number within a valid range. Installation fails (bad) or says it is successful, yet the application does not work (infinitely worse).

Aside from this list, a very useful document for installation (and application development)authors to follow is the "Designed for Microsoft Windows XP" Application Specifications. Many of the items listed there are also listed above.