Scott Hanselman

New Outlook VSTO AddIn: How to disable Reply To All and Forward in Outlook 2007

August 22, 2008 Comment on this post [6] Posted in Source Code | Tools
Sponsored By

2010 UPDATE: Gavin has released an updated version of his No Reply To All Add-In on the Microsoft Research Site. Go get it free!

Last October I posted a Macro-quasi-hack to Disable Reply To All and Forward in Outlook within your own company network. The technique uses a macro to flip a metadata bit in a message.

Of course the only REAL way truly to disable Reply to All and Forward is to use IRM (Intellectual Rights Management) in Outlook 2003/7. However, this technique was useful to a lot of people as it is super simple and can stop those "knee-jerk" Reply to Alls.

Anyway, after this post Gavin Smyth of Microsoft Research emailed me and said:

"However, it's still such a useful idea that I finally got round to writing a C# addin to do it (vaaaassst overkill, I know, but it was easy) - toggle buttons (one for reply, one for forward) on the ribbon that set the two flags appropriately."

Cool. He's written his first Visual Studio Tools for Office (VSTO) AddIn, and it's a good tutorial on how to write one!

image The general idea os:

  • Start with the VS Outlook Add-In project wizard
  • Add the ribbon group & buttons
  • Create click event handlers for both, replicating what was in your my blog posting

Poof. Package and Deploy. It's really obscenely easy. Actually, way easier than the macro way I did it.

Now my Messages have these nice shiny new icons:

NoReplyButtons 

The source is trivial:

using System;
using Microsoft.Office.Tools.Ribbon;
using Outlook = Microsoft.Office.Interop.Outlook;
using Office = Microsoft.Office.Core;

namespace NoReplyAllAddin
{
public partial class Ribbon : OfficeRibbon
{
public Ribbon() { InitializeComponent(); }

private bool SetActionFromButton( object sender, object context, string action )
{
bool oldValue = false;
Outlook.Inspector inspector = context as Outlook.Inspector;
if( inspector != null )
{
Outlook.MailItem msg = inspector.CurrentItem as Outlook.MailItem;
if( msg != null )
{
oldValue = msg.Actions[ action ].Enabled;
RibbonToggleButton btn = (RibbonToggleButton)sender;
msg.Actions[ action ].Enabled = !btn.Checked;
}
}
return oldValue;
}

private void OnClickNoReplyAll( object sender, RibbonControlEventArgs e )
{
SetActionFromButton( sender, e.Control.Context, "Reply to All" );
}

private void OnClickNoForward( object sender, RibbonControlEventArgs e )
{
SetActionFromButton( sender, e.Control.Context, "Forward" );
}
}
}

You can download the setup and/or the source for Gavin's "No Reply for Outlook 2007"  over at his Software Utilities site. Thanks to Gavin!

About Scott

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

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

The Weekly Source Code 32- Atom, AtomPub and BlogSvc, an AtomPub Server in WCF

August 21, 2008 Comment on this post [7] Posted in ASP.NET | Source Code | Web Services | Windows Client | WPF | XML
Sponsored By

In my new ongoing quest to read source code to be a better developer, Dear Reader, I present to you thirty-second in a infinite number of posts of "The Weekly Source Code."

UPDATE: The BlogSvc.NET code has been refactored considerably, so consider checking out the Recent CheckIns to see what's changed..

BlogSvcBlogSvc.NET - The AtomPub Server for WCF and .NET

Much respect to people who not only release Open Source Software, but also take the time to get a nice, clean logo for their project as BlogSvc.NET did. It's written by Jarrett Vance and the code is up on CodePlex with Documentation and details on the main BlogSvc.NET site.

It also appears that the site at http://www.blogsvc.net is also the Demo Site for BlogSvc itself! Actually, if you download the source, you're downloading the complete implementation of the BlogSvc.net website. Booyachaka. Much respect.

Since the project uses Atom and AtomPub he can work against it using Windows Live Writer. You can learn all about how WLW likes Atom by reading the series of posts the most excellent Joe Cheng of the Live Writer team did on how this is all implemented.

Made it this far and wondering what the heck it all means? Let us turn to Wikipedia who gets it mostly right this time.

The name Atom applies to a pair of related standards. The Atom Syndication Format is an XML language used for web feeds, while the Atom Publishing Protocol (short AtomPub or APP) is a simple HTTP-based protocol for creating and updating web resources.

