Debugging Third-Party Applications – Part 3


7 February 2012, by

previous article in series

This is the last in a short series of posts about a problem I had with Microsoft Exchange’s Outlook Web Access (OWA): reading the Old New Thing blog through OWA suddenly stopped working with error:

This link has been disabled for your security.

In the second part I tracked down the .NET code that was rejecting the blog article URL as unsafe and I guessed that the problem was the URL was relative not absolute – and so looked to OWA like an attempt to reference one of its own resources, potentially maliciously, and not a real link to a page on the internet.

The problem and the work-around

I discovered then that I was reading this particular blog through its Atom feed, an alternative and more detailed syndication feed format than RSS; Atom URLs are permitted to be relative links, and examining the Atom XML that’s what I now had here:

  <entry>
    <title>How do I delete bytes from the beginning of a file?</title>
    <link rel="alternate" type="text/html"
                          href="/b/oldnewthing/archive/2010/12/01/10097859.aspx" />

Microsoft had upgraded their blog platform to the latest version of Community Server and it appears that upgrade changed the generated Atom feed in a way incompatible with Outlook and OWA.

I used OutlookSpy to confirm that the URL had been imported into Exchange as a relative URL, not an absolute URL

A feed item from an Atom feed in OutlookSpy

and that the equivalent RSS feed for the same blog imported into Exchange as the absolute URL. And, sure enough, if I read the same blog in OWA from its RSS feed not Atom feed the article links are not blocked. I now had a work-around for the problem.

Since I can’t find the specification for the PostRssItemLink MAPI item property I don’t know where the actual fault lies: it’s either with Outlook’s feed ingestion for storing the relative URL in PostItemRssLink not the absolute URL, or with OWA for not supporting absolute URLs stored in that property. However either way the bug should be reported to Microsoft, so I did through their online Live Mail / OWA help and support.

And although I didn’t get a response, a few months later I found the issue had been fixed. Microsoft have now fixed the problem at both ends: OWA has been modified to support relative PostItemRssLink URLs and Outlook to expand relative URLs in ingested Atom XML and write absolute PostItemRssLink URLs. So I still can’t be sure whether the original spec for PostItemRssLink allowed relative URLs or not, but with relative values out-in-the-wild the safest fix was to start supporting them in OWA whether that was intentional or not. And as it happens situations like this, where a design decision was forced on Microsoft to maintain compatibility with programs and data already out there, is one of the topics covered in the Old New Thing blog I was trying to read in the first place.

If it hadn’t been that easy

So what if I hadn’t been able to spot the problem here? My next step would have been to put together a minimal clone of Exchange as a virtual machine so that I could modify the OWA code and run the entire OWA app under a debugger.

I would need to determine the application state at the point it was generating the UrlBlockedError URL; looking at the OwaSafeHtmlCallbackBase class there is no easy way to leak the state and so this would have meant adding breakpoints to the code and running it in a debugger. This would have been a large undertaking, and beyond my Exchange admin knowledge, so I’m happy it didn’t get that far.

Other resources

  • If instead the URL had been blocked by the JavaScript code, I would have had to dig through the minified JavaScript to track down the problem. jsbeautifier.org hosts a script that will reformat and (to a limited extent) unpack minified JavaScript, and you can (and should!) download the script and use the Mozilla Rhino command-line JavaScript engine to unpack the whole application locally to make it easier to read and understand.If the problem had been in the script then it would have been relatively easy to modify the script to leak state, e.g. using JavaScript alerts or by tracing out to an element on the page or in a new window, to identify where and why things were going wrong.
  • If instead this had been a C or C++, i.e. native not .NET, application then the job becomes significantly harder. This is simply because the code would be much harder to navigate and understand, and even more so without debugging symbols as was my situation here. An interactive disassembler such as IDA Pro is a must: this will perform control flow and data flow analysis for you, identify imported functions and attempt to separate code and data fairly successfully. You still have to pick through the assembler yourself, though!

Final word

But the best overall advice I have for debugging someone else’s code is: don’t. If they’re approachable and you have a commercial relationship with them – or even if you don’t – it’s worth asking them first. Fun though it can be, debugging this sort of issue yourself is a difficult and time-consuming process, and the original vendor may be able to provide hints, debugging symbols or even take the whole task off you!

The main circumstance where this is appropriate is when the original vendor is unwilling or unable to help you, or if you need a quick work-around for the problem. In my case I took on this bug myself to find such a work-around – some blogs from the same server worked, some didn’t, so it must be solvable! – but partly for my own interest and education, and partly because it would almost certainly be a very low priority issue for Microsoft to progress themselves since the problem is barely mentioned on the web. And partly also for professional pride: I’m a developer myself, so if I’m going submit a bug report to a third party I’m going to submit the most thorough bug report I can!

Tags: , , , , ,

Categories: Technical

«
»

Leave a Reply

* Mandatory fields


eight − = 1

Submit Comment