Closed Fedora-Core closed 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.
That's going to be the same problem with any of his solutions. Without encryption, it's going to stay like that...
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.
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).
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:
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.
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.
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
).
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. :)
@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.
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.
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).
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)
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).
@Fedora-Core Have you checked out the latest dev versions of Pi-hole and the web interface?
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.
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?
@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. :)
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, 😃
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.
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 :)
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 (!isset($_Session['login'])){ header ( 'location: admin/login.php')}
If user forget password they can open up the sqlite db and add a new one in manually.
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:
Did you implement XSRF protection?
I'm a bit behind on websec terminology.. but if CSRF is the same thing, then yes!
@PromoFaux Sorry yes, it is :) Sometimes people write "X" for "Cross" in an attempt to be hip ;)
I gave up on being hip as soon as I turned 30. XD
These issues should be fixed for now.
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
Greetings, F.C.