Discussion:
RFC: https://bugzilla.redhat.com/show_bug.cgi?id=1174405
Dominick Grift
2015-01-09 21:05:53 UTC
Permalink
https://bugzilla.redhat.com/show_bug.cgi?id=1174405

This is a inconsistency in SELinux
Stephen Smalley
2015-01-09 21:52:18 UTC
Permalink
Ports in the local port range can be auto-assigned by the kernel to
unbound sockets on first use. So it makes no sense to control them,
and there isn't even an LSM hook in the place where such auto-port
selection occurs. Controlling binding to ports is only useful when
the port number is a "name" (i.e. a well-defined value that is
expected to correspond to a specific service), to prevent spoofing of
security-relevant services like sshd.
Post by Dominick Grift
https://bugzilla.redhat.com/show_bug.cgi?id=1174405
This is a inconsistency in SELinux
_______________________________________________
Selinux mailing list
Dominick Grift
2015-01-09 22:19:11 UTC
Permalink
Post by Stephen Smalley
Ports in the local port range can be auto-assigned by the kernel to
unbound sockets on first use. So it makes no sense to control them,
and there isn't even an LSM hook in the place where such auto-port
selection occurs. Controlling binding to ports is only useful when
the port number is a "name" (i.e. a well-defined value that is
expected to correspond to a specific service), to prevent spoofing of
security-relevant services like sshd.
Okay for the sake of argument let's say that makes sense to me. Should SELinux not somehow communicate this to the user.

First we had the scenario where selinux denies and not logs denials (user space object managers) and now we have the scenario where
selinux allows even if there is no rule to allow it

As a policy writer it gave me confidence to know that "if selinux blocks it logs" and that "selinux denies access by default". Now that those things turn out to not be true. Its a black box. voodoo.
Post by Stephen Smalley
Post by Dominick Grift
https://bugzilla.redhat.com/show_bug.cgi?id=1174405
This is a inconsistency in SELinux
_______________________________________________
Selinux mailing list
--
Dominick Grift
eric gisse
2015-01-09 22:22:51 UTC
Permalink
I disagree.

I've had to have technical discussions justifying my belief that
certain common things should be available to all domains such as
/dev/urandom and more recently /proc/sys/vm/overcommit_memory.

Discussions around those reasonable defaults basically rotate around
the philsophical notion of least privilege.

So seeing there's an entire swath of ports that programs can bind to
by default is crazytalk and blows that notion out of the water.

Further, it is bad policy.

Consider sshd, or any other daemon that does nothing but bind to a
port and listen for connections.

It does not need the ability to bind to to anything other than its'
daemon port, not even epheremal ports. Yet it can, regardless of
policy considerations. Which is the underlying point here.

If someone gains access to a server through a compromised service,
they can bind a backdoor to that epheremal range or at least exfil
data.

This is bad, bad, bad and rather surprising because until it was
pointed out by this thread I would not have considered it possible due
to the...vehemence... in which least privilege has been upheld.




On Fri, Jan 9, 2015 at 3:52 PM, Stephen Smalley
Post by Stephen Smalley
Ports in the local port range can be auto-assigned by the kernel to
unbound sockets on first use. So it makes no sense to control them,
and there isn't even an LSM hook in the place where such auto-port
selection occurs. Controlling binding to ports is only useful when
the port number is a "name" (i.e. a well-defined value that is
expected to correspond to a specific service), to prevent spoofing of
security-relevant services like sshd.
Post by Dominick Grift
https://bugzilla.redhat.com/show_bug.cgi?id=1174405
This is a inconsistency in SELinux
_______________________________________________
Selinux mailing list
_______________________________________________
Selinux mailing list
Paul Moore
2015-01-10 03:02:48 UTC
Permalink
I think there is a point of clarification that may help put everyone at
ease... SELinux provides two permissions relevant to socket bind()
operations, bind and name_bind. The name_bind operation controls the
socket's ability to bind to a specific port, while the bind operation
controls the ability of a domain to bind a socket. Those of you who wish
to restrict a domain from performing a socket bind() operation, regardless
of the port, would likely find your answer with the socket:bind permission.

