mikaku / Monitorix

Monitorix is a free, open source, lightweight system monitoring tool.
https://www.monitorix.org
GNU General Public License v2.0
1.1k stars 166 forks source link

Information leakage when using monitorix http server #147

Open ghost opened 8 years ago

ghost commented 8 years ago

If you grant write permissions to all in the imgs folder (where the png files are generated), a non-privileged user can install a symlink under the directory and target sensitive data, then read the data through the bundled web-server.

Imagine ~/monitorix/www/imgs has 777 permissions, then you should be able to perform the following with a non-privileged user:

cd /var/lib/monitorix/www/imgs && \
rm -f fs01z.1day.png && \
ln -s /etc/shadow fs01z.1day.png && \
curl http://localhost:8080/monitorix/imgs/fs01z.1day.png

And retrieve the contents of the /etc/shadow file, despite that file its read only for root.

I know the ideal should be to have the folder with permissions only to the owner of the http server, but I think the script shouldn't let the end-user perform the steps above and read files that shouldn't.

mikaku commented 8 years ago

Hi,

Despite the fact that the example is not valid (since you are unable to read a file with root only read permission even following a symbolic link), the flaw is valid for any other file with sensible information if it's world readable (i.e: /etc/passwd).

I guess you are referring to the following line in the docs/monitorix.spec file:

%attr(777,root,root) %{_localstatedir}/lib/monitorix/www/imgs

If so, that only affects Monitorix installations using (or based to) the RPM package from the Monitorix web site (like Debian), not the RPM package from Fedora or EPEL repositories.

Please, confirm this and I'll modify that line.

ghost commented 8 years ago

The example is valid, if you follow the steps to create a symlink and use curl to access the png file (that its now a symlink), you get the contents of the file that its pointing to.

My guess is that the issue might come from lib/HTTPServer.pm and the user that runs the httpd server daemon (the monitorix one, not any external like Apache or lighthttpd). I don't have access to a Linux box right now, but I will add a capture later to illustrate the issue.

mikaku commented 8 years ago

The built-in HTTP server in Monitorix is executing under the user nobody (unless you changed it) so, it shouldn't have access to read that symbolic link.

ghost commented 8 years ago

I've been able to reproduce the issue (see the attached capture). The monitorix httpd configuration its as follows:

<httpd_builtin>
        enabled = y
        host = 192.168.56.101
        port = 8080
        user = nobody
        group = nobody
        log_file = /var/log/monitorix-httpd
        hosts_deny =
        hosts_allow =
        <auth>
                enabled = n
                msg = Monitorix: Restricted access
                htpasswd = /var/lib/monitorix/htpasswd
        </auth>
</httpd_builtin>

I've done a ps and you can see that it's truly running as nobody, but doing the commands typed above, I'm able to link sensitive data and see it through the builtin http server.

capture

mikaku commented 8 years ago

It looks like your /etc/shadow is world readable since I'm unable to reproduce in my CentOS 6.7:

[mikaku@linux /var/lib/monitorix/www/imgs]$ l /etc/shadow
----------. 1 root root 1286 Dec 22  2014 /etc/shadow
[mikaku@linux /var/lib/monitorix/www/imgs]$ cd /var/lib/monitorix/www/imgs/ && rm -f system1.1day.png && ln -s /etc/shadow system1.1day.png && curl http://localhost:8080/monitorix/imgs/system1.1day.png
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
The requested URL &#x2F;monitorix&#x2F;imgs&#x2F;system1.1day.png was not found on this server.<p>
<hr>
<address>Monitorix HTTP Server listening at localhost Port 8080</address>
</body></html>
[mikaku@linux /var/lib/monitorix/www/imgs]$ 

Now the same example with /etc/passwd which is indeed a world readable file:

