Open website in the user's default browser without letting them launch anything else?
Asked Answered
G

7

7

I would like to open a website in a user's default web browser, however since the url is user-defined I would also like to prevent them from doing anything other than opening a website.

I have seen people use Process.Start(url); to open a site in the default browser, but since the url is user-defined I want to be sure they don't enter something like a script location and execute it.

I also don't want to use Process.Start("iexplore", url); since I would rather open the link in the user's default browser.

Is there a way I can open a website in the user's default browser, without letting them launch any other process or command?

EDIT

For example, I don't want users to be able to enter C:\Windows\Notepad.exe into the Customer's Website field and open Notepad when they click the Website link

EDIT #2

I am not looking for a way to filter user's access online or have this substitute for property security. I am simply looking for a way to prevent users from launching any other application by entering in a bad url. If they enter "google" for a Customer's website, it should not throw an Open With file dialog, but instead launch the user's default web browser with the word "google" in the URL

Gesundheit answered 31/3, 2011 at 14:20 Comment(19)
I would have said embed the browser in your application, but you won't be able to do this for the default browser, but only for a pre-specified browser (normally IE).Keesee
How is the Url "user defined"? Do they enter it in a text box? Can you explain the [intended] workflow a bit more?Unspeakable
Just check it starts with "http://" or "https://"?Quaternion
@WeekendWarrior: For example, a Customer can have a Website which the user enters. The Website is displayed as part of the Customer record, and clicking on the website should go to it.Gesundheit
@Quaternion Users are generally not going to the website when they find the data, they are just entering it. Quite often the data doesn't come with a http/https prefix and sometimes it doesn't even include the wwwGesundheit
It sounds like your actual problem is "How do I validate a given URL is safe" - maybe the client should have some web-security in place? A gateway security device or something...Keesee
@Gesundheit in that case, you can't use Process.Start(url) anyway..Quaternion
@Blorgbeard: Even perfectly valid HTTP/HTTPS URLs aren't safe for some browsers, see e.g. this: mcafee.com/threat-intelligence/vulnerability/… Although this specific vulnerability is probably now patched everywhere, countless others like this likely exist, esp. on computers that don't get patched.Softpedal
@Quaternion I do not want to use that because it does not stop someone who enters the path of some malicious script and executes it by clicking the linkGesundheit
@Rachel: Hmm, but aren't they executing it on their own computer anyway? Or the user who enters the URL and the user whose browser gets launched are separate people?Softpedal
Combined with Piskvor's answer below, if you are concerned about the content of external sites, you might present a warning to the user "You are about to open an external link..." and have Continue/Cancel buttons. Have an option to disable it (e.g. after the first time) though, otherwise it would be really annoying.Ostrich
Do you want to prevent the user from running scripts/files on the local harddrive, or from downloading them from the net? Or both?Quaternion
@Gesundheit Whatever you do it sounds like someone could enter a malicious web-site and execute it. In fact, they could enter a perfectly good URL, but that web-site might have been hacked and be serving malware on the day it was clicked. I don't really understand why you think your application should be responsible for the security of external web-sites - that's for the clients environment. Unless I've completely misunderstood your question...?Keesee
What about the url file://C:/Windows/ - do you need to block that?Quaternion
Google has a safe browsing api....code.google.com/apis/safebrowsing/developers_guide_v2.htmlHelvetii
@RB We have a content-filter/firewall in place which blocks most bad websites and all internet downloads. @Piskvor Most users are running the application through Terminal Services, so the malicious script would get executed on our servers, not on a local machine.Gesundheit
@Gesundheit When I saw your answer, I finally understood the question. Sorry - I'd been on completely the wrong track (although I think I wasn't the only one!!).Keesee
@RB I added an example. Sorry if there was some confusion...Gesundheit
@Rachel: aha, that makes it clearer. Indeed, you may need to filter at data entry - "websites must start with http(s)://" or somesuch.Softpedal
Q
6

You could look up the default browser from the registry. It's in several different places, but I think HKEY_CURRENT_USER\Software\Classes\http\shell\open\command would be a good place to look.

Extract the executable name from that, then Process.Start it with the user-entered URL as a parameter.

Quaternion answered 31/3, 2011 at 14:39 Comment(2)
Thanks, I actually got that working right before you posted this :) Do you know if that works with other Windows operating systems or if any special permissions are needed to access that key in a terminal-server environment?Gesundheit
I would .. tentatively .. expect it to work in at least Win2k and up. And there shouldn't be permissions problems accessing HKCU, but I do not have experience with terminal services.. So I advise you to test it carefully :)Quaternion
G
5

I found a way to do it, however I haven't tested to see if this will work on other operating systems

I get the Path for the DefaultWebBrowser from the registry and then use Process.Start(defaultBrowserPath, url);

public static void OpenWebsite(string url)
{ 
    Process.Start(GetDefaultBrowserPath(), url);
}