One way to look at it is that RSS is as a syndication format that looked like XML, but didn't really respect XML at its heart. Atom does. For publishing to blogs or content sites, the Blogger/MetaWeblog APIs are based on XML/RPC (a protocol that you either love or it makes you ill. Or both) while AtomPub is based on the RESTmodel and Atom and went through a more Standardsy adoption process. Ultimately it's a safe bet to use Atom and/or AtomPub. Everyone's pretty much on board. Microsoft got on board earlier this year. My hero Pablo Castro, the Principal Architect of ADO Data Services is supporting AtomPub in his project.

That said, BlogSvc is:

"...an open source implementation of the Atom Publishing Protocol. It is built on top of a provider model. There are providers for the file system and databases. The service is compatible with Live Writer."

Enough chatter, let's see some code. It's 0.3, but it's marching right along. When Jarrett starts using .NET 3.5 SP1, he'll likely get to do some "coding via subtraction" and swap out a lot of the boring Atom Object Model code with the new System.ServiceModel.Syndication and use the ServiceDocument. Jarreyy might be able to remove most of his "BlogService.Core" project. The new 3.5 SP1 stuff includes Atom and AtomPub object models as well as an Rss20 object model. It'll be interesting to see if those new object models can stand up against Argotic.

He's got a pretty comprehensive IAtomPub namespace with the UriTemplates that correspond to the "tag" URI Scheme from RFC 4151 that he's complying with.

[ServiceContract]
public interface IAtomPub
{
[OperationContract]
[WebInvoke(BodyStyle = WebMessageBodyStyle.Bare, UriTemplate = "{workspaceName}/{collectionName}")]
Stream CreateResource(string workspaceName, string collectionName, Stream stream);

[OperationContract]
[WebInvoke(BodyStyle = WebMessageBodyStyle.Bare, UriTemplate = "{workspaceName}/{collectionName}/*")]
Stream Annotate(string workspaceName, string collectionName, Stream stream);

[OperationContract]
[WebGet(UriTemplate = "{workspaceName}/{collectionName}/*")]
Stream RetrieveResource(string workspaceName, string collectionName);

[OperationContract]
[WebInvoke(BodyStyle = WebMessageBodyStyle.Bare, UriTemplate = "{workspaceName}/{collectionName}/*", Method = "PUT")]
Stream UpdateResource(string workspaceName, string collectionName, Stream stream);

[OperationContract]
[WebInvoke(UriTemplate = "{workspaceName}/{collectionName}/*", Method = "DELETE")]
void DeleteResource(string workspaceName, string collectionName);

[OperationContract]
[WebInvoke(UriTemplate = "{workspaceName}/{collectionName}/*", Method = "HEAD")]
void HeadResource(string workspaceName, string collectionName);

[OperationContract]
[WebGet(UriTemplate = "service")]
AppService RetrieveService();

[OperationContract]
[WebInvoke(BodyStyle = WebMessageBodyStyle.Bare, UriTemplate = "service", Method = "PUT")]
AppService UpdateService(AppService serviceDoc);

[OperationContract]
[WebGet(UriTemplate = "{workspaceName}/{collectionName}/category?scheme={scheme}")]
AppCategories RetrieveCategories(string workspaceName, string collectionName, string scheme);

[OperationContract]
[WebGet(UriTemplate = "{workspaceName}/{collectionName}")]
AtomFeed RetrieveFeed(string workspaceName, string collectionName);
}

Now, let's look at CreateMedia which would be called as a part of CreateResource for any type of data that's not an Atom content type. CreateMedia is the kind of thing you'd want to do if you were attaching a picture or a video to your blog post.

public AtomEntry CreateMedia(string workspace, string collection, Stream stream)
{
try
{
if (!Authenticate(true)) return null;
string slug = WebOperationContext.Current.IncomingRequest.Headers["Slug"];
string contentType = WebOperationContext.Current.IncomingRequest.ContentType;
string etag;
AtomEntry entry = Atom.Provider.GetService().GetCollection(workspace, collection).CreateMedia(stream, slug, contentType, out etag);
WebOperationContext.Current.OutgoingResponse.ContentType = Atom.ContentTypeEntry;
WebOperationContext.Current.OutgoingResponse.Headers["Content-Location"] = entry.Location.AbsoluteUri;
WebOperationContext.Current.OutgoingResponse.ETag = etag;
WebOperationContext.Current.OutgoingResponse.SetStatusAsCreated(entry.Location);
return entry;
}
catch (ResourceNotFoundException rnfe)
{
WebOperationContext.Current.OutgoingResponse.SetStatusAsNotFound(rnfe.Message);
}
catch (InvalidContentTypeException icte)
{
WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.NotAcceptable;
WebOperationContext.Current.OutgoingResponse.StatusDescription = icte.Message;
}
catch (Exception ex)
{
WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.InternalServerError;
WebOperationContext.Current.OutgoingResponse.StatusDescription = ex.Message;
}
return null;
}

