Monthly Archives: April 2005

You are browsing the site archives by month.

OOP and Security

A new article has been posted at http://www.codemilitia.com/blogs/tobin.titus/articles/10.aspx

(begin excerpt)

A brief discussion broke out at work today surrounding collections and how they should be exposed in a client class. The proper OO way to expose a collection as a property is to provide a get accessor only. The get accessor should most likely always return an instance. Here is an example:

public class GoodClient {
   private TrustedCollection _data = null;
   public GoodClient() {}
   public TrustedCollection Data {
      get {
         if( _data == null ) {
            _data = new TrustedCollection();
         }
         return _data;
      }
   }
}

The get accessor checks for a null private member and creates a new instance if needed. This follows good encapsulation design.

So what does this have to do with security?

Lets consider that your collection’s “Add” and “Insert” methods might do some data validation on the parameters passed to the method before adding an item to the collection. Let’s look at an example of a class that does some validation:

public class TrustedCollection : CollectionBase {
   public TrustedCollection() { }
   public virtual void Add( DateTime date ) {
      DateTime now = DateTime.Now;
      DateTime is21 = new DateTime( now.Year - 21, now.Month, now.Day );
      if( date > is21 ) {
         throw new ArgumentException(
            "The person must be 21 years old.", "date" );
      }
      List.Add( date );
   }
}

Remember, the first rule of application security is that all input is evil. If your client depends on this validation to occur, it had better not provide a set accessor. Let’s look at how we can defeat this by using an inherited class and a set accessor.

(end of excerpt)

Continue

Home Network Paranoia

Some have called me paranoid, but I have a slogan of “Friends don’t let friends use wireless networks.”  The reason for this is that wireless networks compromise the need for physical access to a network to perform any attack on the internal network. 

Well, I of course, do have exceptions to my wireless rule.  I’m planning on getting a new PDA with 802.11 capabilities, I’d like to be able to access the internet from it.  As such, I’ve decided go add a wireless router to my home network.  Before I did such, I wanted to make sure that my devices and laptop would only have access to the internet from the wireless network, and not to my internal network.  I don’t any stranger standing in the woods of my back yard able to access my TaxCut and MS Money files through a wireless hack, and considering the Feds can do it in 3 minutes now, I think my paranoia is justified. 

I’m not a network security guru. I used to be a network administrator, but that was over 6 years ago and hardware was much different then.  As such, I’m publishing my network layout and asking for comments or suggestions or holes that anyone might see. 

network

As you can see, my internet access comes in through a cable modem which connects to a VoIP-capable router (yes, I use Vonage).  The reason for using this router as my opening router is somewhat physical.  In my garage, where I terminated all of my network runs, I also terminated a cable line and phone lines at a patch panel.  Since the VoIP router also provides data ports, it’s perfect for acting as a distribution for both my planned wireless router and my 8 port routing switch.  The outgoing voice line patches into a telephone patch panel distribution that supplies the house telephone runs.  The 8 port router serves as the first layer of defense for my data network It then provides access to the whole house through the patch panel distribution point where I ran all of my data lines to. (I luckily got to do all my own structured wiring while the house was being built).

Its important to note that I do not allow access from the wireless network across the internal side of the VoIP router, and I again block packets originating from the wireless router at the 8 port.  The 8 port router and the VoIP router does, however have some rules for open ports that my wife needs to play games, and that I need for various services I have running on my internal network.  Because of this, I’ve added another Cisco PIX firewall in my upstairs office to prevent any inbound requests to my file server, my development PC, and of course the computer I use for family record keeping. The file server is behind the firewall, but I have rules set up to allow access to it from the other house PC’s.

In any case, as I look at my network, I start to realize how imperfect it is.  I’m looking for advice from anyone on how to make it more secure but still provide the needed functionality to our standard home PC’s and to our private personal-data machines.

ASP.NET 2.0 Quickstarts Available

For those of you that don’t know, the ASP.NET 2.0 SDK quickstarts are available.  Obviously, these are just an overview, but it helps to get yourself up and running fairly quickly with features new and old.

Check them out at http://quickstarts.asp.net/QuickStartv20

File uploading in a web environment

A recent question was asked on the ASP.NET forums:

“i’m building a page to let people upload images to my site. they are supposed to see the images after uploading them.
i wondered if somebody can take ane “exe” file, change the extension to “jpg”, upload it, and then run it by pressing the “view picture” button. will my server run this exe file? if yes, how can i check if it image (“jpg” and “gif”) or something else?
great thanks…”

The question actually encompasses a very frequent request that users have. The fact that someone knew to ask about this before just implementing the upload feature proves that the mentality toward securing applications has been changed slightly from “Lets implement as many features as we can” to “How will implementing this feature affect the security of my application”.  This mentality, I feel, is spurred by several factors such as Microsoft’s increased Trustworthy Compupting initiative.

