Friday, 19 March 2010

Development: Common MOSS coding issues based on MS recommendations

Hi All,

Whilst browsing Sample code acceptance checklist for IT organizations on Technet, I realised that in several places we as an organisation were not always following best practises. As stated in this article, this probably means that we could do a few things to improve the performance and security of our product - and who doesn't want to write faster, safer code?

Here are the items that rang alarm bells and I thought it might be worth sharing them in case anyone else still has a few BP boxes to check:
  1. Plain text passwords are not present in Web.config, Machine.config, or any files that contain configuration settings. Utilities such as Aspnet_setreg.exe and Trustee or the identity setting in AppPool on IIS 6.0 or IIS 7.0 are used to encrypt credentials.

    This often seems to slip through the net, reason being that administrators tend to think "Users can't get on our servers so what's the point?". The point, I think is that we as developers should always try to implement defence in depth security practises and this is a good example. OK - if an attacker somehow obtains RDP access to your server farm a plain text password for a Web application may well be the least of your worries but this is not a tricky one to fix. Grab Aspnet_setreg.exe and get to work!

  2. If cookies contain sensitive data, they are marked secure.

    The severity of missing this item depends on the sensitivity of your application and your supporting infrastructure. If your data must be secure during transit, then you need to either ensure that all cookies are marked secure, or you must ensure the channel is encrypted via some other means. Options that spring to mind are forcing this via IIS (straightforward in version 6.0 and later) and / or forcing an SSL redirect via a reverse proxy server such as ISA Server 2006. In our case, we implemented the last 2 options which ticked the corporate security check box when we conducted an external security review recently.

  3. Input surfaces in Web parts and other customizations include boundary checks, input data integrity checks, and appropriate exception handling to protect from cross-site scripting and SQL injection.

    OK, XSS and SQL injection are both well known security problems in Web applications. However, its always worth bearing these two common issues in mind and applying protective measures such restricting input (must be server side - think regular expressions) and using parametrised stored procedures. See How To: Protect From SQL Injection in ASP.NET for more info.

  4. You avoid using AllowUnsafeUpdates. You use ValidateFormDigest() and, if necessary, use elevated privileges to interact with SharePoint objects. In cases where AllowUnsafeUpdates must be used, you ensure that AllowUnsafeUpdates is set to False in your try-catch-finally block, or you use a Dispose() method (as required by the IDisposable interface) to avoid security issues.

    In the SharePoint development world, I believe it is relatively common knowledge that using AllowUnsafeUpdates liberally is a big no-no. However, there are places where it is unavoidable (sometimes whilst using SPLimitedWebPartManager) so ensure you utilise that finally block.

  5. The ASP.NET validateRequest option is enabled, if possible.

    Based on my experience, this appears to be a favourite item for penetration testers to pick on whilst testing ASP.NET forms applications. Enabling this option is a step toward preventing XSS (see How To: Prevent Cross-Site Scripting in ASP.NET).

  6. The application consistently uses standardized input validation such as RegEx throughout.

    I would like to confidently tell you that this requirement is a given and that I haven't come across an example where standardised input validation is neglected in recent years. However, that is simply not the case and I would encourage you to rigorously check and confirm that your ASP.NET controls are all validated using a white list input validation approach.

  7. The application uses a standardized approach to structured error and exception handling throughout.
    1. The code uses exception handling. The code catches only the exceptions that you know about. For example, do not use try{} catch(Exception ex){}unless you throw the error again.

      1. I think that although many organisations do use a standardised approach to error and exception handling, it is sometimes an approach that is consistently wrong. For example, I have been guilty of doing this in the past:

        catch (Exception ex)
        throw (ex); // do NOT do this!

        1. (this lesson here is that if you want to re-throw the exception currently handled by a parameter-less catch clause, use the throw statement without arguments see here)

          The main point here is that you should review your code and ensure that your exception handling procedure is both consistent and follows best practises.

  8. Application errors do not contain sensitive information or information that could be used to exploit the fault.

    Quite often, this is viewed as a negative point as far as the end user experience is concerned. If a user fails to logon, they often want to know why they can't logon. As always, the problem here is striking a balance between usability and security. We want to help the user out by providing useful error messages, we really do. But we also want to prevent unauthorised access to your application and that has to take priority.

    Throw generic error messages on-screen, but make sure you log as much detail about the error as possible to the log. Use proper exception handling to ensure the stack trace isn't lost.

  9. Customizations are accompanied by a list of all dependencies. This could include account/passwords, Web services, databases, other solutions or Features, patches, tool sets or libraries, and other dependencies.

    This might appear to be a relatively obvious point but I'm often surprised at how much information is retained in a developers head rather than correctly documented. The acid test is ensuring that someone outside of the development team can deploy the customisation without any issues.

  10. When using the Count property of a SPListItemCollection, you only call it once and then store it in a variable that you can refer to when looping. You do not call it inside a loop.

    I think this one speaks for itself, although this was a recent revelation for me.