Personally I'd have done a little refactoring in and pulled out WebOperationContext.Current.OutgoingResponse into a variable, but you get the idea. I think there's some more opportunity for some larger, more profound refactorings as this method looks a lot like most of the others. CRUD (Create, Read, Update, Delete) code does tend to repeat.

I think Jarrett will be able to move all the try/catch and the caching work for eTags and what not into some helpers. The project site says the next step is to add some authentication and have that factored out into a module, and that's confirmed by his copious TODO comments.

I really enjoy reading code where someone, like Jarrett, has taken the time to actually put in TODO: comments. It's easier to get into the programmers head if you know where they are going, and TODOs also tell you where they've been. I can tell when I'm reading this that the project owner knows what's good and what's not, and from that, gauge the trajectory of the project.

image

Great stuff and I hope that we see more work like this in the .NET Open Source space around Atom and AtomPub. Why should you care? Perhaps you work for a company that has a content management system, or a sales catalog system where sales people want to edit project web pages. Why not put something like BlogSvc in front of it and let your sales folk use Windows Live Writer or some other AtomPub compliant editor? The possibilities are really endless.

WEIRD SIDE NOTE: I had a weird COM Interop Error when opening his "Web.csproj" - I'd get "System.Runtime.InteropServices.COMException." I opened the csproj in notepad and noticed two things. First, the IISUrl was set to his computer name, http://rocket, so I changed that to http://localhost. The other was that it said UseIIS="True" so I suspect that was a lame error message trying to tell me that I didn't have the IIS 6.0 compatibility extensions on my Vista system. I set it to UseIIS="False" and the project loaded fine.
CONFIRMED: I ran into this bug on Connect and I shall now yell about it internally.

It'll be interesting to see how BlogSvc and ADO Data Services in 3.5 SP1 intersect. BTW: You can learn more about ADO Data Services by watching the How Do I videos on MSDN. (Yes, the video player sucks, but you can download the WMVs.)

Technorati Tags: ,,

About Scott

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

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

Hanselminutes Podcast 126 - Chat with John Resig, Creator of jQuery

August 16, 2008 Comment on this post [9] Posted in ASP.NET | Javascript | Podcast
Sponsored By

image My one-hundred-and-twenty-sixth podcast is up. I got to talk to John Resig the creator of jQuery. We talk about about how he developed jQuery, how it performs, and where he thinks it's headed.

Subscribe: Subscribe to Hanselminutes Subscribe to my Podcast in iTunes

If you have trouble downloading, or your download is slow, do try the torrent with µtorrent or another BitTorrent Downloader.

Do also remember the complete archives are always up and they have PDF Transcripts, a little known feature that show up a few weeks after each show.

Telerik is our sponsor for this show.

Telerik's new stuff is pretty sweet, check out the ONLINE DEMO of their new ASP.NET AJAX suite. RadGrid handles sorting, filtering, and paging of hundreds of thousands of records in milliseconds, and the RadEditor loads up to 4 times faster and the navigation controls now support binding to web services on the client.

As I've said before this show comes to you with the audio expertise and stewardship of Carl Franklin. The name comes from Travis Illig, but the goal of the show is simple. Avoid wasting the listener's time. (and make the commute less boring)

Enjoy. Who knows what'll happen in the next show?

About Scott

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

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

Hidden Gems - Not the same old 3.5 SP1 post

August 14, 2008 Comment on this post [32] Posted in ASP.NET | ASP.NET Dynamic Data | ASP.NET MVC | Windows Client | WPF
Sponsored By

