My goal is to safely open a web page in a users default browser. The URL for this web page is considered "untrusted" (think of it as a link in a document opened with this software, but the document could be from anywhere and the links in it could be malicious)
I want to avoid someone passing "C:\Windows\malicious_code.exe" off as a URL
My current thought is to do something like this:
Uri url = new Uri(urlString, UriKind.Absolute);
if( url.Scheme == Uri.UriSchemeHttp || url.Scheme == Uri.UriSchemeHttps )
{
Process.Start(url.AbsoluteUri);
}
Am I forgetting about anything else that my 'urlString' might contain that makes this dangerous (e.g. a new line character which would allow someone to sneak a second process to be started in after the URL or a possible execution of a relative executable starting with http)?
I'm pretty sure both of those cases are handled by this (as I don't believe Process.Start allows you to start two processes as you would in a BATCH file and this should only allow strings starting with http: or https: and are valid urls)
Is there a better way to do this in C#?
What you want to check is the scheme
of the url (i.e. ftp://
, http://
, file://
, etc.) Here is a list of schemes: http://en.wikipedia.org/wiki/URI_scheme#Official_IANA-registered_schemes
To find the scheme of a URL, use:
Uri u = new Uri("C:\\Windows");
String scheme = (u.GetLeftPart(UriPartial.Scheme).ToString());
For me, the above example gives file://
. Just check the scheme, using the code above, and reject the ones you want to filter. Also, surround the parsing with a try-catch
block and if an exception is caught, reject the URL; it can't be parsed so you shouldn't trust it.
If you want to ultra-paranoid-safe, you could always parse the URL using a URL parser and reconstruct it, validating each part as you go along.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With