Project

General

Profile

Bug #708

Need more checks for dns rebind issue

Added by Scott Ullrich almost 9 years ago. Updated almost 8 years ago.

Status:
Resolved
Priority:
Normal
Assignee:
-
Category:
Web Interface
Target version:
Start date:
07/01/2010
Due date:
% Done:

0%

Estimated time:
Affected Version:
All
Affected Architecture:

Description

I just committed a change for --stop-dns-rebind on dnsmasq but we need to go a bit further on our checks in auth.inc:

The --stop-dns-rebind option for DNSMasq is definitely a good one to enable,
but I would also suggest validating HTTP host headers. If the router
receives an HTTP request and the Host header doesn't match the router's IP
address or host name (assuming it has a host name), then it should block the
request or redirect the client to an error page.

Associated revisions

Revision ce46b5da (diff)
Added by Scott Ullrich almost 9 years ago

More dns-rebind checks. Ticket #708

History

#1 Updated by Chris Buechler almost 9 years ago

  • Category set to Web Interface
  • Target version changed from 1.2.3 to 2.0

This is a good addition for dnsmasq, there are a couple issues with this in general though.
1) The dnsmasq change breaks some RBLs. maybe an advanced checkbox to disable that?
2) You can't rely on referrer without breaking things, specifically:
- those who use scripts to do things, such as deleting MAC addresses from the passthrough MAC list, scripting backups, and other things.
- those who use reverse proxies or SSH port forwarding to access systems.
both of those cover a lot of people

#2 Updated by Bill Marquette almost 9 years ago

Something like this is the likely fix in auth.inc

if ($_SERVER['HTTP_HOST'] != $config['system']['hostname'] or
    $_SERVER['HTTP_HOST'] != $_SERVER['SERVER_ADDR'] or 
    $_SERVER['HTTP_HOST'] != $_SERVER['SERVER_NAME'] ) {
    display_error_form("501", "DNS Rebind attack detected, see http://en.wikipedia.org/wiki/DNS_rebinding");
    exit;
}

#3 Updated by Bill Marquette almost 9 years ago

Chris Buechler wrote:

This is a good addition for dnsmasq, there are a couple issues with this in general though.
1) The dnsmasq change breaks some RBLs. maybe an advanced checkbox to disable that?

dnsmasq has two other options...the --rebind-localhost-ok is probably ok by default
--rebind-localhost-ok
Exempt 127.0.0.0/8 from rebinding checks. This address range is returned by realtime black hole servers, so blocking it may disable these services.
--rebind-domain-ok=[<domain>]|[[/<domain>/[<domain>/]
Do not detect and block dns-rebind on queries to these domains. The argument may be either a single domain, or multiple domains surrounded by '/', like the --server syntax, eg. --rebind-domain-ok=/domain1/domain2/domain3/

2) You can't rely on referrer without breaking things, specifically:
- those who use scripts to do things, such as deleting MAC addresses from the passthrough MAC list, scripting backups, and other things.

Not referrer, Host: header (and scripts can define referrers anyway...anyone relying on those for security has a hole in their head).

- those who use reverse proxies or SSH port forwarding to access systems.
both of those cover a lot of people

I don't think so. Fix your reverse proxy so it sends the correct Host header (it's not hard to do). As for SSH port forwarding, use the SOCKS proxy feature of SSH and problem is solved, or modify the code I sent to allow 127.0.0.1 as another valid host header.

--Bill

#4 Updated by Scott Ullrich almost 9 years ago

  • Status changed from New to Feedback

Thanks Bill, I committed these changes to dnsmasq and to auth.inc.

#5 Updated by Anonymous almost 9 years ago

Hello,

I'm new here, but I wanted you to know this DNS rebind check had to be commented out in order to get the captive page working.
$_SERVER['HTTP_HOST'] returned the host the browser was calling when not yet authenticated to the captive page.

,,
WT

#6 Updated by Peter Baumann almost 9 years ago

I can confirm that I also had to comment out this DNS rebind code in /etc/inc/auth.inc so that I could login.

#7 Updated by - BlackB1rd - almost 9 years ago

DNS domain forwarding no longer works, log says: possible DNS-rebind attack detected. I used this function to forward domains through OpenVPN.

#8 Updated by Scott Ullrich almost 9 years ago

I would like to thank Craig Heffner for bringing this issue to our attention.

#9 Updated by Josh Stompro almost 9 years ago

Hello, I needed it remove the --stop-dns-rebind option from the dnsmasq section of /etc/inc/services.inc to enable the ability to do dns lookups to our internal split dns. In my case the captive portal looked to be behaving strangely because the after auth forward to our home page was triggering the rebind attach warning, so the dns lookup would just fail, leaving the browser to just report a lookup error. Would it be acceptable to be able to disable this feature on the dns forward service page?

The setup I'm dealing with is this.

