[grsec] sshd can open server sockets, but should not.
Schwarz
schwarz at power-netz.de
Wed Sep 7 09:26:24 EDT 2005
Hi all,
I played a bit with grsec and found sshd to bypass handle_sock_server()
and handle_sock_server_other() while opening a serversocket.
-> Which function does it use and does grsec handle this?
What did I do?
###############
I reversed the original grsec behavior. I have set a group which
is allowed to open a server-socket. This is much more useful
on multidomainhostingsystems instead of adding each user to the group
who is not allowed to open a socket.
We run a tool to force execution of webscripts with the correct
userid of it's owner.
The source of my patch is attached below.
What did i found out?
######################
If i use "nc -l -port 9999" as a none-server-socket-user
i get a can't bind requested port 0.0.0.0:9999 which is
what should happen.
if i setup sshd to use the same port, it works!
it can bind the port and answere to requests.
as the grsec log does not show the attempt to bind the socket
and to check for groups ( see below ) I think two things can happen:
1) the "quick check" marked if statement lets the sshd pass because
sshd is somehow started with uid 0 ( i.e. internally changed to uid = 0)
2) sshd bypasses these two functions ( more likely ) .
sshd version opensshd 3.9p1 -> 4.2p1
#############################
Does anyone know more about how ssh binds it's port to a socket ?
Thanks,
M.Schwarz
int
gr_handle_sock_all(const int family, const int type, const int protocol)
{
#ifdef CONFIG_GRKERNSEC_SOCKET_ALL
if (grsec_enable_socket_all && in_group_p(grsec_socket_all_gid)
&&
(family != AF_UNIX) && (family != AF_LOCAL) && (type <
SOCK_MAX)) {
gr_log_int_str2(GR_DONT_AUDIT, GR_SOCK2_MSG, family,
gr_socktype_to_name(type), gr_proto_to_name(protocol));
return -EACCES;
}
#endif
return 0;
}
int
gr_handle_sock_server(const struct sockaddr *sck)
{
#ifdef CONFIG_GRKERNSEC_SOCKET_SERVER
######################
#### CODE removed #### to spare lines, it's the same as below
except :
###################### (sck->family != AF_UNIX) which is
(sck->sa_family != AF_UNIX)
#endif
return 0;
}
int
gr_handle_sock_server_other(const struct sock *sck)
{
#ifdef CONFIG_GRKERNSEC_SOCKET_SERVER
/*
if (grsec_enable_socket_server &&
in_group_p(grsec_socket_server_gid) &&
sck && (sck->family != AF_UNIX) &&
(sck->family != AF_LOCAL)) {
gr_log_noargs(GR_DONT_AUDIT, GR_BIND_MSG);
return -EACCES;
}
*/
int i = current->ngroups;
if (grsec_enable_socket_server) {
// Quick check : if root or in the server socket group you may
pass
if ( in_group_p(grsec_socket_server_gid)
|| current->uid == 0
|| current->fsuid == 0
|| current->p_pptr->uid == 0
|| current->p_pptr->euid == 0
|| current->p_pptr->gid == 0
|| current->p_pptr->egid == 0
) return 0;
// if user is not in the group do further checks
if ( in_group_p(grsec_socket_server_gid)==0 && // nicht in der
Gruppe
( current->fsuid != 0 ) &&
( current->uid != 0 ) &&
sck &&
(sck->family != AF_UNIX) &&
(sck->family != AF_LOCAL)
) {
gr_log_noargs(GR_DONT_AUDIT, GR_BIND_MSG);
if (i) {
gid_t *groups = current->groups;
do {
if (*groups == grsec_socket_server_gid)
{
gr_log_int(GR_DONT_AUDIT,"
bind() gruppe gefunden %u by ",*groups);
} else {
gr_log_int_int(GR_DONT_AUDIT, "
bind() gruppe %d != %d ",*groups,grsec_socket_server_gid);
}
groups++;
i--;
} while (i);
}
gr_log_int(GR_DONT_AUDIT," bind() gruppenanalyse
ende",0);
return -EACCES;
}
}
#endif
return 0;
}
More information about the grsecurity
mailing list