--
paul moore
www.paul-moore.com
Post by eric gisse
I disagree.
I've had to have technical discussions justifying my belief that
certain common things should be available to all domains such as
/dev/urandom and more recently /proc/sys/vm/overcommit_memory.
Discussions around those reasonable defaults basically rotate around
the philsophical notion of least privilege.
So seeing there's an entire swath of ports that programs can bind to
by default is crazytalk and blows that notion out of the water.
Further, it is bad policy.
Consider sshd, or any other daemon that does nothing but bind to a
port and listen for connections.
It does not need the ability to bind to to anything other than its'
daemon port, not even epheremal ports. Yet it can, regardless of
policy considerations. Which is the underlying point here.
If someone gains access to a server through a compromised service,
they can bind a backdoor to that epheremal range or at least exfil
data.
This is bad, bad, bad and rather surprising because until it was
pointed out by this thread I would not have considered it possible due
to the...vehemence... in which least privilege has been upheld.
On Fri, Jan 9, 2015 at 3:52 PM, Stephen Smalley
Post by Stephen Smalley
Ports in the local port range can be auto-assigned by the kernel to
unbound sockets on first use. So it makes no sense to control them,
and there isn't even an LSM hook in the place where such auto-port
selection occurs. Controlling binding to ports is only useful when
the port number is a "name" (i.e. a well-defined value that is
expected to correspond to a specific service), to prevent spoofing of
security-relevant services like sshd.
Post by Dominick Grift
https://bugzilla.redhat.com/show_bug.cgi?id=1174405
This is a inconsistency in SELinux
_______________________________________________
Selinux mailing list
To get help, send an email containing "help" to
_______________________________________________
Selinux mailing list
To get help, send an email containing "help" to
_______________________________________________
Selinux mailing list
Dominick Grift
2015-01-10 09:56:21 UTC
Permalink
Post by Paul Moore
I think there is a point of clarification that may help put everyone at
ease... SELinux provides two permissions relevant to socket bind()
operations, bind and name_bind. The name_bind operation controls the
socket's ability to bind to a specific port, while the bind operation
controls the ability of a domain to bind a socket. Those of you who wish
to restrict a domain from performing a socket bind() operation, regardless
of the port, would likely find your answer with the socket:bind permission.
Good to know but the socket bind access vector is checked on the domain
type and not on the port type

Thus is you have a process with a requirement to bind a socket to a port
< ephemeral, then it is automatically also able listen on ports >=
ephemeral from an selinux pov

