Scott Hanselman

UrlScan and ADO.NET Data Services (Astoria)

February 10, '09 Comments [6] Posted in ASP.NET | IIS | Web Services
Sponsored By

In an ongoing series on different reasons that I suck, I wanted to share another interesting quasi-debugging story about this public ADO.NET Data Services (Astoria) service I'm trying to help get live at a large company.

I'd mentioned how I had some trouble with UrlScan and Astoria Services in my post on "RTFLF - Read the Expletive Log File."

UrlScan 3.1 is a security tool that restricts the types of HTTP requests that IIS will process. By blocking specific HTTP requests, the UrlScan 3.1 security tool helps to prevent potentially harmful requests from reaching applications on the server. UrlScan 3.1 is an update to UrlScan 2.5 supports IIS 5.1, IIS 6.0 and IIS 7.0 on Windows Vista and Windows Server 2008.

UrlScan is a really valuable tool and a really powerful way to slap down evil and attacks on your Web Server. It is VERY configurable and very powerful and takes a clear mind to make sure that all your application's URLs work well while still preventing evil. Learn how to setup UrlScan here.

When we moved the service onto a production machine, it turned out that their production UrlScan.ini was locked down more than development. They were disallowing single quotes in QueryStrings as well as Dots in Url Paths.

The trick was that they haven't partitioned their sites up by subdomain, or website, just AppDomain. This means that they have 40+ "logical sites" running under one instances of IIS6, which means that they can't setup a separate IIS site with their own configuration and instance of the UrlScan ISAPI Filter. They also didn't feel like making a separate domain or subdomain just for our one little service.

OK, blah blah blah, background, right? So where did things go wrong?

URLScan has a section in the UrlScan.ini file called [AlwaysAllowedUrls] that does just that. It allows access to any URL in that section. Adding a URL there will make UrlScan completely ignore it.

I added our service to this section like this:

[AlwaysAllowedUrls]
/foo/MyService.svc

And I thought this would work. It DID allow us to request that Url. However, no other Astoria queries worked.

When you traverse Entities in ADO.NET Data Services (Astoria), your URLs look like this, for example:

/foo/MyService.svc/Cars()
/foo/MyService.svc/Cars()$filter=((Visible%20eq%20true)

And I didn't initially see why these were being blocked.

The issue, pointed out to me by the IIS Team's Wade Hilmo (check out his blog) was obvious (hence: I suck). The URL isn't the file, it's everything before the ?. It's everything before the QueryString. This is one of those "Duh" moments, and was my bad. I know the difference, of course, and understand Urls fully, but I completely brain-farted this obvious point when looking at ADO.NET Data Service queries and had been mentally parsing them wrong for hours. Once Wade set me straight, configuring UrlScan.ini was trivial:

[AlwaysAllowedUrls]
/foo/MyService.svc/Cars()
/foo/MyService.svc/Houses()
/foo/MyService.svc/Whatevers()

In the ADO.NET Data Services parlance, the Entities exist after the .svc filename, but before the ? delimiter. Once we added those to our UrlScan.ini file, we were able to maintain the existing state of "super locked-down-ed-ness" while still allowing our services to run.

It is not possible to have a SQL Injection attack on a ADO.NET Data Service, due to the complete query rewrite that happens server side when a URL query comes into the system. The analogy is to think of in the same way that a LINQ query goes through a complete query re-write or a translation layer before it actually gets executed as SQL on the server. This re-write or translation is the layer of protection against SQL Injection attacks.

I was happy to learn that I could have my Cake ADO.NET Data Services and my UrlScan too.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. I am a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by ORCS Web
Tuesday, February 10, 2009 2:35:34 AM UTC
Thanks for sharing that Scott. We all suck at one time or another! Its only human.
Malcolm
Tuesday, February 10, 2009 5:11:19 AM UTC
Wow!!! you heard it here folks. Scott is human ;)

Don't beat yourself up so much, we all do it, we are just too chicken to write about it.
Mitch
Tuesday, February 10, 2009 8:04:49 AM UTC
Uh and what about /foo/MyService.svc/Cars(guid'c543caca-9ce0-42cd-aad6-fac9b47ad10e') ?
Tuesday, February 10, 2009 8:08:26 AM UTC
Jabe - Agreed, I realize that indexers like that don't work and for THIS client, they'd be screwed. I'm working with the UrlScan folks to see if they can fix that in the next rev. I would say that another SITE would be the best idea for this client.
Tuesday, February 10, 2009 7:23:03 PM UTC
One small comment -
Of course we design and coded ADO.NET Data Services to not allow Sql injection attacks, but with any security scenario folks should always have multiple layers of defense.

Wednesday, February 11, 2009 9:10:09 PM UTC
Shouldn't
/foo/MyService.svc/Cars()$filter=((Visible%20eq%20true)
Have a question mark and not a dollar sign?
--

Also, FYI, your OpenID implementation doesn't seem to work. I get
403 - Forbidden: Access is denied.
You do not have permission to view this directory or page using the credentials that you supplied.
My OpenID works fine in StackOverflow. Is there something else we're supposed to do you use OpenID on your site? If so, might want to make it more obvious.
Matthew Henry
Comments are closed.

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.