Folks were hassling me in the comments for not posting the picosecond that .NET 3.5 SP1 came out (or, as I like to call it, .NET 3.6 - although the bosses really don't like that).

First, the obvious stuff.

Should I fear this release?

I wouldn't. The SP1 Framework is full of goodness. The VS Installer is slow (it was for me) but I just shut everything down, ran it, and was patient. It's POSSIBLE. It's way better than the beta installer was. There's a metric buttload of little VS fixes and tweaks that make the IDE a more pleasant place to spend your day. ScottGu lists a bunch of new stuff, like JavaScript intellisense, formatting, editor performance improvements, and on and on.

If you want to see some crazy interesting statistics, go check out Patrick Smacchia's updated 3.5 SP1 Changes Overview.

You can get it here:

If you've ever installed anything wacky or beta, be sure to run the important Preparation Tool and also R'ingT*M.

Now, why should I bother?

What's it got for ASP.NET?

There are lots of details here http://www.asp.net/downloads/3.5-sp1 including stuff on things we used to call ASP.NET 3.5 Extensions (in case you were wondering where all that went.)

ASP.NET Dynamic Data: This is now included in the .NET Framework 3.5 Service Pack 1 release. You can find further information on ASP.NET Dynamic Data here as well as instructions on how to convert applications written using the ASP.NET 3.5 Extensions December 2007 CTP in the readme. Piles of Dynamic Data videos here.

ASP.NET MVC: Nope! MVC has always been a separate release. Check out Phil Haack's blog for details!

ASP.NET AJAX browser history: This is now included in the .NET Framework 3.5 Service Pack 1 release. You can find details of how to convert applications written using the ASP.NET 3.5 Extensions December 2007 CTP in the readme. Check out the Video on AJAX Browser History.

ADO Data Services - It's RESTful! RESTy! A POX on your data! It's AtomPubtastic. Go check out Pablo's most excellent ADO.NET Data Services ("Project Astoria") videos from Mix.

ADO.NET Entity Framework: The ADO.NET Entity Framework is now included in the .NET Framework 3.5 Service Pack 1 release. You can find the documentation for the ADO.NET Entity Framework here. There's also an EntityDataSource.

ASP.NET controls for Silverlight: These ASP.NET Web server controls make it easier to use Silverlight in ASP.NET Web applications. These controls are now included in the Microsoft Silverlight 2 Software Development Kit.

Not to mention other new features like AJAX Script Combining (check the AJAX Script Combining video by Bertrand) and find out "What's the big deal with Script Combining?"

What's it got for Fat Chubby Smart Rubenesque Clients?

Bunch of new SP1 stuff on the client side, and I fully intend to have BabySmash exploit the new stuff as much as possible.

One of the cooler things is the new 3.5 Client Profile bootstrapper. This means I can get a Windows XP SP2 machine with no .NET Framework installed up and running with the 3.5 Client (WinForms, WPF, etc) assemblies in just 26megs with a 200k bootstrapper. I'm going to blog on how to do this, and use BabySmash as a guinea pig soon.

  • Immediate Responsiveness: Bootstrapper is small (200K) to enable the fastest possible response. After the security prompts, the user immediately is presented with the EULA.
  • 3 Clicks: One for the application, installing certificates, and the EULA. For ClickOnce, the user clicks accept on the EULA and the application automatically launches once setup is complete.
  • Size and Speed: With a typical broadband connection, setup will take ~6 minutes or less.
  • Faster launch time: Bunch of NGen and memory layout and CLR improvements.
  • FireFox ClickOnce and XBAP support. Finally!

What about ASP.NET MVC?

There is likely some confusion around MVC as a few people expected ASP.NET MVC to ship in SP1. This is probably because MVC was included in 3.5 "Extensions Preview." However, the plan was always to ship in Q4CY08.

(That date is marketing speak, I've just learned. I tell people what Eilon told me - it'll ship in a month ending in "-ber." Possible "March-ber" but also maybe "next June-ber.")

Anyway, Phil has always said that MVC is on its own schedule and will ship when its done. Possibly when Duke Nukem Forever ships.

What else is new? What about ASP.NET itself?

Here's the unsung heroes. Scott Galloway and the ASP.NET will do some articles in exquisite (I hope) detail on http://www.asp.net soon on all the subtle good fixes in ASP.NET, so watch for those.

Here's some details on a few niceties for people who like their URLs and Forms a certain way.

  • RenderAllHiddenFieldsAtTopOfForm - In versions of ASP.NET earlier than the .NET Framework 3.5 SP1, ASP.NET renders some hidden fields (for example, __VIEWSTATE) at the top of the form. Other hidden fields (for example, __EVENTVALIDATION) are rendered near the bottom of the form, just before the closing </div> tag. By default, in ASP.NET 3.5 SP1, all system-generated hidden fields are rendered at the top of the page. This makes sure that the information in these fields is sent to the server even if a postback is performed before the page has finished loading. If RenderAllHiddenFieldsAtTopOfForm is set to false, performing a postback before the page has finished loading can cause an "Invalid postback or callback argument" error.

    This is a nice, but subtle fix. Basically if you tried to do a postback (AJAX or otherwise) before the whole page was loaded and one of the hidden fields like __EVENTTARGET wasn't loaded yet because it was rendering at the bottom of the page, you'd be in a pickle. And you'd get a validation error on post. Now you can set this to true and move those hidden fields to just below the <form>.
  • HtmlForm.Action is now settable - Again, subtle, but very cool.  I like to use URL rewriting a lot and want my <form action=""> to be a certain way. Now I can set it manually without fooling around with RegEx's and messing with the whole response.
  • RedirectMode for CustomErrors - Also nice for URL redirects. If you set the redirectMode on <customErrors/> in web.config to "responseRewrite" you can avoid a redirect to a custom error page and leave the URL in the browser untouched.

A few more advanced improvements:

  • There's a new overload of System.Web.Caching.Cache.Insert() and a new CacheItemUpdateCallback. Thomas Marquardt has more on this in detail. Now you can get notified when a cache item is invalid and you get an opportunity to generate a replacement. This means you actually get warned BEFORE the item is yanked.
  • New RemapHandler method on HttpContext lets you swap in your own IHttpHandler mid-request as long as you do it before MapRequestHandler has been called.
  • New throttling option under IIS7 using aspnet.config. You can set MaxConcurrentRequestsPerCpu or MaxConcurrentThreadsPerCpu. For example, if you had a number of high-latency calls that were tying things up, you could use change the Concurrent Threads setting to throttle more logically than Concurrent Requests.
  • Now Response.Flush is safe reliable to call from a background thread. Before you could wreck havoc if you called Flush from the the background in an AJAX app, but no longer!
  • Remember that System.Web.Routing has been brought over from MVC world and is a core part of ASP.NET now. You can use ASP.NET Routing as you like and there's a fine writeup on Routing here. How is Routing different from URL Rewriting?

    ASP.NET routing differs from other URL rewriting schemes. URL rewriting processes incoming requests by actually changing the URL before it sends the request to the Web page. For example, an application that uses URL rewriting might change a URL from /Products/Widgets/ to /Products.aspx?id=4. Also, URL rewriting typically does not have an API for creating URLs that are based on your patterns. In URL rewriting, if you change a URL pattern, you must manually update all hyperlinks that contain the original URL.

    With ASP.NET routing, the URL is not changed when an incoming request is handled, because routing can extract values from the URL. When you have to create a URL, you pass parameter values into a method that generates the URL for you. To change the URL pattern, you change it in one location, and all the links that you create in the application that are based on that pattern will automatically use the new pattern.

If any of these small but important fixes make you smile, thank Stefan Schackow and the ASP.NET team. If you ever see them, give them a hug, it'll make them very uncomfortable. There are more fixes, and I hope ScottGal expounds on them soon at http://www.asp.net

What about Connected Services?

On the services side, Sam Gentile points out a bunch of new WCF features in 3.5 SP1 like:

  • Improvements in writing REST based services ranging from easily supporting ServiceDocuments publication and consumption to providing greater control and usability of UriTemplate with new syntax. AtomPub support in a new Object Model.
  • DataContract Serializer gets way easier by relaxing/removing the ned for [DataContract] and [DataMember] on types. It's POCO (Plain Ol' CLR Object) time, people.
  • More interoperable object references in the serialization format, which means WCF gets along better with Java.
  • New Hosting Wizard when making new WCF Services.
  • Better Partial Trust behavior, particularly when tracing/logging.
  • Support for ADO.NET Entity Framework types in WCF contracts.
  • WCF Templates for consuming services from Silverlight.
  • Scalability increases of 5X-10X (oy!) for WCF services hosted in IIS7-integrated pipeline mode.
  • The Workflow Designer is has a number of performance improvements and is generally quicker.