Although this is good to know and in rare cases may be useful, it is in
my view indeed still a consolation prize at best
Post by Paul Moore
--
paul moore
www.paul-moore.com
Post by eric gisse
I disagree.
I've had to have technical discussions justifying my belief that
certain common things should be available to all domains such as
/dev/urandom and more recently /proc/sys/vm/overcommit_memory.
Discussions around those reasonable defaults basically rotate around
the philsophical notion of least privilege.
So seeing there's an entire swath of ports that programs can bind to
by default is crazytalk and blows that notion out of the water.
Further, it is bad policy.
Consider sshd, or any other daemon that does nothing but bind to a
port and listen for connections.
It does not need the ability to bind to to anything other than its'
daemon port, not even epheremal ports. Yet it can, regardless of
policy considerations. Which is the underlying point here.
If someone gains access to a server through a compromised service,
they can bind a backdoor to that epheremal range or at least exfil
data.
This is bad, bad, bad and rather surprising because until it was
pointed out by this thread I would not have considered it possible due
to the...vehemence... in which least privilege has been upheld.
On Fri, Jan 9, 2015 at 3:52 PM, Stephen Smalley
Post by Stephen Smalley
Ports in the local port range can be auto-assigned by the kernel to
unbound sockets on first use. So it makes no sense to control them,
and there isn't even an LSM hook in the place where such auto-port
selection occurs. Controlling binding to ports is only useful when
the port number is a "name" (i.e. a well-defined value that is
expected to correspond to a specific service), to prevent spoofing of
security-relevant services like sshd.
Post by Dominick Grift
https://bugzilla.redhat.com/show_bug.cgi?id=1174405
This is a inconsistency in SELinux
_______________________________________________
Selinux mailing list
To get help, send an email containing "help" to
_______________________________________________
Selinux mailing list
To get help, send an email containing "help" to
_______________________________________________
Selinux mailing list
_______________________________________________
Selinux mailing list
Stephen Smalley
2015-01-10 16:49:29 UTC
Permalink
This behavior has a) always been present in SELinux, b) documented in
the original SELinux technical report and the LSM-based SELinux
technical report, and c) discussed plenty of times before. So you're
free to disagree but it isn't new or hidden from view. It was viewed
as logically inconsistent and not useful to impose a restriction upon
bind(2) to a port number in the local port range when such port
numbers have no security semantics and can be obtained by any process
that can create a socket just by connecting (TCP) or sending (UDP) on
that socket. At that time, the ipv4 code will cheerfully assign an
available port number out of that local port range to the socket if it
is unbound. If you truly want to control port numbers in that range,
it is not a mere matter of removing the exemption from the
selinux_socket_bind hook but also introducing a new LSM hook inside
the ipv4 code to keep trying until it finds a port number that is
allowed. The potential overhead of applying such checking could be
non-trivial and would show up on connect() and sendto()/sendmsg()
calls. You are free to submit a patch to do exactly that, with
performance measurements if you wish.
Post by Dominick Grift
Post by Paul Moore
I think there is a point of clarification that may help put everyone at
ease... SELinux provides two permissions relevant to socket bind()
operations, bind and name_bind. The name_bind operation controls the
socket's ability to bind to a specific port, while the bind operation
controls the ability of a domain to bind a socket. Those of you who wish
to restrict a domain from performing a socket bind() operation, regardless
of the port, would likely find your answer with the socket:bind permission.
Good to know but the socket bind access vector is checked on the domain
type and not on the port type
Thus is you have a process with a requirement to bind a socket to a port
< ephemeral, then it is automatically also able listen on ports >=
ephemeral from an selinux pov
Although this is good to know and in rare cases may be useful, it is in
my view indeed still a consolation prize at best
Post by Paul Moore
--
paul moore
www.paul-moore.com
Post by eric gisse
I disagree.
I've had to have technical discussions justifying my belief that
certain common things should be available to all domains such as
/dev/urandom and more recently /proc/sys/vm/overcommit_memory.
Discussions around those reasonable defaults basically rotate around
the philsophical notion of least privilege.
So seeing there's an entire swath of ports that programs can bind to
by default is crazytalk and blows that notion out of the water.
Further, it is bad policy.
Consider sshd, or any other daemon that does nothing but bind to a
port and listen for connections.
It does not need the ability to bind to to anything other than its'
daemon port, not even epheremal ports. Yet it can, regardless of
policy considerations. Which is the underlying point here.
If someone gains access to a server through a compromised service,
they can bind a backdoor to that epheremal range or at least exfil
data.
This is bad, bad, bad and rather surprising because until it was
pointed out by this thread I would not have considered it possible due
to the...vehemence... in which least privilege has been upheld.
On Fri, Jan 9, 2015 at 3:52 PM, Stephen Smalley
Post by Stephen Smalley
Ports in the local port range can be auto-assigned by the kernel to
unbound sockets on first use. So it makes no sense to control them,
and there isn't even an LSM hook in the place where such auto-port
selection occurs. Controlling binding to ports is only useful when
the port number is a "name" (i.e. a well-defined value that is
expected to correspond to a specific service), to prevent spoofing of
security-relevant services like sshd.
Post by Dominick Grift
https://bugzilla.redhat.com/show_bug.cgi?id=1174405
This is a inconsistency in SELinux
_______________________________________________
Selinux mailing list
To get help, send an email containing "help" to
_______________________________________________
Selinux mailing list
To get help, send an email containing "help" to
_______________________________________________
Selinux mailing list
_______________________________________________
Selinux mailing list
Dominick Grift
2015-01-10 17:19:51 UTC
Permalink
Post by Stephen Smalley
This behavior has a) always been present in SELinux, b) documented in
the original SELinux technical report and the LSM-based SELinux
technical report, and c) discussed plenty of times before. So you're
free to disagree but it isn't new or hidden from view. It was viewed
as logically inconsistent and not useful to impose a restriction upon
bind(2) to a port number in the local port range when such port
numbers have no security semantics and can be obtained by any process
that can create a socket just by connecting (TCP) or sending (UDP) on
that socket. At that time, the ipv4 code will cheerfully assign an
available port number out of that local port range to the socket if it
is unbound. If you truly want to control port numbers in that range,
it is not a mere matter of removing the exemption from the
selinux_socket_bind hook but also introducing a new LSM hook inside
the ipv4 code to keep trying until it finds a port number that is
allowed. The potential overhead of applying such checking could be
non-trivial and would show up on connect() and sendto()/sendmsg()
calls. You are free to submit a patch to do exactly that, with
performance measurements if you wish.
I can live with this "logical inconsistency", and other "gotchas" but i would prefer that tools/libraries like sesearch would some how communicate this.
It may be documented, and discussed but besides a handful of kernel coders and a few others, i bet not many are aware of this inconsistency, and other gotchas
If the tools would some how show that there is a special case, then policy authors would not be left totally in the dark but how would one implement that...
Post by Stephen Smalley
Post by Dominick Grift
Post by Paul Moore
I think there is a point of clarification that may help put everyone at
ease... SELinux provides two permissions relevant to socket bind()
operations, bind and name_bind. The name_bind operation controls the
socket's ability to bind to a specific port, while the bind operation
controls the ability of a domain to bind a socket. Those of you who wish
to restrict a domain from performing a socket bind() operation, regardless
of the port, would likely find your answer with the socket:bind permission.
Good to know but the socket bind access vector is checked on the domain
type and not on the port type
Thus is you have a process with a requirement to bind a socket to a port
< ephemeral, then it is automatically also able listen on ports >=
ephemeral from an selinux pov
Although this is good to know and in rare cases may be useful, it is in
my view indeed still a consolation prize at best
Post by Paul Moore
--
paul moore
www.paul-moore.com
Post by eric gisse
I disagree.
I've had to have technical discussions justifying my belief that
certain common things should be available to all domains such as
/dev/urandom and more recently /proc/sys/vm/overcommit_memory.
Discussions around those reasonable defaults basically rotate around
the philsophical notion of least privilege.
So seeing there's an entire swath of ports that programs can bind to
by default is crazytalk and blows that notion out of the water.
Further, it is bad policy.
Consider sshd, or any other daemon that does nothing but bind to a
port and listen for connections.
It does not need the ability to bind to to anything other than its'
daemon port, not even epheremal ports. Yet it can, regardless of
policy considerations. Which is the underlying point here.
If someone gains access to a server through a compromised service,
they can bind a backdoor to that epheremal range or at least exfil
data.
This is bad, bad, bad and rather surprising because until it was
pointed out by this thread I would not have considered it possible due
to the...vehemence... in which least privilege has been upheld.
On Fri, Jan 9, 2015 at 3:52 PM, Stephen Smalley
Post by Stephen Smalley
Ports in the local port range can be auto-assigned by the kernel to
unbound sockets on first use. So it makes no sense to control them,
and there isn't even an LSM hook in the place where such auto-port
selection occurs. Controlling binding to ports is only useful when
the port number is a "name" (i.e. a well-defined value that is
expected to correspond to a specific service), to prevent spoofing of
security-relevant services like sshd.
Post by Dominick Grift
https://bugzilla.redhat.com/show_bug.cgi?id=1174405
This is a inconsistency in SELinux
_______________________________________________
Selinux mailing list
To get help, send an email containing "help" to
_______________________________________________
Selinux mailing list
To get help, send an email containing "help" to
_______________________________________________
Selinux mailing list
_______________________________________________
Selinux mailing list
--
Dominick Grift
Dominick Grift
2015-01-10 17:43:00 UTC
Permalink
Post by Dominick Grift
Post by Stephen Smalley
This behavior has a) always been present in SELinux, b) documented in
the original SELinux technical report and the LSM-based SELinux
technical report, and c) discussed plenty of times before. So you're
free to disagree but it isn't new or hidden from view. It was viewed
as logically inconsistent and not useful to impose a restriction upon
bind(2) to a port number in the local port range when such port
numbers have no security semantics and can be obtained by any process
that can create a socket just by connecting (TCP) or sending (UDP) on
that socket. At that time, the ipv4 code will cheerfully assign an
available port number out of that local port range to the socket if it
is unbound. If you truly want to control port numbers in that range,
it is not a mere matter of removing the exemption from the
selinux_socket_bind hook but also introducing a new LSM hook inside
the ipv4 code to keep trying until it finds a port number that is
allowed. The potential overhead of applying such checking could be
non-trivial and would show up on connect() and sendto()/sendmsg()
calls. You are free to submit a patch to do exactly that, with
performance measurements if you wish.
I can live with this "logical inconsistency", and other "gotchas" but i would prefer that tools/libraries like sesearch would some how communicate this.
It may be documented, and discussed but besides a handful of kernel coders and a few others, i bet not many are aware of this inconsistency, and other gotchas
If the tools would some how show that there is a special case, then policy authors would not be left totally in the dark but how would one implement that...
There is a difference between not being hidden from view, and being prominently visible. I prefer the latter in instances like these to avoid this embarrassment.
Post by Dominick Grift
Post by Stephen Smalley
Post by Dominick Grift
Post by Paul Moore
I think there is a point of clarification that may help put everyone at
ease... SELinux provides two permissions relevant to socket bind()
operations, bind and name_bind. The name_bind operation controls the
socket's ability to bind to a specific port, while the bind operation
controls the ability of a domain to bind a socket. Those of you who wish
to restrict a domain from performing a socket bind() operation, regardless
of the port, would likely find your answer with the socket:bind permission.
Good to know but the socket bind access vector is checked on the domain
type and not on the port type
Thus is you have a process with a requirement to bind a socket to a port
< ephemeral, then it is automatically also able listen on ports >=
ephemeral from an selinux pov
Although this is good to know and in rare cases may be useful, it is in
my view indeed still a consolation prize at best
Post by Paul Moore
--
paul moore
www.paul-moore.com
Post by eric gisse
I disagree.
I've had to have technical discussions justifying my belief that
certain common things should be available to all domains such as
/dev/urandom and more recently /proc/sys/vm/overcommit_memory.
Discussions around those reasonable defaults basically rotate around
the philsophical notion of least privilege.
So seeing there's an entire swath of ports that programs can bind to
by default is crazytalk and blows that notion out of the water.
Further, it is bad policy.
Consider sshd, or any other daemon that does nothing but bind to a
port and listen for connections.
It does not need the ability to bind to to anything other than its'
daemon port, not even epheremal ports. Yet it can, regardless of
policy considerations. Which is the underlying point here.
If someone gains access to a server through a compromised service,
they can bind a backdoor to that epheremal range or at least exfil
data.
This is bad, bad, bad and rather surprising because until it was
pointed out by this thread I would not have considered it possible due
to the...vehemence... in which least privilege has been upheld.
On Fri, Jan 9, 2015 at 3:52 PM, Stephen Smalley
Post by Stephen Smalley
Ports in the local port range can be auto-assigned by the kernel to
unbound sockets on first use. So it makes no sense to control them,
and there isn't even an LSM hook in the place where such auto-port
selection occurs. Controlling binding to ports is only useful when
the port number is a "name" (i.e. a well-defined value that is
expected to correspond to a specific service), to prevent spoofing of
security-relevant services like sshd.
Post by Dominick Grift
https://bugzilla.redhat.com/show_bug.cgi?id=1174405
This is a inconsistency in SELinux
_______________________________________________
Selinux mailing list
To get help, send an email containing "help" to
_______________________________________________
Selinux mailing list
To get help, send an email containing "help" to
_______________________________________________
Selinux mailing list
_______________________________________________
Selinux mailing list
--
Dominick Grift
--
Dominick Grift
Stephen Smalley
2015-01-10 18:54:01 UTC
Permalink
Well, I noted it in the technical reports I wrote originally for
SELinux. I guess it didn't get carried into documentation written by
others, although it has been discussed on this list and the Fedora
SELinux list various times. Also, even if we were to implement such a
check, we'd have to dontaudit it in most cases because the kernel
would automatically be scanning the range for an available and allowed
port, and various userspace libraries do exactly the same thing when
trying to bind to an available port. Which would render it a
mysterious denial on random send/connect and bind calls.
Post by Dominick Grift
Post by Dominick Grift
Post by Stephen Smalley
This behavior has a) always been present in SELinux, b) documented in
the original SELinux technical report and the LSM-based SELinux
technical report, and c) discussed plenty of times before. So you're
free to disagree but it isn't new or hidden from view. It was viewed
as logically inconsistent and not useful to impose a restriction upon
bind(2) to a port number in the local port range when such port
numbers have no security semantics and can be obtained by any process
that can create a socket just by connecting (TCP) or sending (UDP) on
that socket. At that time, the ipv4 code will cheerfully assign an
available port number out of that local port range to the socket if it
is unbound. If you truly want to control port numbers in that range,
it is not a mere matter of removing the exemption from the
selinux_socket_bind hook but also introducing a new LSM hook inside
the ipv4 code to keep trying until it finds a port number that is
allowed. The potential overhead of applying such checking could be
non-trivial and would show up on connect() and sendto()/sendmsg()
calls. You are free to submit a patch to do exactly that, with
performance measurements if you wish.
I can live with this "logical inconsistency", and other "gotchas" but i would prefer that tools/libraries like sesearch would some how communicate this.
It may be documented, and discussed but besides a handful of kernel coders and a few others, i bet not many are aware of this inconsistency, and other gotchas
If the tools would some how show that there is a special case, then policy authors would not be left totally in the dark but how would one implement that...
There is a difference between not being hidden from view, and being prominently visible. I prefer the latter in instances like these to avoid this embarrassment.
Post by Dominick Grift
Post by Stephen Smalley
Post by Dominick Grift
Post by Paul Moore
I think there is a point of clarification that may help put everyone at
ease... SELinux provides two permissions relevant to socket bind()
operations, bind and name_bind. The name_bind operation controls the
socket's ability to bind to a specific port, while the bind operation
controls the ability of a domain to bind a socket. Those of you who wish
to restrict a domain from performing a socket bind() operation, regardless
of the port, would likely find your answer with the socket:bind permission.
Good to know but the socket bind access vector is checked on the domain
type and not on the port type
Thus is you have a process with a requirement to bind a socket to a port
< ephemeral, then it is automatically also able listen on ports >=
ephemeral from an selinux pov
Although this is good to know and in rare cases may be useful, it is in
my view indeed still a consolation prize at best
Post by Paul Moore
--
paul moore
www.paul-moore.com
Post by eric gisse
I disagree.
I've had to have technical discussions justifying my belief that
certain common things should be available to all domains such as
/dev/urandom and more recently /proc/sys/vm/overcommit_memory.
Discussions around those reasonable defaults basically rotate around
the philsophical notion of least privilege.
So seeing there's an entire swath of ports that programs can bind to
by default is crazytalk and blows that notion out of the water.
Further, it is bad policy.
Consider sshd, or any other daemon that does nothing but bind to a
port and listen for connections.
It does not need the ability to bind to to anything other than its'
daemon port, not even epheremal ports. Yet it can, regardless of
policy considerations. Which is the underlying point here.
If someone gains access to a server through a compromised service,
they can bind a backdoor to that epheremal range or at least exfil
data.
This is bad, bad, bad and rather surprising because until it was
pointed out by this thread I would not have considered it possible due
to the...vehemence... in which least privilege has been upheld.
On Fri, Jan 9, 2015 at 3:52 PM, Stephen Smalley
Post by Stephen Smalley
Ports in the local port range can be auto-assigned by the kernel to
unbound sockets on first use. So it makes no sense to control them,
and there isn't even an LSM hook in the place where such auto-port
selection occurs. Controlling binding to ports is only useful when
the port number is a "name" (i.e. a well-defined value that is
expected to correspond to a specific service), to prevent spoofing of
security-relevant services like sshd.
Post by Dominick Grift
https://bugzilla.redhat.com/show_bug.cgi?id=1174405
This is a inconsistency in SELinux
_______________________________________________
Selinux mailing list
To get help, send an email containing "help" to
_______________________________________________
Selinux mailing list
To get help, send an email containing "help" to
_______________________________________________
Selinux mailing list
_______________________________________________
Selinux mailing list
--
Dominick Grift
--
Dominick Grift
_______________________________________________
Selinux mailing list
Dominick Grift
2015-01-10 19:15:18 UTC
Permalink
Post by Stephen Smalley
Well, I noted it in the technical reports I wrote originally for
SELinux. I guess it didn't get carried into documentation written by
others, although it has been discussed on this list and the Fedora
SELinux list various times. Also, even if we were to implement such a
check, we'd have to dontaudit it in most cases because the kernel
would automatically be scanning the range for an available and allowed
port, and various userspace libraries do exactly the same thing when
trying to bind to an available port. Which would render it a
mysterious denial on random send/connect and bind calls.
You hinted that implementing a check for this could affect performance, and so i am no longer in favor of that solution.

