Open Bug 955628 Opened 11 years ago Updated 2 years ago

FF does not warn or throws an error when the empty host field in proxy setting, and merrily connects to network directly.

Categories

(Firefox :: Security, defect)

x86_64
Windows 7
defect

Tracking

()

People

(Reporter: ishikawa, Unassigned)

Details

Well, I may be paranoia, and feel free to reset the security setting.

But I have a feeling that this could be misused.

For example, I am not sure what happens
if system wide proxy setting leaves host field empty, or 
if some malware or something (javascript maybe?) could
change this field and fool the user to check only "use proxy / do not use proxy" setting while actually FF happily connects to the network without producing or issuing very visible error, etc.
(I have not checked the error console yet, but
I bet many users will be fooled by this in a subtle manner.)

--- What happened.

I am using Firefox 24.2.0 under windows 7.

About an hour ago, I just noticed that suddenly my proxy setting was not followed at all.
Even when I toggle the proxy setting on and off, etc. to no avail.

Then I noticed that somehow my proxy setting had the host field empty (!) 
[I have no idea what did it. It was working as expected only a moment ago before I invoked FF then.
I am a little worried if some malware or something set this, or even a javascript of some web page with malicious intent may have done it knowing this loophole [whether such is possible or not is beyond me]. 
Or it could be a disk data failure or something. My host PC uses ECC and so I think memory corruption is less likely than it is on an average PC.]
 
I am using local privoxy and the port # was still set correctly at 8118.

When I filled in the host setting 127.0.0.1 (as I set it previously)
then the proxy setting works as expected.