Since I feel its good to reward people for thinking about security first, I will do my best to answer this question for the user here on my blog. In the next few days, I will be launching a series of posts relating to uploading files in a web environment, the security issues, and better ways to implement the feature.  I’ll start by defining the functionality that is ultimately wanted, provide some insight into the various ways to implement this functionality and the security issues surrounding each approach, and then move on to designing a solution and perhaps even provide some sample code.

For now, let’s focus on the functionality and delve a bit into some various ways to implement this feature.

In general, the developer wants users to be able to upload image files to a website, and let someone or several people view the images after they are uploaded. This feature is implemented in the very software that is used to run this blog — Community Server.  Over the years, this feature has been implemented in more ways than I care to count.  Some folks store the uploaded file as is to the file system.  Others have stored the binary data as a BLOB in a database.  Others have used hybrids of this mechanism.  For this portion of the article, we will focus on a file-based approach and follow up with a database approach.

Storing in the File System

The most logical way to store files, it would seem, is in a file system.  From a public internet standpoint, however, one has to consider the trade offs of this approach.  The first problem is that your web user account (most likely the ASPNET account) has to have permission to write to the file system in order to pull this off.  The second issue is that if you write to a file within the scope of your web’s root folder, those files can most likely be accessed through IIS as well (and since this particular user desires for the images to be available to the public, they almost have to be available).  The security concerns are massive.  A user could upload a web-executable script to the server that they could then use as a trojan to gain access to the rest of the server. More advanced hacks could be used to compromise memory buffers and cause an executable to run in the server process (one of the main resons behind the new aspnet_wp running under the context of a low-privileged user).  There are some ways to decrease the risk involved in this method, however.  Some of them involve security through obscurity (not sufficient by itself).  Some of them involve coupling the best of OS security, web security and application security. 

Directory Structure

For starters, consider the fact that you do not want any files that are uploaded to be scriptable on the server side.  So lets set up a directory structure and security for our saved files. Start by creating your main upload directory outside of the web root.  For example, if your web root is found at C:inetpubwwwroot , create your image directory at C:inetpubuploadroot.  So why did we do this?  This prevents anyone from uploading malicious scriptable code to your server that can be executed on the server.  Once you create your directory, make sure you grant read and write permission to ASPNET user (if you are not using impersonation)  or to the Groups and Users which you will allow to upload files.  In my case, I granted the following permissions:

Administrators      Full Control
ASPNET             List Folder Contents, Read, Write
Network Service  List Folder Contents, Read, Write
System                 Full Control

Uploading your File

Once you have set up your directory structure, you’ll need to create your upload page. You only need an HTML file control and a submit button. Once you add your HTML controls, make sure you run them at the server side.

screenshot

Once you’ve set up the page, add the following code to save the file:

private void btnSubmit_Click(object sender, System.EventArgs e) {
 HttpPostedFile file = fleUpload.PostedFile;
 if( file != null ) {
     string serverFilePath = String.Format(   
        @"C:domainstitus.touploadroot{0}",
        file.FileName.Substring( 
        file.FileName.LastIndexOf(@"") ) ); 
        // TODO: Write file validation routine.
        if( ValidateIsJpeg( file ) ) {
           file.SaveAs( serverFilePath );
        }
  }
}

Validating The File

This get’s the job done for uploading, but it still isn’t secure and we haven’t given the user any way to retreive the file.  Now, I’m not an expert in image file types, but I know that each has a format.  I would HIGHLY recommend that you learn the proper methods to validate each file type you intend to accept and write a routine to test the uploaded file against the expected format.  For JPEG files, you can read an online FAQ at http://www.faqs.org/faqs/jpeg-faq/ that will explain the format and give you clues on how to validate this file.   Remember that ALL INPUT IS EVIL and with file uploading, this is particularly important.  However, I’ll leave this implementation up to you since this can get rather complex and will change based on each file type you want to accept. 

In Part #2, we’ll discuss how to retreive images that are stored on the file server using an HttpHandler.

Minutemen Incident — So funny!

msn.com is still set as my home page. This morning there was an article posted that had me chuckling to myself because of the picture at the top of the article.  It was a picture of an ILLEGAL IMIGRANT holding up a T-Shirt. I will never call these people “undocumented workers” so people can help you forget the first thing they do is disrespect our country by breaking the law to get here and disrespecting the many people who stand in line to come here the legal way.

In any case, the funny part was what the T-Shirt said:  “Bryan Barton caught an illegal alien and all I got was this lousy T-shirt.”

I don’t know why it made me laugh so much, but I thought I would share it.

Forms Authentication Cookies in the QueryString

Most folks don’t like their authentication data appearing in the query string, and with good reason. However, one does have to consider some trade offs when enabling cookieless sessions.

