tag:blogger.com,1999:blog-60532783488802727702023-11-15T07:00:16.333-08:00Stupid Coding TricksDanielhttp://www.blogger.com/profile/05209486047280683085noreply@blogger.comBlogger4125tag:blogger.com,1999:blog-6053278348880272770.post-52349839071938213642010-09-28T17:54:00.000-07:002010-09-28T17:54:24.244-07:00Script Resource filter up on codeplexI pushed <a href="http://acbcr.codeplex.com/">a ScriptResource wrapper</a> yesterday that implements white list based filtering for Script Resources. This module also contains some defense against the padding Oracle... which is obviously no longer relevant.Danielhttp://www.blogger.com/profile/05209486047280683085noreply@blogger.com0tag:blogger.com,1999:blog-6053278348880272770.post-58726808100446976962010-09-21T22:31:00.000-07:002010-09-22T09:51:20.759-07:00blocking requests to sensitive files (e.g. web.config) through *.axd requestsAfter Doug's comment yesterday I started poking around to see if there was a to filter requests to sensitive files and as it turns out the answer is yes.<br />
Both WebResource.axd and ScriptResource.axd using the function Page.DecryptString which is marked as internal. We can, of course, use reflection to get access to this function and evaluate the decrypted string that the user is trying to pass to these these classes. The updated code below includes code to do just that and passes each string to a blacklisted set of regular expressions. <script class="brush: csharp" type="syntaxhighlighter">
<![CDATA[using System;
using System.Collections.Generic;
using System.Reflection;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.UI;
public class SaferWRHandler : IHttpHandler
{
// this class is marked as reusable
private IHttpHandler AssemblyResourceLoaderHandler = null;
private IHttpHandler ScriptResourceHandler = null;
private MethodInfo decryptor;
//return the same time for each request, but return them as fast as possible
private static int maxTime = 0;
public bool IsReusable { get { return true; } }
SaferWRHandler()
{
filters.Add(new Regex(".*config.*", RegexOptions.Compiled));
filters.Add(new Regex(".*cs.*", RegexOptions.Compiled));
filters.Add(new Regex(".*aspx", RegexOptions.Compiled));
}
public void ProcessRequest(HttpContext context)
{
AssemblyResourceLoaderHandler = AssemblyResourceLoaderHandler ?? new System.Web.Handlers.AssemblyResourceLoader();
ScriptResourceHandler = ScriptResourceHandler ?? new System.Web.Handlers.ScriptResourceHandler();
DateTime start = DateTime.Now;
if (decryptor == null)
{
decryptor = typeof(Page).GetMethod("DecryptString", BindingFlags.Static | BindingFlags.NonPublic);
}
try
{
string str = context.Request.QueryString["d"];
string decString = (string)decryptor.Invoke(null, new object[1] { str });
FilterRequest(decString);
if (context.Request.Url.LocalPath.Contains("ScriptResource"))
{
ScriptResourceHandler.ProcessRequest(context);
}
else
{
AssemblyResourceLoaderHandler.ProcessRequest(context);
}
}
catch (Exception e)
{
if (e is FormatException || e is System.Web.HttpException || e is CryptographicException)
{
var ex = new HttpException(404, "invalid request");
int duration = (int)(DateTime.Now - start).TotalMilliseconds;
maxTime = duration > maxTime ? duration : maxTime;
System.Threading.Thread.Sleep(maxTime - duration);
throw ex;
}
else
{
throw e;
}
}
}
List<regex> filters = new List<regex>();
void FilterRequest(string requestedPath)
{
foreach (var filter in filters)
{
if (filter.IsMatch(requestedPath))
{
throw new HttpException(404, "invalid request");
}
}
}
}
]]</script><br />
<em>Important:</em> You also need to rewrite requests to ScriptResource.axd into this module.<br />
<br />
Ideally the list of expression would be loaded from web.config, but for the time being you will need to add any additional expressions in the constructor.Danielhttp://www.blogger.com/profile/05209486047280683085noreply@blogger.com1tag:blogger.com,1999:blog-6053278348880272770.post-707329024109723892010-09-20T07:25:00.000-07:002010-09-20T07:58:34.424-07:00My workaround for the ASP.Net Vulnerability<div>So over night I hacked together a quick work around that I think (No waranty, YMMV, and all that) will help with <a href="http://www.microsoft.com/technet/security/advisory/2416728.mspx">this</a> advisory from Microsoft.<br />
The vulnerability seems to rely on getting different responses for different errors with a potential second gen attack using timing information to glean the same information (albeit more slowly) from requests toWebResource.axd. I attempt to work around both of these here.</div><div><br />
</div><div>The first thing you are going to need is a custom HttpHandler, which we are going to use to wrap requests to WebResource.axd</div><div>here is the code:</div><div><script class="brush: csharp" type="syntaxhighlighter">
<![CDATA[
using System;
using System.Web;
using System.Security.Cryptography;
public class SaferWRHandler : IHttpHandler
{
// this class is marked as reusable
private IHttpHandler innerHandler = null;
//return the same time for each request, but return them as fast as possible
private static int maxTime = 0;
public bool IsReusable { get { return true; } }
public void ProcessRequest(HttpContext context)
{
innerHandler = innerHandler ?? new System.Web.Handlers.AssemblyResourceLoader();
DateTime start = DateTime.Now;
try
{
innerHandler.ProcessRequest(context);
}
catch (Exception e)
{
//correction there are 3 exceptions that need to be caught
if (e is FormatException || e is System.Web.HttpException || e is CryptographicException)
{
var ex = new HttpException(404, "invalid request");
int duration = (int)(DateTime.Now - start).TotalMilliseconds;
maxTime = duration > maxTime ? duration : maxTime;
System.Threading.Thread.Sleep(maxTime - duration);
throw ex;
}
else
{
throw e;
}
}
}
}
]]>
</script></div><div>Basically this looks for the two exceptions in question and throws a 404 for either one. Since this is only for embedded resources I don't think this will cause a problem for AJAX in most cases, but if so you could probably figure out a carve out that would leave them working.</div><div><br />
</div><div>the next thing we need to do is to wire up our handler to some arbitrary file extension in your web.config (see below)</div><div></div><div>Now we just need to get IIS to route requests through our fixed handler and were done. I used the URLRewrite module found <a href="http://www.iis.net/download/URLRewrite">here</a> and mapped WebRequest.axd to the new URL that I attached my handler too.</div><br />
<br />
<script class="brush: xml" type="syntaxhighlighter">
<![CDATA[
<system.webServer>
...
<handlers>
<add name="Safer Handler" path="*.swr" verb="*" type="SaferWRHandler" resourceType="Unspecified" preCondition="integratedMode" />
</handlers>
<rewrite>
<rules>
<rule name="WebResource.axd">
<match url="WebResource.axd" />
<action type="Rewrite" url="WebResource.swr" />
</rule>
</rules>
</rewrite>
</system.webServer>
]]>
</script><br />
<br />
feedback welcome.Danielhttp://www.blogger.com/profile/05209486047280683085noreply@blogger.com4tag:blogger.com,1999:blog-6053278348880272770.post-52125132017349847382010-02-19T19:05:00.000-08:002010-02-26T22:31:55.767-08:00generic reparenting in Silverlight<div>If you have tried to detach an object from its parent in Silverlight you have undoubtedly discovered that this.Parent doesn't expose the Children collection and that most if not all of the code on the net requires knowledge of the type of the Parent. This inevitably leads to brittle code and introduces constraints on what type of container your control can be placed in.</div><div><br /></div><div>Fortunatly .Net gives us a tool to write generic code in just this type of situation... reflection. So with that in mind I wrote a simple pair of functions that set or clear the parent of a Silverlight control as long as the Parent has a collection of UIElements named Children.</div><div><span class="Apple-style-span" style="font-family:monospace;font-size:100%;"><span class="Apple-style-span" style=" white-space: pre;font-size:13px;"><span class="Apple-style-span" style="font-family:Georgia, serif;font-size:130%;"><span class="Apple-style-span" style=" white-space: normal;font-size:16px;"><br /></span></span></span></span></div><br /><script type="syntaxhighlighter" class="brush: csharp"><![CDATA[<br /> private void Deparent(UIElement target)<br /> {<br /> Type parentType = target.Parent.GetType();<br /> PropertyInfo ChildrenProperty = parentType.GetProperty("Children");<br /> object children = ChildrenProperty.GetValue(target.Parent, null);<br /> Type ChildrenCollectionType = children.GetType();<br /> MethodInfo RemoveMethod = ChildrenCollectionType.GetMethod("Remove");<br /> RemoveMethod.Invoke(children, new object[1] { target });<br /> }<br /><br /> private void SetParent(object newParent, UIElement target)<br /> {<br /> Type parentType = newParent.GetType();<br /> PropertyInfo ChildrenProperty = parentType.GetProperty("Children");<br /> object children = ChildrenProperty.GetValue(newParent, null);<br /> Type ChildrenCollectionType = children.GetType();<br /> MethodInfo AddMethod = ChildrenCollectionType.GetMethod("Add");<br /> AddMethod.Invoke(children, new object[1] { target });<br /> }<br />]]></script><br />It should be possible to get rid of the (expensive) calls to <span class="Apple-style-span" style="font-family: monospace; font-size: 13px; white-space: pre; ">MethodInfo.Invoke <span class="Apple-style-span" style="font-family: Georgia, serif; white-space: normal; font-size: 16px; ">but as this code is code is called infrequently in my case I'm not that concerned with with the optimization. I'll leave it as an exercise to the reader to figure out this optimization if your use case is different.</span></span><div><br /><br /></div>Danielhttp://www.blogger.com/profile/05209486047280683085noreply@blogger.com0