socket_server useless?

Discuss usability issues, general maintenance, and general support issues for a grsecurity-enabled system.

socket_server useless?

Postby grebneke » Tue Dec 23, 2003 10:37 pm

kernel 2.4.23 + grsec 1.9.13

I'm trying to use socket_server and socket_server_gid to stop group "nogroup" from starting listening daemons. The point is to prevent exploits with Apache/PHP that install a small telnet-daemon running as "nobody", letting anyone telnet straight into the server w/o password

Tests show that enabling socket_server block the bind() call, but it doesn't seem to matter - the daemon can still accept connections on the port. Look at these straces:

## Without socket_server
## echo 0 >| /proc/sys/kernel/grsecurity/socket_server
[pid 4717] socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3
[pid 4717] bind(3, {sin_family=AF_INET, sin_port=htons(14589), sin_addr=inet_addr("0.0.0.0")}}, 16) = 0
[pid 4717] listen(3, 5) = 0
[pid 4717] accept(3, <unfinished ...>

## With socket_server enabled
## echo 1 >| /proc/sys/kernel/grsecurity/socket_server
[pid 984] socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3
[pid 984] bind(3, {sin_family=AF_INET, sin_port=htons(14589), sin_addr=inet_addr("0.0.0.0")}}, 16) = -1 EACCES (Permission denied)
[pid 984] listen(3, 5) = 0
[pid 984] accept(3, <unfinished ...>

In the second example, bind() returns EACCES, but the daemon still accepts on the port (14589). When telneting to port 14589 you get access to a login shell running as the Apache user (nobody/nogroup).

What's wrong here?
Am I missing something obvious?
How can I prevent Apache/PHP from opening listening sockets?
Blocking bind() seems totally useless?

Grateful for any help.
grebneke
 
Posts: 6
Joined: Tue Dec 23, 2003 10:19 pm

Postby Sleight of Mind » Wed Dec 24, 2003 6:27 am

do you use CONFIG_GRKERNSEC_SOCKET_SERVER_GID?
and if so, to what value is it set? and is apache in this group?

after setting socket_server to 1 and socket_server_gid to a certain value i tested logging in as this user(with [primary group $socket_server_gid) and running `nc -l -p 12345`:
Code: Select all
....
bind(3, {sa_family=AF_INET, sin_port=htons(12345), sin_addr=inet_addr("0.0.0.0")}, 16) = -1 EACCES (Permission denied)
write(2, "Can\'t grab 0.0.0.0:12345 with bi"..., 34Can't grab 0.0.0.0:12345 with bind) = 34
write(2, " : Permission denied\n", 21 : Permission denied
)  = 21
close(-1)                               = -1 EBADF (Bad file descriptor)
_exit(1)                                = ?


As you can see it works perfectly for me.
Sleight of Mind
 
Posts: 92
Joined: Tue Apr 08, 2003 10:41 am

Postby grebneke » Wed Dec 24, 2003 7:42 am

I'm using the sysctl interface. Apache runs as nobody.nogroup. nogroup has id 65534:

# id -g nobody
65534

echo "65534" >| /proc/sys/kernel/grsecurity/socket_server_gid

As you can see from the straces I posted, bind() returns EACCESS just as in your case, indicating that I configured the socket_server_gid correctly. Your code seems to do error checking and bail out on the error, but the program I tried doesn't care about bind() returning -1 and so continues to accept() successfully which is the real problem here.

I don't have the src for the program but I believe it's fairly obvious from the straces what's going on
grebneke
 
Posts: 6
Joined: Tue Dec 23, 2003 10:19 pm

Postby Sleight of Mind » Wed Dec 24, 2003 1:46 pm

well, if this is true i don't think its a grsecurity bug, since it does what it is supposed to (return -EACCES). The operating system (kernel) should take care about it from here afaik.

Code: Select all
int
gr_handle_sock_server(const struct sockaddr *sck)
{
#ifdef CONFIG_GRKERNSEC_SOCKET_SERVER
    if (grsec_enable_socket_server &&
        in_group_p(grsec_socket_server_gid) &&
        sck && (sck->sa_family != AF_UNIX) &&
        (sck->sa_family != AF_LOCAL)) {
        security_alert(GR_BIND_MSG, DEFAULTSECARGS);
        return -EACCES;
    }
#endif
    return 0;
}


I don't think anything _can_ be wrong about this code, since it's all pretty clear. So my guess would be some config error, and if not, maybe a kernel bug. Could you make the application you're using to test available somewhere?
Sleight of Mind
 
Posts: 92
Joined: Tue Apr 08, 2003 10:41 am

Postby grebneke » Wed Dec 24, 2003 9:15 pm

The code is clear and as you can see from the strace, the application gets EACCES like it should, but it can still accept() on the port like nothing happened.

The program I've been tested with can be found here: http://www12.aname.net/~johan/telnetd

Grateful for any help - if this isn't an error on my part it's an extremely serious security problem
grebneke
 
Posts: 6
Joined: Tue Dec 23, 2003 10:19 pm

Postby Sleight of Mind » Thu Dec 25, 2003 7:35 am

i tried to test this application to see if i could reproduce the error, but this program segfaults on any machine i try it on. Do you have it's source code somewhere? Or is this just a distro's telnetd?
Sleight of Mind
 
Posts: 92
Joined: Tue Apr 08, 2003 10:41 am

Postby grebneke » Thu Dec 25, 2003 7:55 am

Please download it again. I stripped the binary before posting it on the URL and that seems to have broken it (segfaults here as well). I've restored the original without any modifications and it should work

http://www12.aname.net/~johan/telnetd
grebneke
 
Posts: 6
Joined: Tue Dec 23, 2003 10:19 pm

Postby Sleight of Mind » Thu Dec 25, 2003 8:24 am

with this program i was able to reproduce: (using strace & strace -f)

Code: Select all
socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3
bind(3, {sa_family=AF_INET, sin_port=htons(14589), sin_addr=inet_addr("0.0.0.0")}, 16) = -1 EACCES (Permission denied)
listen(3, 5)                            = 0
accept(3,


But when trying nmap or telnet on this port it seems to be closed. When doing the same thing as a user that is not in the group it works just fine and a shell is spawned when i telnet to the port.

So this problem seems to occur on your box only. Do you use any other patches on your kernel? or just plain 2.4.23 with grsec?
Sleight of Mind
 
Posts: 92
Joined: Tue Apr 08, 2003 10:41 am

Postby grebneke » Mon Dec 29, 2003 6:46 am

This is vanilla 2.4.23 + grsec, no other related patches applied. (The only other patches are a few small adjustments for using quota with reiserfs)

This is the relevant config from /proc:
Code: Select all
# cat /proc/sys/kernel/grsecurity/socket_server
1
# cat /proc/sys/kernel/grsecurity/socket_server_gid
65534


I tried this again by adding my own user "johan" to group 65534 and starting the telnetd program.

dmesg said:
Code: Select all
grsec: From ...: attempted bind() by (telnetd:25326) UID(4501) EUID(4501), parent (telnetd:25324) UID(4501)
EUID(4501)


netstat -telp said:
Code: Select all
tcp        0      0 *:33193                 *:*                     LISTEN      johan      24547948   26953/getty


Telnetting to the machine from another location:
Code: Select all
other-machine# telnet ... 33193
Connected to ...
Escape character is '^]'.

Linux 2.4.23-grsec (...) (pts/1)

~$ whoami
johan


I really don't know what to do now...
grebneke
 
Posts: 6
Joined: Tue Dec 23, 2003 10:19 pm


Return to grsecurity support

cron