however i would like some of the tools to be aware of this issue.

for example if i do

sesearch -A -s sshd_t -t port_type -c tcp_socket -p name_bind

That it returns somehow that this access to ports in the local port range will be allowed. So that auditors see that it is allowed even though there is no rule to allow it.
At least then they know there is something going on and can look for documentation about it.

The problem is how does one implement that in an informative way without relying on customizable identifiers.
Post by Stephen Smalley
Post by Dominick Grift
Post by Dominick Grift
Post by Stephen Smalley
This behavior has a) always been present in SELinux, b) documented in
the original SELinux technical report and the LSM-based SELinux
technical report, and c) discussed plenty of times before. So you're
free to disagree but it isn't new or hidden from view. It was viewed
as logically inconsistent and not useful to impose a restriction upon
bind(2) to a port number in the local port range when such port
numbers have no security semantics and can be obtained by any process
that can create a socket just by connecting (TCP) or sending (UDP) on
that socket. At that time, the ipv4 code will cheerfully assign an
available port number out of that local port range to the socket if it
is unbound. If you truly want to control port numbers in that range,
it is not a mere matter of removing the exemption from the
selinux_socket_bind hook but also introducing a new LSM hook inside
the ipv4 code to keep trying until it finds a port number that is
allowed. The potential overhead of applying such checking could be
non-trivial and would show up on connect() and sendto()/sendmsg()
calls. You are free to submit a patch to do exactly that, with
performance measurements if you wish.
I can live with this "logical inconsistency", and other "gotchas" but i would prefer that tools/libraries like sesearch would some how communicate this.
It may be documented, and discussed but besides a handful of kernel coders and a few others, i bet not many are aware of this inconsistency, and other gotchas
If the tools would some how show that there is a special case, then policy authors would not be left totally in the dark but how would one implement that...
There is a difference between not being hidden from view, and being prominently visible. I prefer the latter in instances like these to avoid this embarrassment.
Post by Dominick Grift
Post by Stephen Smalley
Post by Dominick Grift
Post by Paul Moore
I think there is a point of clarification that may help put everyone at
ease... SELinux provides two permissions relevant to socket bind()
operations, bind and name_bind. The name_bind operation controls the
socket's ability to bind to a specific port, while the bind operation
controls the ability of a domain to bind a socket. Those of you who wish
to restrict a domain from performing a socket bind() operation, regardless
of the port, would likely find your answer with the socket:bind permission.
Good to know but the socket bind access vector is checked on the domain
type and not on the port type
Thus is you have a process with a requirement to bind a socket to a port
< ephemeral, then it is automatically also able listen on ports >=
ephemeral from an selinux pov
Although this is good to know and in rare cases may be useful, it is in
my view indeed still a consolation prize at best
Post by Paul Moore
--
paul moore
www.paul-moore.com
Post by eric gisse
I disagree.
I've had to have technical discussions justifying my belief that
certain common things should be available to all domains such as
/dev/urandom and more recently /proc/sys/vm/overcommit_memory.
Discussions around those reasonable defaults basically rotate around
the philsophical notion of least privilege.
So seeing there's an entire swath of ports that programs can bind to
by default is crazytalk and blows that notion out of the water.
Further, it is bad policy.
Consider sshd, or any other daemon that does nothing but bind to a
port and listen for connections.
It does not need the ability to bind to to anything other than its'
daemon port, not even epheremal ports. Yet it can, regardless of
policy considerations. Which is the underlying point here.
If someone gains access to a server through a compromised service,
they can bind a backdoor to that epheremal range or at least exfil
data.
This is bad, bad, bad and rather surprising because until it was
pointed out by this thread I would not have considered it possible due
to the...vehemence... in which least privilege has been upheld.
On Fri, Jan 9, 2015 at 3:52 PM, Stephen Smalley
Post by Stephen Smalley
Ports in the local port range can be auto-assigned by the kernel to
unbound sockets on first use. So it makes no sense to control them,
and there isn't even an LSM hook in the place where such auto-port
selection occurs. Controlling binding to ports is only useful when
the port number is a "name" (i.e. a well-defined value that is
expected to correspond to a specific service), to prevent spoofing of
security-relevant services like sshd.
Post by Dominick Grift
https://bugzilla.redhat.com/show_bug.cgi?id=1174405
This is a inconsistency in SELinux
_______________________________________________
Selinux mailing list
To get help, send an email containing "help" to
_______________________________________________
Selinux mailing list
To get help, send an email containing "help" to
_______________________________________________
Selinux mailing list
_______________________________________________
Selinux mailing list
--
Dominick Grift
--
Dominick Grift
_______________________________________________
Selinux mailing list
_______________________________________________
Selinux mailing list
--
Dominick Grift
Vincent Brillault
2015-01-10 20:39:49 UTC
Permalink
Hi,

