Simple web proxy in ASP.NET

In last two weeks, on two separate occasions, I needed a simple web service that would act as proxy to remote servers.

First, while writing my crude twitter ticker in Silverlight, I run into issue with lack of support for GIF images in Silverlight, and potentially also with accessing 3rd party servers. Normally, Silverlight and Flash (and also JavaScript) are able to freely contact ONLY their server of origin, but due to XSS attacks accessing other hosts is… less than ideal.

In this case I set up a simple ASP.NET handler that receives requests from my Silverlight program using URL like this:
http://localhost/imageproxy.ashx?url=http://remote.server.com/some/alien/avatar.gif

then the service contacts the URL specified in parameter, downloads the data and returns it to the original Silverlight app, in single trip. In my case the service also re-encodes the images as JPEG’s or PNG’s which are easier to work with in SL, but that step is optional, as most of the pictures are JPEG’s anyway and are passed through without changes. I used code from the article Silverlight: Handling Cross-Domain Images and Gifs by and modified it slightly.

A week later I was forced to overhear my unholy fallen .netless colleagues talking repeatedly about problems with accessing MS Reporting Services from Hell Java and blaming Integrated Windows Authentication (a.k.a. NTLM). When they started considering setting up ISA Server (aptly renamed to Microsoft Forefront Threat Management Gateway), I offered a single-file alternative that I could write in 5 minutes. Java would call this unsecured proxy, which in turn would apply security and access the MS Reporting server.

Two hours later the file was mostly done, tested and somewhat working. In order to host it under IIS on Windows you need to put it some existing “web folder”, e.g. c:\Inetpub\wwwroot\ or create separate one using IIS manager. No manual compilation is needed, just make sure the server has ASP.NET installed and enabled (tested on version 4.0 and IIS 7.5).

The usage is similar to the previous example, but it adds hard-coded credentials and POST support, used for talking to SOAP web services.

Please see the whole file below, including a funny fake password. Some cleaning and tuning advised, regarding error handling and security. I’m posting it anyway, even though one could probably write it from scratch faster than read this lengthy blog post.

The file should be saved with .ashx extension. Use at your own risk.

<%@ WebHandler Language="C#" Class="Ekus.WebServiceProxy" %>
using System;
using System.Collections;
using System.Data;
using System.Drawing;
using System.IO;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Net;
using System.Collections.Generic;

namespace Ekus
{

	/// <summary>
	/// Receives a web request with target URL, 
	/// invokes another web request to the target URL with added NTLM credentials, 
	/// and returns the response to the original caller.
	/// </summary>
	
	public class WebServiceProxy : IHttpHandler
	{
		public void ProcessRequest(HttpContext context)
		{
			string webServiceUrl = context.Request["url"].ToString();
			string proxy;
			// proxy = "127.0.0.1:8888"; used for testing with Fiddler2

			HttpWebRequest req = (HttpWebRequest)WebRequest.Create(webServiceUrl);
			if (proxy != null) req.Proxy = new WebProxy(proxy, true);
			// if SOAPAction header is required, add it here...
			req.Headers.Add("SOAPAction", context.Request.Headers["SOAPAction"]);
			req.ContentType = "text/xml;charset=\"utf-8\"";
			req.Accept = "text/xml";
			req.Method = context.Request.HttpMethod; // "POST";
			req.Credentials = new NetworkCredential(
				"joker", // username; didn't work when using domain\username format
				"funny",  // password
				"gotham"); // domain
			req.PreAuthenticate = true; // Cargo_cult_programming

			if (req.Method == "POST")
			{
				// copy original request "body" to the new request
				string input = new StreamReader(context.Request.InputStream).ReadToEnd();
				// encode it using the predefined encoding (see above, req.ContentType)
				System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
				byte[] bytesToSend = encoding.GetBytes(input);
				// Set the content length of the string being posted.
				req.ContentLength = bytesToSend.Length;
				Stream newStream = req.GetRequestStream(); // This method has the side effect of initiating delivery of the request in its current state to the server. Any properties like the request method, content type or content length as well as any custom headers need to be assigned before calling the GetRequestStream() method.
				newStream.Write(bytesToSend, 0, bytesToSend.Length);
				// Close the Stream object.
				newStream.Close();
			} // else GET, no body to send. Other verbs are not supported at the moment.

			WebResponse resp = req.GetResponse();
			Stream respStream = resp.GetResponseStream();
			StreamReader r = new StreamReader(respStream);
			// process SOAP return doc here. For now, we'll just send the XML out to the browser ...
			string output = r.ReadToEnd();
			context.Response.Write(output);
		}

		public bool IsReusable
		{
			get
			{
				return false;
			}
		}
	}
}
Advertisement

The safest password

Today at work I was forced to change my silly, complicated Windows password: Pas$w0rdX to Pas$w0rdY.
That’s it. I changed one letter and called it a day. And not just any letter. The last letter. And I changed it in the least relevant way. I incremented it by a single bit. Looking at binary representation, this is my password before and after the change:

010100000110000101110011001001000111011100110000011100100110010001011000
010100000110000101110011001001000111011100110000011100100110010001011001

Looks like my network administrator hopes that in case my old password was about to be compromised by a hacker (for example by using the simplest method possible – trying all possible combinations one after another), he/she won’t be able to hack it now. Phew, disaster averted.

This ridiculous waste of time led me to idea: in order to make the hacking as difficult as possible, I will switch to

The Ultimate Safest Password

Of course I could make it idiotically long, but where is the fun in that? Instead, I will use the strongest password that fits in the minimum length, lets say 8 characters.

Looking at the binary representation of my previous and current password, the solution presents itself very easily:
If somebody tries to iterate all possible values, they will (obviously) start from 0 and increment it over and over. Thus, the binary form of the very last password to hack is…
1111111111111111111111111111111111111111111111111111111111111111

This password is guaranteed to be the most difficult 8-letter password to break using the most sophisticated KISS algorithm known to man (exactly 264 = 1.84467441 × 1019 iterations, as opposed to 5.7920372 × 1018 for the old password limited to 8 characters). That’s mind-bogglingly 3.18 times more secure (requires 3.18 x longer time to hack using very brute force).

But wait, there’s more!

Translating to decimal, it’s series of 8 bytes with value 255 (binary 11111111) each.
And now, the ultimatest safety haxx0r. Please turn on the NumLock key on your keyboard, and check the character that the code 255 produces:

First, you need to open Notepad and press and hold Left Alt, and then use the numeric keypad to type the character code. Tablet and Apple users should not apply, they don’t know what a numpad (nor a password) is:

Apple keyboard without numpad
The location of the new, magical Numeric Pad on the current Apple keyboard

Still holding that Alt key? Type 255 on the numeric keypad (while nothing happens) and… release the Alt key.

That’s it! Did you miss it? You just typed it! Code 255 produces an invisible space character!
Now, type it 7 more times.

invisible password in notepad
invisible password in notepad

Now, you can even save it on pendrive or print it and tape it to your desk. Your ultimate password is invisible and secure!