[Firehol-support] Insecure source port handling (see request-ID 927532)

Wojtek Sczygiol sczygiol at konvulsator.kicks-ass.org
Wed Aug 4 12:24:25 BST 2004


Hi Costa,

while tweaking my firehol.conf today I stumbled across the
same bug again. I still believe that there is a flaw
in firehol's current rule generation logic which could be
easily(?) eliminated. Just...

  "Ignore the source ports from service definitions when
   creating REJECT/DROP/deny rules."

-- As suggested in the original bug report on Apr, 1st
    (No, it wasn't an April Fool's joke :-)

Let me first answer your posting and then explain why.

 >Thanks for notifying this. FireHOL cannot be used for POLICY
 >ACCEPT/DROP EXPLICITLY type of firewalls. I have changed the
 >documentation of the policy command in the CVS to explicitly
 >state this.

But why can't firehol be used for that??
The *only* reason I see is that firehol honors source
ports in incoming REJECT/DROP/deny rules which makes it
vulnerable. Apart from that it could *perfectly* be used
for POLICY-ACCEPT/DROP-EXPLICITLY setups.

 >Policy accept has been designed to save time in cases you
 >really trust the hosts that can access this interface. It
 >has not been designed to change the mode of operation of the
 >firewall.

Ok, but in that case the policy command is misleading.
Almost every good book or web site about IT security in
general and firewalls in particular teaches us that firewalls
or (packet) filters can either be operated in
   1) default-accept/explicit-reject mode
or
   2) default-reject/explicit-accept mode
Linux netfilter (as almost any other firewall "application")
adopts this doctrine by providing a way to set a default
policy, e.g. with "iptables -P".
I believe it is reasonable to expect firehol to behave the
same way when it provides something like a "policy accept"/
"policy reject" switch.

 >Well, FireHOL creates a bi-directional firewall, meaning
 >that it protects BOTH the server and the client. In fact,
 >FireHOL does not know which one is protecting at any given
 >time. It just sets up the rules to match the traffic in both
 >directions, and actually the only difference between client
 >and server statements, is the the input/output are reversed.
 >Everything else is the same.

Quite right. An iptables parameter snippet like
   -p tcp --sport 1024:65535 --dport 80 \
   -m --state NEW,ESTABLISHED
matches outgoing client as well as incoming server http
connections. But the moment you put it in the INPUT chain
it becomes an uni-directional rule that *only* matches
incoming connections. (In the FORWARD chain it depends on the
iface/oface parameter but it's also distinguishable.)
So at this point of time firehol *does* know whom it's
protecting.

 >In your example:
 >
 >attacker.host:499 --TCP-SYN--> target.host:111
 >
 >you have assumed that you protect the portmap server. But
 >this:
 >protected.host:499 --TCP-SYN--> attacker.host:111
 >
 >really means that we have to check the source ports too.

Hm? Why should firehol protect the attacker's portmap here?
I don't quite understand this example.

 >Why to protect clients?
 >FireHOL protects clients to tighten the security even more.
 >Even if an attacker finds an application vulnerability and
 >manages to get some kind of access on the host, he will be
 >able to do only what the firewall allows. Nothing more. This
 >means that even if the attacker enters a host, if he/she
 >cannot stop the firewall, or if the firewall is running on
 >another dedicated box, he will not be able to do much using
 >the network. This is why I discourage all FireHOL users to
 >use "client all accept" on production servers.

While I agree on the need to enforce security policies on
outgoing/client connections, I disagree on relying on
information which can be easily manipulated by an attacker.
Now let's analyze the two intrusion scenarios:

1) vulnerable daemon and firehol run on the same host (1 box)
  a) daemon runs as root (uid=0)
  We're out of luck! Attacker will simply disable the firewall
  altogether.

  b) daemon runs as non-root (uid!=0)
  Attacker cannot bind ports <1024 but he doesn't have to
  anyway. If he wants to download more exploits or rootkits
  from his evil webserver to gain root access he can do so.
  firehol's source port check won't stop him because the
  service definition for http (like 99% of all the services
  definitions) allows any client port between 1024 and 65535!
  No luck again.

2) vulnerable daemon and firehol run on different hosts
  Attacker cannot disable the firewall even when he has root
  access on the application server box. But he can bind any
  port he likes and we basically have the same situation as in
  1b).

 >So, FireHOL cannot be used for ACCEPT EVERYTHING-DROP
 >EXPLICITLY firewalls. Only for DROP/REJECT EVERYTHING-ACCEPT
 >EXPLICITLY ones. I have updated the documentation (on CVS)
 >to emplasize that.

Well, even with DROP/REJECT EVERYTHING-ACCEPT EXPLICITLY
there's an ugly problem. It's not dangerous but it's
bothering:

firehol logs all packets which don't match any rule so the
sys admin can monitor the syslog and "decide if each entry
was something useful" as
http://firehol.sourceforge.net/trouble.html states.
This is a reasonable practice.

But now suppose I'm sick and tired of having my syslog
spammed with the countless connection attempts to port 445
and I don't even have a service listening on that port.
I would expect that adding an explicit
"server microsoft_ds reject"
to my external interface definition which has "policy reject"
by default would prevent firehol from logging this kind of
traffic because now it does match a rule and is silently
rejected.
However, my syslog is still spammed with packets that have
sport=12 and dport=445. I know that the source port is
"illegal" here but it's obvious that somebody tries to connect
to my win2k-smb service and, in case of doubt, if there was a
server listening on port 445 it most likely wouldn't even care
about the source port and would accept this connection.
So I think firehol shouldn't care either and ignore the source
port if *but only if* it generates reject rules.

In case of accept rules I completely agree with you that we
have to check source ports as well. Even though it's a weak
protection because most services use 1024-65535 it is the
Right Thing to do.
We would see suspicious log messages if e.g. an internal
client tried to initiate a connection to an external (web)
server form an unusual port.

As for now I have set DEFAULT_CLIENT_PORTS="0:65535" but this
is only an ugly hack. It strenghens server protection rules
but weakens client protection rules.

Ok, enough for now. I look forward to hear your comments.


firehol-bugs at konvulsator.kicks-ass.org


PS: Despite my objections I'm still convinced firehol is the
best iptables-rule-generator out there and I really appreciate
your work and the work of all the other contributors. :-)





More information about the Firehol-support mailing list