I'm not sure I understand the "performance" impact considerations.
Indeed, if we were to try to control the binding to 'ephemeral' ports
individually, the looping that Stephen proposed would definitely have a
huge impact if all port are denied (as the kernel will have to loop over
all of them to find out that all bindings are denied).

However, does considering all these ports individually make sense?
If we can consider them as a group, not individually, I believe that we
could control 'ephemeral' bindings with almost no performance hit.
For example, we could create a permission 'ephemeral_bind' in addition
to bind and named_bind:
- bind controls the ability to invoke the bind system calls
- named_bind controls the ability to bind a given non ephemeral port
- ephemeral_bind would controls the ability to bind any 'ephemeral' port

Would that make sense?

I'm not a kernel/selinux developper, so I can't judge the amount of work
needed to implement such a solution, but I don't think that this issue
can be discarded for 'performance' reasons.

Cheers,
Vincent Brillault
Stephen Smalley
2015-01-12 16:29:32 UTC
Permalink
Post by Vincent Brillault
Hi,
I'm not sure I understand the "performance" impact considerations.
Indeed, if we were to try to control the binding to 'ephemeral' ports
individually, the looping that Stephen proposed would definitely have a
huge impact if all port are denied (as the kernel will have to loop over
all of them to find out that all bindings are denied).
Yes, that was what I meant.
Post by Vincent Brillault
However, does considering all these ports individually make sense?
If we can consider them as a group, not individually, I believe that we
could control 'ephemeral' bindings with almost no performance hit.
For example, we could create a permission 'ephemeral_bind' in addition
- bind controls the ability to invoke the bind system calls
- named_bind controls the ability to bind a given non ephemeral port
- ephemeral_bind would controls the ability to bind any 'ephemeral' port
Would that make sense?
I'm not a kernel/selinux developper, so I can't judge the amount of work
needed to implement such a solution, but I don't think that this issue
can be discarded for 'performance' reasons.
You can bind to a port in the local port range in three different ways:

