pi-hole / web

Pi-hole Dashboard for stats and more
https://pi-hole.net
Other
2.04k stars 558 forks source link

Possible Future Security Breach Warning #39

Closed Fedora-Core closed 8 years ago

Fedora-Core commented 8 years ago

The future maintenance functions of the /admin/ website can be reached from the outside !

[PANIC SWITCH] ---------- [ON]

The IT-gurus, employed by the multi-million-dollar advertising industry (that we sabotage), can - in the future - 'whitelist' their domains with something like the following : <img src="http://adserver.com/admin/php/add.php?list=white&domain=adserver.com">

Pi-Hole is Open-Source, and the GitHib development branch is visible by everyone, including by these IT-gurus of the advertising industry.

---------- Request => Please 'harden' the Pi-Hole admin webserver.

2 Possible solutions => One for Short-Term, and One for Long-Term.

Solution 1° - Short-Term { Add username / password Authetication. }

From the github / pi-hole / wiki = https://github.com/pi-hole/pi-hole/wiki/Nginx-configuration-instead-of-the-default-lighttpd-and-php-cgi-option

From the jacob salmela blog = http://jacobsalmela.com/password-protect-a-lighttpd-web-server-on-a-raspberry-pi-using-mod-auth/

Solution 2° - Long-Term { Run each of the Pi-Hole-appliance's services on individual Static IP-addresses. }

A) Give the RaspberryPi's 'main' interface a Static IP-address for SSH and other softwares. Bonus: this main Static IP-address remains free for other appliances (cloud, web, streaming,...) Note : we have seen this requirement on several fora by people who want to run other stuff too.

B) Give the Pi-Hole-appliance's DNS server another Static IP-address for the DNS resolution. Bonus: this is the only Static IP address that the user's router must know.

C) Give the Pi-Hole-appliance's 'adblock' Webserver - and future miniDLNAserver - yet another Static IP-address, and adapt the gravity script accordingly. (No more dynamic-searching for the IP). Bonus: the user of the Pi-Hole-appliance can run other webservers on the main interface Static IP-address - see A). Optional Bonus: a full-fledged webserver, crippled with Rewrite-Rules, is no longer required. A simple webserver in Perl, or in Python2, or in Python3, or even in command-line PHP, can simply reply with the HTTP header '204 No Content'. ° This new Static IP-address must not be known by anybody but: the gravity script that feeds the DNS server's configuration file.

D) Give the Pi-Hole-appliance's 'admin' webserver yet another Static IP-address. Bonus: Cutting-off the outside world. Problem solved. Bonus: No need for /admin/ in the URL. It can be the document-root for this webserver. Bonus: No need for yet another username / password to remember. (But may be optional.) ° This new Static IP-address must be known only by the 'administrator' of the Pi-Hole-appliance.

Optional => E) Disable (not un-install) the dhcp-client-daemon(s), the assumption being that we run a 'server'. F) Use the '/etc/network/interfaces' again to declare the multiple Static IP-addresses, this time by using the 'ip' utility from the 'route2' package. Raspbian Jessie already includes the statement 'source-directory /etc/network/interfaces.d'

Conclusion: Yes, We Can.

[PANIC SWITCH] ---------- [OFF]

Note: why I used the term 'Pi-Hole-appliance' => Quote from the githib / AdminLTE / New admin features (idea) #24

jacobsalmela commented 3 days ago If we ever want to commercialize anything, ....

Greetings, F.C.

--- Want to back this issue? **[Post a bounty on it!](https://www.bountysource.com/issues/31023975-possible-future-security-breach-warning?utm_campaign=plugin&utm_content=tracker%2F20311099&utm_medium=issues&utm_source=github)** We accept bounties via [Bountysource](https://www.bountysource.com/?utm_campaign=plugin&utm_content=tracker%2F20311099&utm_medium=issues&utm_source=github).
PromoFaux commented 8 years ago

I'm pretty sure it was just given as an example. What he's saying is that if the password is intercepted, somehow, the function can be run.

AzureMarker commented 8 years ago

That's going to be the same problem with any of his solutions. Without encryption, it's going to stay like that...

AzureMarker commented 8 years ago

I don't think that there's enough features to split between home and enterprise. With #53 this issue may be solved until we move to redirecting ads to an empty server or port or something.

ryt51V commented 8 years ago

I've just been reading through this issue, https://github.com/pi-hole/pi-hole/pull/354, and https://github.com/pi-hole/AdminLTE/pull/49

In those pull requests, it looks like we're rolling our own password protection, which usually means spending a lot of effort on writing and maintaining that's likely to have some flaw compared to something prebuilt we can use that's been written by a netsec team whose code has been well looked over by the FLOSS community.

https://github.com/pi-hole/pi-hole/pull/360 and https://github.com/pi-hole/AdminLTE/pull/53 also - my first thought was "Wait, why not bcrypt?" then "Wait, why not salt it?", followed by "Wait, I'm not even remotely netsec, surely there's even more missing than the basics I've read repeatedly on Ars Technica?"

Forgive me but I must be missing something - is there a reason we're not using lighttpd's mod_auth? I can see @Fedora-Core already mentioned lighttp's mod_auth in passing. (Ironically Googling "lighttpd mod_auth" brings up Jacob's article as the second result.) We know it will be relatively reliable, and there are quite a few options on how we encrypt the password, plus digest auth.