[mikaku@linux /var/lib/monitorix/www/imgs]$ cd /var/lib/monitorix/www/imgs/ && rm -f system1.1day.png && ln -s /etc/passwd system1.1day.png && curl http://localhost:8080/monitorix/imgs/system1.1day.png
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
[...]
ghost commented 8 years ago

I've created a new user just for the test and I'm able to reach the file despite the user doesn't belong to the file group. The file has 640 permissions for root:root. I believe I shouldn't be able to reach it through the web server, since I'm not unable to perform a cat of the file. capture2

I've seen your file doesn't have any permissions, so I did also another test, changing the permissions from 640 to 600. If the file has 640, any user its able to view them through the httpd server, but if the file has only permissions for the user (not group, nor others), the user isn't able to see it. capture

Could you please see if you're able to reproduce the issue from your side by doing chmod 640 /etc/shadow and running the command I typed in the first post?

IzzySoft commented 8 years ago

@Silmano could you please check in your /etc/group if you haven't accidentally added nobody (the user running your Monitorix process) to the root group? grep -e '^root:' /etc/group should do that. I don't see another way how your described behaviour could happen.

Also, in the first screenshot of your last comment you let the "dummy" user do an cat /etc/shadow and it gets refused ("permission denied"). What happens if you do the same cat as "dummy" on the symlink, to make it comparable?

One more thing you could check: sudo -u nobody "cat /etc/shadow" (and the same for the symlink). If that gives the content of the file, you can't blame Monitorix for it :)

mikaku commented 8 years ago

@Silmano,

Could you please see if you're able to reproduce the issue from your side by doing chmod 640 /etc/shadow and running the command I typed in the first post?

Since /etc/shadow is owned as root:root having a permission like 640 won't have any effect:

[mikaku@linux /var/lib/monitorix/www/imgs]$ l /etc/shadow
-rw-r-----. 1 root root 1286 Apr 21 09:18 /etc/shadow
[mikaku@linux /var/lib/monitorix/www/imgs]$ cd /var/lib/monitorix/www/imgs/ && rm -f system1.1day.png && ln -s /etc/shadow system1.1day.png && curl http://localhost:8080/monitorix/imgs/system1.1day.png
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
The requested URL &#x2F;monitorix&#x2F;imgs&#x2F;system1.1day.png was not found on this server.<p>
<hr>
<address>Monitorix HTTP Server listening at localhost Port 8080</address>
</body></html>
[mikaku@linux /var/lib/monitorix/www/imgs]$ 

Indeed.

As @IzzySoft suggested, check the supplementary groups of your nobody user.

ghost commented 8 years ago

I've checked the /etc/group file and nobody isn't there. In fact I'm unable to perform a cat neither to the direct file nor the symlink, but I'm able to retrieve the data via curl. capture02

Another thing that I don't know if it has something to do its that upon starting the machine, the service starts by itself. If I try to do a curl like above, I get the 404 correct message, but if I restart the service without changing anything, I'm able to access the file despite I wasn't able to do it before. capture03

I've checked the process and it starts with the same user, and from the logs I see the same messages as when I start the machine:

### Start of the server
Thu Apr 21 20:42:59 2016 - Starting Monitorix version 3.8.1 (pid 1992).
Thu Apr 21 20:42:59 2016 - Loaded main configuration file '/etc/monitorix/monitorix.conf'.
Thu Apr 21 20:42:59 2016 - Initializing graphs.
Thu Apr 21 20:43:00 2016 - Generating the 'index.html' file.
Thu Apr 21 20:43:00 2016 - Started built-in HTTP server (pid 2043).
Thu Apr 21 20:43:00 2016 - Ok, ready.
Thu Apr 21 20:43:00 2016 - WARNING: the built-in HTTP server has authentication disabled.
HTTPServer: You can connect to your server at http://localhost:8080/
### Restart monitorix process
Thu Apr 21 20:43:38 2016 - SIGQUIT caught.
Thu Apr 21 20:43:38 2016 - Exiting.
Thu Apr 21 20:43:38 2016 - Starting Monitorix version 3.8.1 (pid 2291).
Thu Apr 21 20:43:38 2016 - Loaded main configuration file '/etc/monitorix/monitorix.conf'.
Thu Apr 21 20:43:38 2016 - Initializing graphs.
Thu Apr 21 20:43:38 2016 - Generating the 'index.html' file.
Thu Apr 21 20:43:38 2016 - Started built-in HTTP server (pid 2342).
Thu Apr 21 20:43:38 2016 - Ok, ready.
Thu Apr 21 20:43:38 2016 - WARNING: the built-in HTTP server has authentication disabled.
HTTPServer: You can connect to your server at http://localhost:8080/

