Root --web is insecure

(long time root user, since root version 3 days)

reporting a security problem. If I run root --web as shown in the documentation, everybody on the internet can access my files:

$ root --web=server:8877 $ROOTSYS/tutorials/v7/browser.cxx 
$ netstat -an | grep 8877
tcp        0      0 0.0.0.0:8877            0.0.0.0:*               LISTEN  
$ from anywhere, firefox http://xxx:8877/win1/

as solution, i suggest that by default, port 8877 should be bound to localhost instead of 0.0.0.0. if there is a command line option to make it so, I do not see it in the documentation.

if you suggest a solution using a campus firewall, problem becomes “anybody on the local network can see my files” (also bad). if you suggest solution using firewall rules on my machine, this is functionally equivalent to my solution, but requires more work and root access.

(as alternative solution, please release a version of ROOT that works on macos 14, all I want to do is to look at a couple of plots in a root file)

I am using ubuntu 22 pre-build binary kit for root 6.28.06.

The defective documentation that causes this problem is here:

https://root.cern/for_developers/root7/#rbrowser

ROOT Version: ROOT 6.28/06
Platform: linuxx8664gcc
Compiler: c++ (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0


Hi @dd1, thanks for this report!

Can you maybe open a GitHub issue about this? The forum is more for support questions that can usually be answered without fixing code inside ROOT.

For problem or but reports like yours, GitHub issues are better, so the problem gets assigned to the right ROOT developer and not forgotten.

Cheers,
Jonas

Hi,

Issue appears only when your HTTP ports are accessible from outside.
It is not a normal case for desktop machines.

For working on public hosts like lxplus.cern.ch I recommend to use rootssh - which is shortly described under the same link. It is secure while uses unix sockets - which are protected for reading and writing only by the user itself.

In principle, one can switch to unix sockets also in default case. Probably this can be done in next ROOT version. Of course, it only will work on Linux and MacOS.

Regards,
Sergey

at Fermilab, a node running an application listening to an external port would be taken off the [internal] network quite promptly.

so

a) the security hole needs an immediate fix - you may seek an advice from the CERN compsec
b) the suggestion by @dd1 to bind by default the port to localhost makes a lot of sense, and the users need an option to redefine that

– regards, Pasha

in the midas data acquisition system, our default is to bind mhttpd port 80 to localhost, and we instruct users to setup apache password protected https proxy for outside access. internal midas ports also bind to localhost by default. no external ports open by default.

if midas frontend needs to run on another computer, midas provides an access control whitelist and tell users to setup firewall rules.

all this was implemented specifially to run on the CERN network (the ALPHA anti-H experiment) because we had problems with hostile port probing and tcp attack injections (this is inside CERN, behind lxplus).

K.O.

(if I ever figure out where --web is handled, and I cannot find any documentation on this command line option so far, I guess I can submit a patch to switch it to localhost or to enable the “?localhost” option in root httpd).

can you say more about this? if I am at an internet cafe connected to local wifi, everybody else on the same network can connect to my machine. by default, ubuntu 22.04 has no firewall rules and everybody in the cafe can access my root session, see my files. do try this at home!

macos has a restrictive firewall by default, but if user clicks “yes” on “allow root.exe to accept internet connections?” popup, the problem appears and it is not clear to me how to undo this “yes” to make root secure again. (you cannot try this at home, root is broken on macos 14).

K.O.

@jonas: Dear Ionas, understanding the gravity of the issue, do yo still want @dd1 to go through the bureaucracy of reporting the issue on github as well? - BTW, he just did what is recommended the ROOT7 web page … For completeness, I could also report this issue to CS.

@dd1 : the slice is thin :slight_smile: would it possible in the near future to ask you question(s) about MIDAS ?

I think, the entry point is here - void TROOT::SetWebDisplay(const char *webdisplay)
(somehow I am not allowed to post even a ROOT github URL)

at a closer look, it seems that everything needed is already implemented in gui/webdisplay/src/RWebWindowsManager.cxx, and binding the ports to localhost is just a matter of changing the defaults:

/// One also can bind HTTP server socket to loopback address,
/// In that case only connection from localhost will be available:
///
///      WebGui.HttpLoopback: yes
///
/// Or one could specify hostname which should be used for binding of server socket
///
///      WebGui.HttpBind: hostname | ipaddress
///
/// To use secured protocol, following parameter should be specified
///
///      WebGui.UseHttps: yes
///      WebGui.ServerCert: sertificate_filename.pem
///
/// Alternatively, one can specify unix socket to handle requests:

Hi,

WebGui.HttpLoopback: yes

It should be default option for the web widgets.
But it was changed only in one place (in C++ code), but remained off in default rootrc file.

I will fix it as soon as possible.

Thanks for pointing out this problem.

Regards,
Sergey

For the time been just create .rootrc file with the entry:

WebGui.HttpLoopback: yes

yep - that works - thanks a lot!
One more question: how would a user control the URL of the created canvas page ?

  • in the example below the generated URL ended up being http_://localhost:9791/win1/?key=949902 (the underscore after “http” is not a typo, but a way to fool the forum software)
  • how would a remote client know about the “key=949902” part ?
root [0] TH1F* h2 = new TH1F("h2","h2",100,0,100)
(TH1F *) 0x3237a30
root [1] h2->Draw()

   !!! ATTENTION !!! 

ROOT comes with a web-based canvas, which is now being started. 
Revert to the legacy canvas by setting "Canvas.Name: TRootCanvas" in rootrc file or
by starting "root --web=off".
Find more info on https://root.cern/for_developers/root7/#twebcanvas

Info in <THttpEngine::Create>: Starting HTTP server on port 127.0.0.1:9791

key is optional parameter and only used for handshaking between server and client. But canvas URL also works without such parameter.

Only if WebGui.OnetimeKey: yes configured in rootrc file, web widget will response only with such key parameter - which can be used only once.

thanks again!

thank you for the quick solution. please add it to the documentation web page (URL in the OP). please consider posting this information to the ROOT announcements list. all users of ROOT 6.28 must know about this problem. I assume it will be fixed in the next 6.28 point release? or we have to wait for 6.30?

K.O.

sure, ask away. best is to use the MIDAS forum at midas.triumf.ca. Stefan usually answers faster than me.

(answers price list: answer: $1, correct answer: $10, useful answer: $100)

Full documentation about server parameters one can find in RWebWindowsManager::CreateServer() method.

Fix will be apply for next 6.28 release and most probably for 6.30.02.

Thanks everyone for your super useful input. Two comments:

  • In the future, please notify us through email at rootdev@cern.ch to give us time to address security issues, rather than making them public immediately. See e.g. Coordinated vulnerability disclosure - Wikipedia and Reporting Security Issues - ROOT
  • We are currently documenting the security issue; we are preparing patch releases for all affected production versions still in active maintenance, i.e. at least 6.28 and 6.30.

Thanks again for your help with this, and major apologies for this terrible bug.

More news in the coming days.

Cheers, Axel

Hi Axel,

Now that a release with a patch for the bug is provided, would it be prudent that somebody gets in touch with any known package maintainers and lets them know about the urgency, to hopefully minimise any exploitation time where we can. Some packages will have more CI than others and might pick up on the changes automatically, but best to not rely on this as much as possible.