I think that just about covers it. Please let me know if these items rang any alarm bells or if you have any comments.

Cheers, Ben.

Subscribe to the RSS feed

Follow me on Twitter

Follow my Networked Blog on

Wednesday, 17 March 2010

Administration: Changing a MOSS Site's Application Pool


Whilst developing a new version of our MOSS based product, we decided that we would like to isolate new sites by placing them in a brand new IIS 6.0 application pool. The idea behind this was to prevent issues on the new sites affecting clients on the old (stable) version of our product by running them in a new worker process.

While it would have been easy to opt to create a new Web application in our new application pool, we were faced with the problem of modifying an existing MOSS site to use a newly created pool. Note that I am not talking about change the identity of the application pool - this has already been documented on sites such as Eli Robillard's "World of Blog" - thanks Eli for the info.

When a member of our development team first asked me how to go about doing this, I incorrectly assumed that this would be as straightforward as going into IIS and modifying the properties of the MOSS Web site, having configured the appropriate SQL and group permissions (details of which are documented on technet).

However, having attempted this in our pre-production environment I can safely say this was simply not the case. Whatever I tried, SharePoint refused to allow me access to the site and greeted me with the standard MOSS access denied page. Taking a look online using a popular search engine, I found others had encounters similar issues but (as far as I could tell) had not come up with a solution.


The fix? In the end I simply had to delete and recreate the Web application. I created the process below which I hope others will find useful. Before you begin:
  1. Backup your farm (i.e. full SQL backup)
  2. Backup IIS on all WFE servers
  3. Backup the web.config of the site you wish to modify the application pool for
  4. Create the new application pool and document the new identity (service account) used
  5. Document any custom Web parts that are deployed to the Web application
  6. Document regional settings - e.g. time zone
  7. Document authentication settings (e.g. Basic, Integrated)
As always, you should always test these steps in your own environment before using them in a real-world scenario:

1. Delete Web application in SharePoint Central Administration - do NOT delete the content database or IIS Web site just yet.

2. Delete IIS Web site

3. Create new Web application with new IIS site (making sure to select your brand new application pool) & note down default content DB name (to be deleted)

4. Perform an “IISreset /noforce”

5. Reconfigure your IIS settings (e.g. authentication providers, SSL certificate, host header bindings, home directory, logging, virtual directories)

5. Remove automatically created content db in SharePoint Central Administration

6. Confirm DB create date and delete temporary content db in SQL Server management studio.

7. Rename & Reattach correct content DB and confirm no. sites > 0 (could have attached the wrong content DB – minimal chance as I have checked all portal URLs)

8. Restore web.config (as SharePoint overwrites it upon creating a new Web application - you backed it up right?)

9. Add policy for web application if applicable

10. Redeploy web parts to all restored web applications if applicable

11. Set authentication providers

12. Set general settings (timezone) for restored web application

13. Set People picker settings for restored web application using STSADM

I think it's worth stating again that you should attempt these steps yourself in a test environment before attempting them on your production servers.

Feel free to let me know if you encounter any issues or whether these steps worked for you.

Cheers, Ben.

Subscribe to the RSS feed

Follow me on Twitter

Follow my Networked Blog on