Related Posts

About Scott

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

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

Hacked! And I didn't like it - URLScan is Step Zero

August 12, 2008 Comment on this post [36] Posted in ASP.NET | ASP.NET MVC | IIS | Tools
Sponsored By

My blog was down a few days ago. I've had downtime in the minutes over the last few years, but as far as I recall, it's never been down for any significant time. Keyvan noticed that a bunch of us were attacked. Phil Haack was also, ahem, haacked.

UPDATE: To be clear, I wasn't really hacked. I was "DoS'ed" or brought down for a little bit by a distributed denial of service attack that spiked my CPU. I'm advocating that you constrain the URLs that input that get to your  application by either black-listing, or white-listing allowed content.

I host at ORCSWeb and have forever. We're in the process of making a lot of chances to my blog. I'm on an x64 machine (I've blogged about DasBlog on x64 before), but running in 32-bit AppPool We're moving my blog to a dedicated server, switching to x64, and we also were upgrading to UrlScan 3.0 which just had a Beta Release in June.

Anyway, in this crazy process, there was window of time where I didn't have UrlScan enabled on the machine. I mistakenly thought that the Ninjas wouldn't be able to catch me if I was on fire. In fact, not so.

ninjasonfire

Speaking of Ninjas, Wade Hilmo is a ninja at Microsoft who writes UrlScan.

There's a great IIS7 Request Filter for protecting against nasty attacks, but UrlScan Beta 3.0 still has the edge on the filter for the time being. Version 3.0 of UrlScan adds:

  • Support for query string scanning, including an option to scan an unescaped version of the query string.
  • Change notification for configuration (no more restarts for most settings.)
  • UrlScan can be installed as a site filter.  Different sites can have their own copy, with their own configuration.
  • Escape sequences can be used in the configuration file to express CRLF, a semicolon (normally a comment delimiter) or unprintable characters in rules.
  • Custom rules can be created to scan the URL, query string, a particular header, all headers or combination of these.  The rules can be applied based on the type of file requested.
  • Support for 64 bit IIS worker processes.

This release of UrlScan is a beta, but it's config file is backward compatible and there's a GoLive license. It's working great for me. However, to quote Wade:

"While they are effective against the current wave of automated attacks, they cannot protect against more directed attacks against a specific server."

This was a SQL Injection attack with URLs that looked like this (and some variations):

[08-11-2008 - 17:29:31] Client at 201.67.x.x: Query string length exceeded maximum allowed. Request will be rejected. Site Instance='13', QueryString= 'guid=0b93befc-3543-4bfc-ba8e-6cd340b6d9d3;DECLARE%%20@S%%20VARCHAR(4000);SET%%20@S=CAST(0x4445434C4152452...(incrediblyLONGQueryString)...220%%20AS%%20VARCHAR(4000));EXEC(@S);--', Raw URL='/blog/CommentView.aspx'

In this example, it's hitting CommentView.aspx and trying to add a bunch of T-SQL at the end, with the most evil part encoded inside a CAST() statement. It's a distributed attack with a bunch of (likely innocent) drones reaching out to be mean. In a few hour period, there were thousands of attacks for over 250 different IP addresses.

Fortunately DasBlog doesn't use a database at all, rather a bunch of XML files for storage. Unfortunately, the application was still trying to map these query strings to blog posts, and the result took my blog down.

There's really two main things to think about when dealing with user input, remembering that the URL is an input point for your application!

  1. Trust no input from the user.
  2. Constrain the input that reaches your application code as much as you can. Deny as early as possible (hardware, load-balancer, appliance, module, etc).

We need to tighten up DasBlog to more quickly reject URLs that are surely not requests for blog posts, but a tool like UrlScan allows me to easily reject obvious attacks in an way that is more efficient than letting my application code do it.

I would encourage you to take a moment and do a threat analysis on your own websites, and make sure that you ARE constraining input appropriately.

One thing to note, you can and will likely break things for a while with UrlScan, as it does constrain input and you might have valid URLs you aren't aware of. For example, UrlScan broke OpenID authentication for me as the query strings included dots, which UrlScan was denying and also the presence of the word "open" in the querystring. Other denials can happen because of keywords in the URL or length of the querystring. Be sure to test appropriately and watch the UrlScan logs of denials. You can set very blanket rules, or constrain by extension.

We always installed UrlScan on staging and production machines when I was in banking, and made them part of the testing and deployment process. In these times, having a filter installed like UrlScan is Step Zero. I will remember that in the future! Thanks to ORCSweb for answering my 2am emails and helping me fix it in near-real-time!

Technorati Tags: ,,

About Scott

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

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

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