Internet <-> Ipcop firewall <-> 192.168.x.x network <-> Pfsense <-> laptop

We have a split dns, so when dnsmasq on pfsense gets a query for our domain, it should get passed to our ipcop firewall, which returns a 192.168.x.x address, which trips the rebind logic. It will probably work fine with the rebind stuff enabled once I'm done setting up the pfsense firewall and deploy it.

#10 Updated by Scott Ullrich almost 9 years ago

Do you have an entry in the DNS Forwarder to forward the domain? If not try adding one.

#11 Updated by Josh Stompro almost 9 years ago

Scott Ullrich wrote:

Do you have an entry in the DNS Forwarder to forward the domain? If not try adding one.

Scott, I assumed that setting the DNS forward to forward the domain would override locally set DNS entries. I want the firewall to override certain entries before they get sent on to our authoritative domain server. I have shortcuts setup, like printer1.example.com always pointing to the IP of our local printer. So a machine can just connect at any location and print to printer1.example.com and it will work.

For another example, some of our sites have local software deployment caches, (squid reverse proxy) while some do not. All the clients connect to proxy-inventory.example.com. In some sites pfSense has an entry for that host that is local, which causes them to use a local cache, in other sites no local entry is present so the request goes to our main distribution server.

I'll test my assumption and see how it works.
Thanks
Josh

#12 Updated by Chris Buechler almost 9 years ago

  • Status changed from Feedback to Resolved

everything here seems to be reasonable with all the latest changes

#13 Updated by Cyrus Patel almost 8 years ago

The checks won't protect against DNS rebind attacks that run like this:
1. browser makes DNS lookup for <hostname-of-pfsense-box>
2. evil nameserver returns <evil-ip>, + very short TTL
3. browser goes to <evil-ip> and gets served a malicious script
4. browser runs malicious script which makes request to <hostname-of-pfsense-box>
5. TTL expired, so browser again makes DNS lookup for <hostname-of-pfsense-box>
6. evil name server returns <correct-ip>
7. malicious script has access to context of <hostname-of-pfsense-box> since its the same-origin.
In this sequence, the "Host:" field in the browser's requests will always be the expected <hostname-of-pfsense-box>. The current "Potential DNS Rebind attack detected" check won't work.

Also: as of 2.0 RC3 Mon Jul 25 20:30:19 EDT 2011, the message "Potential DNS Rebind attack detected" is somewhat disconcerting in conjunction with the vhosts package. Say, a user browsing to a vhost that happened to forget to add the port number. Or, the pfsense gui running on https and the user accidentally using "https://" instead of "http://" in the URI.

Could the message please be changed to something less specific? e.g. "404 Not found" or "400 Unrecognized request", or more verbosely "412 This webserver does not service requests for $host_name:$host_port".

ps: out of curiosity: why is the rebind checking not implemented as $HTTP["host"] section(s) in lighty.conf?

#14 Updated by Chris Buechler almost 8 years ago

That's impossible because 5 will never happen, browsers' internal DNS caches don't come anywhere near obeying short TTLs. Would also require accepting an invalid cert, which would probably trip up many users as they use an untrusted cert to begin with, but in that case they're ignoring proper deployment of anything HTTPS. If you have patches for improving things, please feel free to open a feature request ticket and attach.

#15 Updated by Cyrus Patel almost 8 years ago

Chris Buechler wrote:

That's impossible because 5 will never happen, browsers' internal DNS caches don't come anywhere near obeying short TTLs.

Yep, DNS pinning makes short TTLs impossible.

But short TTLs is precisely how DNS rebinding works.
When short TTLs are impossible, then DNS rebinding is impossible.
When DNS rebinding is impossible, then the present php code is superfluous.

So yes, in effect the present checks do not protect against DNS rebinding at all. They protects against unrecognized "Host:"s. This is not the same thing as protecting against DNS rebinding.

And yes, as it stands, the present php code looks like an adaptation of something from the late 1990s. It is stuff only appropriate for a narrow window around 1997 (after HTTP 1.1 but before virtual hosts became common), and before user agents began DNS pinning.

I don't understand the point about "proper deployment of anything HTTPS". When HTTPS is properly deployed, there is no need for any additional connection checking. So why mention https?

If you have patches for improving things, please feel free to open a feature request ticket and attach.

Well, it would first be necessary to identify which part needs fixing. The checks leading up to the "DNS rebind detected" message cannot detect DNS rebinds, so either the checks are broken, or the message is.

Second: it would be good to know whether it is really necessary to restrict access to only recognized "host:"s. It doesn't hurt to make this restriction, but it would be good to know whether it also fulfils some purpose.

Third: it would be good to know why those checks are being done by a script, and not via $HTTP["host"] sections in lighty.conf. After all, someone may have had a good reason to do it via script, rather than at a stage before any script gets executed.

Also available in: Atom PDF