private static string GetDefaultBrowserPath()
{
    string key = @"http\shell\open\command";
    RegistryKey registryKey =
    Registry.ClassesRoot.OpenSubKey(key, false);
    return ((string)registryKey.GetValue(null, null)).Split('"')[1];
}
Gesundheit answered 31/3, 2011 at 14:39 Comment(10)
How does that protect the user at all?Circinate
Oooooh - Now I understand. You are concerned about people launching a process that isn't the browser, because they have set the URL to "C:\Windows\Notepad.exe".Keesee
@RB: What happens when "http\shell\open\command" is "C:\Windows\Notepad.exe"?Softpedal
@Dan It is opening the user-defined string in a WebBrowser instead of just launching a user-defined string and hoping they entered a URLGesundheit
@Piskvor Most users don't have access to the RegistryGesundheit
@Rachel: This is in the HKEY_CURRENT_USER hive, IIRC any user has permissions to edit here (as it's their own hive, as opposed to HKEY_LOCAL_MACHINE). So no, every user has access to this part of the Registry, write access even (although this can be limited by policies, it rarely happens).Softpedal
@Rachel: c:\windows\notepad.exe is a valid address in IE, as is the Uri of a web-hosted malicious script. What do you protect the user from by forcing a browser to open the content?Circinate
@Dan Users are not able to download items online and by putting notepad.exe in the webbrowser it downloads it and asks you if you want to run or save it. Putting the path to a script file does the same thing, or in some cases (such as batch files) it just displays the contents of the script file. It doesn't run them.Gesundheit
@Gesundheit If the user wants to run notepad.exe they can click on the start button, type notepad, press enter and, hey presto! Notepad.Carrycarryall
@David Yes, this wasn't a question meant to be used for security, it was one about making the application do the expected behavior.Gesundheit
S
3

Well, not really. What you could do is check whether it's a HTTP(s) URL, and whether the URL returns a text/html content-type - but not even that will help if the browser uses content sniffing (ignores content-type, tries to determine it from file content - IIRC IE6 does this, not sure what others).

Also, various browsers are susceptible to various security holes in malformed URLs (why does IE come to mind again?), so you may want to check for things like null hacks, EOL hacks, etc etc.

In the end, there is no perfect URL check - old/unpatched browsers will always be susceptible to some exploits, and that's not really something you can fix. You can, however, filter out most of them - whether it will be 80%, 99%, or 99.99%, depends on the amount of time you are willing to invest.

Softpedal answered 31/3, 2011 at 14:32 Comment(0)
C
2

If I'm understanding you right, then there is no solution to the problem you describe. You're saying: how can I filter user-entered data (hopefully in the form of a Uri, but even a Uri is a very broad concept) to ensure that it's not malicious content. The answer is that without doing it manually, you can't.

http://here.dowloadmyvirus.com is a perfectly valid site Uri but you can never ever guarantee the content that will be served from there.

It needn't even be a Uri: if you hit Start/Run and type "iexplore c:\windows\notepad.exe" then (with IE9 RTM) I get my own local notepad.exe launched as a download. There's nothing to stop you pointing at a malicious script hosted online.

I'd suggest that you either need to limit access so that only a few trusted users can edit whatever data it is you're managing, or have an audit process in place to ensure that such content is validated before it's published.

Circinate answered 31/3, 2011 at 14:45 Comment(1)
User's are mostly on Terminal Services with some strict permissions set. They cannot download anything online, they cannot install applications, there is a content-filter and firewall in place which helps with most bad websites, they have very limited permissions to do anything. I am not looking for a way to filter web access, I am looking for a way to stop users from launching scripts or applications via the URL they can enter. In short, I want to open the users Default Web Browser and pass it a URL, NOT just go Process.Start(url);Gesundheit
K
2

I've worked out a way, which takes advantage of the fact that javascript runs in a sandbox.

Have a web-page (e.g. http://mydomain/LaunchPage.html) that is accessibly to your desktop application. Call it by putting your URL on the query string (so http://mydomain/LaunchPage.html?URL=http://www.google.com).

All the LaunchPage does is to use JavaScript to set the document.location.

<script>
    /*
     * Retrieve names values from the query string.
     * Based on an idea from
     * http://ilovethecode.com/Javascript/Javascript-Tutorials-How_To-Easy/Get_Query_String_Using_Javascript.shtml
    */
    function queryString(key) {
        args = window.location.search.substring(1).split("&");
        for (i = 0; i < args.length; i++) {
            keyValuePair = args[i].split("=");
            if (keyValuePair[0].toUpperCase() == key.toUpperCase()) {
                return keyValuePair[1];
            }
        }
        return null;
    }

    document.Location = queryString("URL");
</script>

If the URL is set to a local file or something, then the JavaScript sandbox will prevent it being used.

You can now use the following code in perfect safety.

Process.Start("http://mydomain/LaunchPage.html?URL=C:\Windows\Notepad.exe") 

EDIT Note that the HTML file could be installed alongside your application. If you have done this, the code to launch it would be something like:

Process.Start("c:\<InstallRoot>\LaunchPage.html?URL=C:\Windows\Notepad.exe") 
Keesee answered 31/3, 2011 at 14:59 Comment(2)
Thanks, but this is not a web application. Someone retagged my original question. It is a WPF desktop application using C#Gesundheit
@Gesundheit This works for a WPF application as well. Rather than using Process.Start(url) (or whatever solution you come up with), you use Process.Start("http://mydomain/LaunchPage.html?URL=" + url) instead. So, all you need is 1 single HTML file in your WPF application - it could be on the local filesystem, or sitting on a central file-server, or running on a web-server. It doesn't matter. See my edit...Keesee
M
1

I think you can check the url to confirm that it is a valid URL not a path of an executable file.

You can use regular expressions to validate the url, have a look here here.

Good luck!

Melodize answered 31/3, 2011 at 14:25 Comment(1)
There are so many different types of URLs and Applications that building a regex for this would be a nightmareGesundheit
C
1

It seems to me that you are worrying about something that is not in fact a problem. If the user could run a program rather than a URL from your app, then they could just as well run a program themselves. It's only a security concern if you accept input from some entity other than the logged on user.

Carrycarryall answered 31/3, 2011 at 14:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.