SECURITY-related PROBLEM or issue is this:
It seems to me that FF merrily goes on to connect to the net without
proxy, if the host field is empty.
I think FF ought to issue error message or something if
the host field is empty (I don't know if the proxy host is not reachable, etc.)
and refuse to connect to the net.

Has anyone noticed/experienced this behavior?

As I mentioned above, the choice of enabling security flag for this bug may
not be inappropriate. In that case, please reset this.

But I was so perplexed when my toggling proxy setting on/off did not produce
any change after previously blocked ads and other stuff suddenly showed up.

A casual user may think after checking proxy setting (and failing to notice
the host field, the setup page is rather cluttered) 
"OK, I have enabled proxy, and so it should be OK. 
The new look (obviously different layout because some data 
that has been blocked [ads, etc.] now appear) must have something do with the LEGITIMATE changes of the web pages or FF itself."
Oh well.

TIA
Ideally, all UI fields should be validated and users shouldn't be able to make simple mistakes. So, this could be addressed as a usability issue.

However, should a hacker be able to delete proxy settings, they'd be able to do much worse. I don't know of a way for this to be done via web content (JS) or other malicious means. So, as a security issue, I'm inclined to say that the behavior described here is less of a security concern, and that we're going to unhide the bug.
Group: core-security
(In reply to Matt Wobensmith from comment #1)
> Ideally, all UI fields should be validated and users shouldn't be able to
> make simple mistakes. So, this could be addressed as a usability issue.
> 
> However, should a hacker be able to delete proxy settings, they'd be able to
> do much worse. I don't know of a way for this to be done via web content
> (JS) or other malicious means. So, as a security issue, I'm inclined to say
> that the behavior described here is less of a security concern, and that
> we're going to unhide the bug.

That is fine with me.

My main concern is that instead of simply disabling the proxy which would have been noticed
right away because of the easily recognizable radio button, 
the intruder / malware can clear the host field (I am not sure how that can be done. Like Matt mentioned
it could have been my zittering mouse did it.), which is not quite obvious and
so it is a good way to fool a user into all is well (so more of a problem of
social / human engineering aspect of the security).

Of course, much worse could be done, but the idea is to hide the
exploit longer than anti-spyware would usually allow such exploit to linger or
the diligent users would allow.
(If a malware or an exploit that does something describe above does exist, it certainly will have
fooled me for a few dozen minutes until I figure it out. An average user like my parents would have allowed it for a week or so before they really feel strange and contact me that something is amiss on their computer.)

So despite this being a usability issue, whatever the urgency scale mozilla uses,
it ought to be given a higher priority than others, I hope.

TIA
http://mxr.mozilla.org/mozilla-central/source/browser/components/preferences/connection.xul#32

So this is the dialog that pops up when one wants to change the proxy setup.

And it is called from the following code:
http://mxr.mozilla.org/mozilla-central/source/browser/components/preferences/in-content/advanced.js#271

 /**
272    * Displays a dialog in which proxy settings may be changed.
273    */
274   showConnections: function ()
275   {
276     openDialog("chrome://browser/content/preferences/connection.xul",
277                "mozilla:connectionmanager",
278                "modal=yes",
279                null);
280   },

I dwonder where the value returned into the host field as string is checked, but
that is the place where proper checking should be enforced.

Searching for |network.proxy.http|
I found the following matches excluding the test code.

Found 27 matching lines in 8 files
/browser/components/preferences/connection.js (View Hg log or Hg annotations)

    line 18 -- var httpProxyURLPref = document.getElementById("network.proxy.http");
    line 19 -- var httpProxyPortPref = document.getElementById("network.proxy.http_port");
    line 51 -- var httpProxyURLPref = document.getElementById("network.proxy.http");
    line 53 -- var httpProxyPortPref = document.getElementById("network.proxy.http_port");
    line 137 -- var pref = document.getElementById("network.proxy.http" + (aIsPort ? "_port" : ""));

/browser/components/preferences/connection.xul (View Hg log or Hg annotations)

    line 32 -- <preference id="network.proxy.http" name="network.proxy.http" type="string"/>
    line 33 -- <preference id="network.proxy.http_port" name="network.proxy.http_port" type="int"/>
    line 84 -- preference="network.proxy.http" onsyncfrompreference="return gConnectionsDialog.readHTTPProxyServer();"/>
    line 87 -- preference="network.proxy.http_port" onsyncfrompreference="return gConnectionsDialog.readHTTPProxyPort();"/>

/dom/system/gonk/NetworkService.js (View Hg log or Hg annotations)

    line 331 -- Services.prefs.clearUserPref("network.proxy.http");
    line 332 -- Services.prefs.clearUserPref("network.proxy.http_port");
    line 344 -- Services.prefs.setCharPref("network.proxy.http", network.httpProxyHost);
    line 347 -- Services.prefs.setIntPref("network.proxy.http_port", port);

/modules/libpref/src/init/all.js (View Hg log or Hg annotations)

    line 1344 -- pref("network.proxy.http", "");
    line 1345 -- pref("network.proxy.http_port", 0);

A couple of points that stood out after my cursory browsing:

(1) connection.js seems to process the user input:

http://mxr.mozilla.org/mozilla-central/source/browser/components/preferences/connection.js#6


6 var gConnectionsDialog = {
7   beforeAccept: function ()
8   {
9     var proxyTypePref = document.getElementById("network.proxy.type");
10     if (proxyTypePref.value == 2) {
11       this.doAutoconfigURLFixup();
12       return true;
13     }
14 
15     if (proxyTypePref.value != 1)
16       return true;
17 
18     var httpProxyURLPref = document.getElementById("network.proxy.http");
19     var httpProxyPortPref = document.getElementById("network.proxy.http_port");
20     var shareProxiesPref = document.getElementById("network.proxy.share_proxy_settings");
21     if (shareProxiesPref.value) {
22       var proxyPrefs = ["ssl", "ftp", "socks"];
23       for (var i = 0; i < proxyPrefs.length; ++i) {
24         var proxyServerURLPref = document.getElementById("network.proxy." + proxyPrefs[i]);
25         var proxyPortPref = document.getElementById("network.proxy." + proxyPrefs[i] + "_port");
26         var backupServerURLPref = document.getElementById("network.proxy.backup." + proxyPrefs[i]);
27         var backupPortPref = document.getElementById("network.proxy.backup." + proxyPrefs[i] + "_port");
28         backupServerURLPref.value = proxyServerURLPref.value;
29         backupPortPref.value = proxyPortPref.value;
30         proxyServerURLPref.value = httpProxyURLPref.value;
31         proxyPortPref.value = httpProxyPortPref.value;
32       }
33     }
34     
35     this.sanitizeNoProxiesPref();
36     
37     return true;
38   },


This could possibly the place where the |""| value of |host| can be checked
and error can be signaled by throwing an error?
 
(2) /dom/system/gonk/NetworkService.js has an interesting piece of code:

http://mxr.mozilla.org/mozilla-central/source/dom/system/gonk/NetworkService.js#325

325   setNetworkProxy: function setNetworkProxy(network) {
326     try {
327       if (!network.httpProxyHost || network.httpProxyHost === "") {
328         // Sets direct connection to internet.
329         Services.prefs.clearUserPref("network.proxy.type");
330         Services.prefs.clearUserPref("network.proxy.share_proxy_settings");
331         Services.prefs.clearUserPref("network.proxy.http");
332         Services.prefs.clearUserPref("network.proxy.http_port");
333         Services.prefs.clearUserPref("network.proxy.ssl");
334         Services.prefs.clearUserPref("network.proxy.ssl_port");
335         if(DEBUG) debug("No proxy support for " + network.name + " network interface.");
336         return;
337       }
338 

This seems to fit my observation that if the host is empty string,
direct internet connection is initiated.

But then 
- why doesn't the proxy setting button visible to the user is not cleared 
  to show that the proxy setting is cleared for the real operation?, 
  (This is very important UI issue with GRAVE SECURITY CONCERN),
  and
- why I didn't see the debug message? (even in the debug console? Did I miss it by mistake?)

Anyway, this piece of code (and I suspect a few other places) needs checking and modification properly.

I hope someone in the know can fix the places mentioned above and possibly a few more places
I don't know appropriately.

TIA
I got curious. 
|beforeAccept| seems to be used in the following four places.

beforeAccept

Found 4 matching lines in 4 files
/browser/components/preferences/connection.js (View Hg log or Hg annotations)
    line 7 -- beforeAccept: function ()

/browser/components/preferences/connection.xul (View Hg log or Hg annotations)
    line 16 -- onbeforeaccept="return gConnectionsDialog.beforeAccept();"

/modules/libpref/src/init/all.js (View Hg log or Hg annotations)
    line 1367 -- pref("network.cookie.lifetimePolicy", 0); // accept normally, 1-askBeforeAccepting, 2-acceptForSession,3-acceptForNDays

/toolkit/content/widgets/preferences.xml (View Hg log or Hg annotations)
    line 1034 -- if (!this._fireEvent("beforeaccept", this)) 

TIA
Severity: normal → S3
You need to log in before you can comment on or make changes to this bug.