Also sudo -u nobody /etc/shadow gives me permission denied. The id of nobody and its behavior at OS level seems to be fine:

vagrant@BOX /var/log $ id nobody
uid=65534(nobody) gid=65534(nobody) groups=65534(nobody)

I'm also attaching my ´monitorix.conf´ file, in case I've configured something wrong. Its as .conf in the server, but GitHub doesn't like it and I've renamed to .txt: monitorix.txt

mikaku commented 8 years ago

Another thing that I don't know if it has something to do its that upon starting the machine, the service starts by itself. If I try to do a curl like above, I get the 404 correct message, but if I restart the service without changing anything, I'm able to access the file despite I wasn't able to do it before.

Weird.

Please, check (using ps) the user under the built-in HTTP is running on right after start your machine, and compare it once you restarted Monitorix.

Also, make sure you don't have an extra configuration file for Monitorix with a different setup for the built-in HTTP server.

Your monitorix.conf file looks OK to me.

ghost commented 8 years ago

I've done the test and I can't find any difference between the after and before. Not in the httpd process nor the daemon process and the configuration that launches it capture

Any other idea or suggestion to check?

mikaku commented 8 years ago

Can't reproduce this here (Linux CentOS 6.7 64bit).

I'm running out of ideas. I'd suggest you to test this on a fresh new system (real hardware preferably, or KVM virtualization) and let us know.

Thanks.

ghost commented 8 years ago

Thanks for the info. I did the tests in a VM box and in my server and I can reproduce the issue from my side. Maybe it has something to do with the OS...

IzzySoft commented 8 years ago

In that case it might be useful if you mention which one it is – or did I just miss that? Just skimmed through the entire issue, but I couldn't find it.

mikaku commented 8 years ago

@IzzySoft,

No, you don't missed it, he just didn't mention it. But I think it's Gentoo since he filed some bugs and updates in the Gentoo package related to Monitorix.

(but maybe I'm wrong)

ghost commented 8 years ago

Sorry for the late response. I didn't specified because I wasn't aware that the bug might be OS specific instead. As @mikaku has stated, its Gentoo. I have both a live version and a VM one and I'm able to reproduce the issue on both, so I think something its messing with the daemon and making it restart with higher privileges than it should have.

mikaku commented 8 years ago

@Silmano,

It looks like something specific in Gentoo since I was unable to reproduce that behavior on any of the CentOS Linux I have here.

I can't tell if this is reproducible in Debian/Ubuntu systems (I don't use them), but @IzzySoft might be able to shed some light on this.

In the meanwhile, you might want to check the process restarting system in Gentoo to see if there is an option that disables that behavior.

Thanks.

IzzySoft commented 8 years ago

I don't use the internal web server on most machines. On the one I've tested (Debian Wheezy), I just get a 404, even after a restart. So I cannot reproduce it either.

mikaku commented 7 years ago

@Silmano

Also sudo -u nobody /etc/shadow gives me permission denied.

I realized now that this command is wrong, you are trying to execute a file that don't has the proper execute permission bits. If you try the same with any other file even writeable for you but without execution permission files, you'll get the same message.

This means that we still don't know if the user nobody in your system has a special treatment. Regards.