A user recently posted the following in an ASP.NET security forum.:

I use Forms Authentication technique in my Web application interactive with mobile devices. The configuration is like the following:

 < authentication mode="Forms" >
   < forms loginUrl="login.aspx" timeout="30" protection="All" path="/" />
 </ authentication >
 < authorization >
   < deny users="?" />
 < /authorization >
 < sessionState mode="InProc" 
      stateConnectionString="tcpip=127.0.0.1:42424" 
      sqlConnectionString="data source=127.0.0.1;Trusted_Connection=yes" 
      cookieless="true" timeout="20" />

Mangled URLs are used during sessions due to the cookieless=true setting. But why is the authentication cookie (in my case, its name is ASPXAUTH) also carried in the URIs? I know that this cookies is needed to be present in HTTP headers, but what configuration has defined this cookie is embedded in the query string of the URL like this?

http://localhost/myapp/(wcaz3svlxsdfinygyttuiu45)/default.aspx?__ufps=594900&.ASPXAUTH=887134660EC8D9CE8D72

The answer is simple but again requires you to consider the trade-offs when using cookieless sessions. This behavior is largely in part because the SessionStateModule class writes data to the cookies collection using HttpRequest.AddResponseCookie()

The AddResponseCookie() method looks to see if the cookie collection is null (and it will be if you are using cookieless sessions). If it is null, it will then append the asp.net auth cookie to an internal HttpValueCollection. These values are then written to the QueryString when the handler writes the response back to the user.

The fact that this is an cookie doesn’t go away because it’s a “special cookie”. In fact, what good would your cookie do if it was, in fact, written back in the header? The whole reason behind cookieless sessions is to allow sites to work that don’t support client-side cookies. If someone didn’t support cookies, and your authentication cookie was written back in the header instead of the QueryString, your cookie-based forms authentication cookie wouldn’t work either.

Keep this in mind when enabling cookieless sessions and forms authentication together.

String.Format vs StringBuilder.AppendFormat

So here’s a question, what’s the difference between String.Format( string, object[]) and StringBuilder.AppendFormat( string, object[] ) ?

For those of you thate don’t know, String.Format allows you to parameterize your strings, by placing replacement tokens througout a string template.  You can later fill in those tokens with parameterized data by passing it in as an array. Here is an example:

string.Format("I own a {0} and {1} name is '{2}'", 
        "cat", "her", "Ellie" );

Of course this would output the sentence: “I own a cat and her name is ‘Ellie'”.  You can also achieve the same thing by calling StringBuilder.AppendFormat much like the following example:

StringBuilder sb = new StringBuilder();
sb.AppendFormat( "I own a {0} and {1} name is {2}", 
        "cat", "her", "Ellie" );

At first glance, you may be thinking that these are somewhat interchangable with the exception of performance. By now, we all know StringBuilder is usually faster for excessive string manipulation. What you may not know is that string.format calls the StringBuilder.AppendFormat method under the hood.  Additionally, StringBuilder will throw an exception if the number of parameters does not match the number of tokens found in the template string.  Try compiling and running a program that executes the following statement:

[STAThread]
static void Main(string[] args) {
  string x = string.Format(
    "{4} owns a {0} and {1} name is {2}.", "cat", "her", "Ellie" ); 
  Console.WriteLine( x );
  // For those of you that know WriteLine takes format strings... shhhhh
  // I'm trying to make a point here!
}

You will receive the following exception.

An unhandled exception of type 'System.FormatException' 
occurred in mscorlib.dll

Additional information: Index (zero based) must be greater 
than or equal to zero and less than the size of the argument 
list.

This exception is actually thrown by StringBuilder.AppendFormat and the String.Format method bubbles the exception up without providing the consumer with any recourse if the parameters dont’ match up.  However, if you call StringBuilder.AppendFormat yourself, you can place the code in a try catch block, and reap the benefits of a string that has been formatted as best as it can be with the parameters provided. Take the following code, for instance:

[STAThread]
static void Main(string[] args) { 
  StringBuilder sb = new StringBuilder();
  try {
    sb.AppendFormat( "{0} owns a {1} and {2} name is {3}.",
        new object[] {"Tobin", "cat", "her"} );
  }
  catch(FormatException ex) {
    Console.WriteLine("An exception occurred: {0}", ex.Message ); 
  }
  finally { 
    Console.WriteLine( sb.ToString() ); 
  } 
  Console.ReadLine();
}

Notice here that we have caught the exception, reported on it, but can still write the string builder’s text to the screen — or at least the part that was parsed.

Now here’s the questions I pose for all of you:

  1. Since you now know that you can bypass the token-count to parameter-count validation check by using StringBuilder, should you incorporate this into your applications in instances where you don’t know how many parameters you are going to have?
  2. Would you consider this to be a bug, or a reasonable feature and why?

Post Navigation