On another note:

Another option: we run it on a different virtual host. I don't know lighttpd as well as apache, but I understand it can support virtual hosts just fine. The result would be, for example http://mypiholeadmin/admin, takes you to the admin interface, whereas going to http://myadserver/admin takes you to the blocking vhost. Since we control DNS this is easy to add to the hosts file or 01-pihole.conf.

First of all the ad provider would need to use a domain that isn't their own to try to trick the pi-hole, e.g. <img src="http://piholeadmin/admin/php/add.php?list=white&domain=adserver.com">, which is bad form for them (not sure how non-pi-hole users' browsers will react to that) and I'm sure some ad networks wouldn't even allow. EDIT: Heh, we could even make it a globally routable domain (e.g. http://piholeblocking.cheaptld), register it ourselves and put some code - non-malicious but messes up the page for non-pihole users? Big ad wouldn't want to link to it then!

If we want, similar to the subdir idea we could ask the user for a domain to obfuscate it a bit - e.g. http://mypiholeadmin9725. EDIT: Or we could use the actual pi's hostname for this? Different for every user but they should know what it is.

Also, I believe would allow us to specify lighttpd options specific to the admin interface more easily than with a subdirectory, in particular mod_auth. It would also simplify the blocking vhost (regex wouldn't have to accommodate /admin).

ryt51V commented 8 years ago

Also, I'm just thinking of a few things we can do to stop embedding. I doubt we can fully harden it this way and in any case I'm still strongly in favour of passwording the interface, but just food for thought:

PromoFaux commented 8 years ago

it looks like we're rolling our own password protection

It's there, but I personally am not happy with it. It's a workaround/hack to put off an issue, but it's there.

At the moment the whitelisting from the website is being put on hold whilst we work on the refactor, so there is plenty of oppurtunity to get this aspect of things nailed down. I still think the separate port idea is the simplest solution.

ryt51V commented 8 years ago

It's there, but I personally am not happy with it. It's a workaround/hack to put off an issue, but it's there.

I know password protection wasn't considered until this issue was raised. But, done right, is it not a good idea as a permanent feature? IMO it's something we ought to have as standard anyway.

Password aside, in terms of separating the admin interface, your separate port idea is my second choice and I agree that it's by far the simplest to implement and maintain.

DonLexos commented 8 years ago

I like the own hostname idea, or running it on a (non existent) domain. What if the domain would be the non existent adminconsoleformypihole.pi. We can resolve this ourselves and in combination with what @ryt51V mentioned it could resolve to somewhere in /var/www/html/whatever that is not accessible through blockeddomain.com/admin/ (or http://192.168.1.xx/admin).

PromoFaux commented 8 years ago

Sorry, @ryt51V I meant in terms of rolling our own. Self-rolled authentication/security/encryption of any sort is generally a bad idea!

I really like @Fedora-Core's suggestion of multiple IPs, but it's a bit beyond my understanding of how things work! Which is why I ended up thinking about separate ports instead. :)

ryt51V commented 8 years ago

@PromoFaux Ah, right, thanks for clarifying. This is why I'm a bit confused in the first place - AFAIK using lighttpd's mod_auth in the first place would not only have been better but also quicker and easier. i.e. A quicker ugly hack, except not ugly and not really a hack.

I think multiple IPs for each service are ideal, but are not appropriate for an auto install script, both now and after this project has matured. Ports, vhosts and subdirs are far more suitable.

looterz commented 8 years ago

I noticed pi-hole had no authentication for the web panel when installing today, and im also not really a fan of lighttpd. So, I moved it over to nginx and setup a simple basic_auth user:pass setup, nothing fancy but it works. Definitely agree on the separate static ip solution for long-term security, though.

For even better security for the web service (although probably overkill) you could setup HTTPS Client Authentication so that only the administrator of the pi-hole with the certificate can interact with the web service.

DanTup commented 8 years ago

I haven't read all of the comments here, but is this not just XSRF ("Cross Site Request Forgery")?

XSRF is a common issue - eg. if I'm logged into my bank and then I visit a malicious site, what's to stop them outputting a form with hidden fields and auto-posting to my banks transfer form to steal my money?

There's some info in this here:

https://en.wikipedia.org/wiki/Cross-site_request_forgery

One fix is basically to make sure all whitelists requests get a random value (token) entered into the form when the HTML is rendered and when submitted to the server, validate that that token is correct. Here's what it looks like in aspnet mvc (I know you don't use that, just the one I'm most familiar with).

DanTup commented 8 years ago

May also be worth reviewing CSP and locking down anything else that shouldn't be allowed. And X-Frame-Options to ensure the control panel can't be loaded inside a frame on a site (eg. to be click-jacked).

Edit: Oh, I see a lot of this is already being discussed in #444! :)

Edit (Mcat12): Corrected link (It was going to an issue on almasaeed2010's AdminLTE)

AzureMarker commented 8 years ago

Yep, actually just implemented the token on the whitelist branch and X-Frame-Options on the other repo (that's where the server configs are).

AzureMarker commented 8 years ago

@Fedora-Core Have you checked out the latest dev versions of Pi-hole and the web interface?

Fedora-Core commented 8 years ago

Open Source is great ! If one dares to open the source...

Yes, I have followed the development branch.

And now you have introduced a "source" for far more serious issues => concurrency !

What if father Abe is blacklisting a bunch of porn domains for his little daughter, and his son Ben is busy whitelisting a newschannel, and his son Carl is busy whitelisting a gamesportal, all at the same 2 second interval ? Since that's the time-frame that the script typically needs to finish on a bare Raspberry-pi.

And a pihole running in a college dorm has probably several adminweb-users...

Problem = concurrency !

Don't tell me that you will instruct the pihole adminweb-users not to do this... Don't tell me that you will instruct the pihole installers not to give the adminweb away...

Once your software is in the wild, you have strictly no control over it's use. Your development needs to be 100% foolproof.

This is about delegation of duty, and also - I'm not going into it - elevation of privileges.

Proposal: The PHP must accept the request from the adminwebuser, and pass it on to another process. That other process should - independently - execute all the accumulated request that have been queued in a very well defined - and publicized - time-slice. Don't look at the PHP semaphores, they are in fact a form of mutex. Don't look at the PHP queues, they use shared-memory (don't know how Docker likes that) Don't try to install another package for queueing, most require too much effort. There is a very simple solution to tackle this. ° A cron job (a one minute interval would do just fine) ° A subdirectory "arriving" with write access for www-data ° A subdirectory "arrived" with write access for www-data and the cron job ° A subdirectory "accepted" with write access for the cron job ° A subdirectory "iamalreadyandstillbusy" with write access for the cron job ° Elevated privileges for the cron job only (SignalHangUp towards DNSMasq) ° etc

Get inspired ;-)

Yes we can!

note:

The English language has this expression: Eating_your_own_dog_food About Feb 19, 2016 => I have immediately (19) implemented my own proposed short term solution. I'm safe. I have during the following week-end (20-21) implemented my own proposed long term solution. I'm very safe.

dschaper commented 8 years ago

Re: Docker, Is it the Docker way to have a container that includes both a DNS Resolver and a web server? Wouldn't the concept of microservices dictate that two separate containers be used and Compose them together? Or if using a recent Docker version, advertise the services?

AzureMarker commented 8 years ago

@Fedora-Core What about using a database for the queue? We are currently experimenting with sqlite with the Python rewrite and it's going well. PHP could add to a queue and then call a pihole script that would run through it. Just thinking out loud here. :)

dschaper commented 8 years ago

Would that just put the race in a different queue though? Not really solving the concurrency unless you lock the database for access and then it's just pushing the the issue to another thread.

Speaking of which, would you folks be okay with a new issue for concurrency discussions. Don't want to have this single issue addressing two separate themes... Yeah, I'm a little AR about that kind of thing, 😃

AzureMarker commented 8 years ago

A new issue would be good. But about the database, it could have an auto incrementing id, and the program would go from lowest to highest id. Therefore when a new action gets into the queue, it'll be handled by the program after all the other actions get handled. I'm pretty sure sqlite would be able to handle concurrency, as this mentions that it locks the database during writes.

dschaper commented 8 years ago

Okay, I was thinking Race versus Concurrency. User A blacks a domain while User B whites the same domain in the same update cycle. I'm still fighting with even needing an external database with Python, just using all internal data structures and exposing via API or interfaces. But that's yet another Issue :)

viemmsakh commented 8 years ago

I'm a little late to this conversation, but would a simple sqlite db with session variables work? Seems like that would be a pretty easy fix to add user authentication to pages that need it without needing to overhaul too much.

If user forget password they can open up the sqlite db and add a new one in manually.

AzureMarker commented 8 years ago

Thanks for your concern @viemmsakh. :smile: In the latest version we've implemented session variables in the security-focused php (whitelisting and blacklisting) that verifies that only the web interface is able to activate those actions. We've also made sure that the web interface can't be used in an IFrame (tricking users to whitelist the ad one way or another). We're still not sure whether or not we should add a login page for the web interface (or parts of it), but we'll keep your idea in mind. :+1:

DanTup commented 8 years ago

Did you implement XSRF protection?

PromoFaux commented 8 years ago

I'm a bit behind on websec terminology.. but if CSRF is the same thing, then yes!

DanTup commented 8 years ago

@PromoFaux Sorry yes, it is :) Sometimes people write "X" for "Cross" in an attempt to be hip ;)

PromoFaux commented 8 years ago

I gave up on being hip as soon as I turned 30. XD

AzureMarker commented 8 years ago

These issues should be fixed for now.