1) Call bind(2) with the port number explicitly specified. That case we
could trivially check via SELinux today if we wanted to do so just by
removing the range check from selinux_socket_bind. But it would leave
the check trivially bypassable by using one of the other two means until
you hit the desired port number, which is why we did not impose this
check in the first place (in addition to the fact that such ports can
have no security semantics since they are "randomly" assigned on demand).

2) Call bind(2) with a zero port number specified. In that case, the
port is automatically selected by the ipv4 code after we have already
passed the selinux_socket_bind() hook call, so we cannot apply a check
based on the specific port number unless we hook the ipv4 (and ipv6)
code, in multiple places no less, which I don't see as maintainable. We
could apply your generic ephemeral_bind check from selinux_socket_bind()
in this case but this will still be bypassable using the third way below.

3) Call sendto()/sendmsg() or connect() on an unbound socket. In that
case, the port is automatically selected by the ipv4 code after we have
already passed the selinux_socket_sendmsg() or selinux_socket_connect()
hook call. We'd either have to dig down into the inet_sk state within
those hooks to see if the socket was unbound or place a hook down in the
ipv4 code (and the ipv6 code) if we wanted to even apply your
ephemeral_bind check. The former is possible but seems a bit of a
layering violation while the latter seems unmaintainable.

Now, let's say we implement this ephemeral_bind permission check. What
domains that currently are allowed to create UDP or TCP sockets do you
think will need this permission? I'll wager they all do, because they
will be creating sender UDP sockets for DNS lookups and other purposes
that will just be using the local port range. So what did you gain?
Paul Moore
2015-01-11 15:49:03 UTC
Permalink
Post by Dominick Grift
Post by Stephen Smalley
Well, I noted it in the technical reports I wrote originally for
SELinux. I guess it didn't get carried into documentation written by
others, although it has been discussed on this list and the Fedora
SELinux list various times. Also, even if we were to implement such a
check, we'd have to dontaudit it in most cases because the kernel
would automatically be scanning the range for an available and allowed
port, and various userspace libraries do exactly the same thing when
trying to bind to an available port. Which would render it a
mysterious denial on random send/connect and bind calls.
You hinted that implementing a check for this could affect performance, and so i am no longer in favor of that solution.
however i would like some of the tools to be aware of this issue.
for example if i do
sesearch -A -s sshd_t -t port_type -c tcp_socket -p name_bind
That it returns somehow that this access to ports in the local port range will be allowed. So that auditors see that it is allowed even though there is no rule to allow it.
At least then they know there is something going on and can look for documentation about it.
The problem is how does one implement that in an informative way without relying on customizable identifiers.
Perhaps a mention in the relevant man pages?
--
paul moore
www.paul-moore.com
Dominick Grift
2015-01-11 16:23:23 UTC
Permalink
Post by Paul Moore
Post by Dominick Grift
Post by Stephen Smalley
Well, I noted it in the technical reports I wrote originally for
SELinux. I guess it didn't get carried into documentation written by
others, although it has been discussed on this list and the Fedora
SELinux list various times. Also, even if we were to implement such a
check, we'd have to dontaudit it in most cases because the kernel
would automatically be scanning the range for an available and allowed
port, and various userspace libraries do exactly the same thing when
trying to bind to an available port. Which would render it a
mysterious denial on random send/connect and bind calls.
You hinted that implementing a check for this could affect performance, and so i am no longer in favor of that solution.
however i would like some of the tools to be aware of this issue.
for example if i do
sesearch -A -s sshd_t -t port_type -c tcp_socket -p name_bind
That it returns somehow that this access to ports in the local port range will be allowed. So that auditors see that it is allowed even though there is no rule to allow it.
At least then they know there is something going on and can look for documentation about it.
The problem is how does one implement that in an informative way without relying on customizable identifiers.
Perhaps a mention in the relevant man pages?
That is better than nothing in my opinion but I do not believe this is prominently visible enough on its own. In my view we should pro-actively inform users about this and other inconsistencies.
Post by Paul Moore
--
paul moore
www.paul-moore.com
_______________________________________________
Selinux mailing list
--
Dominick Grift
Loading...