Showing posts with label RTFM. Show all posts
Showing posts with label RTFM. Show all posts

Wednesday, March 5, 2014

Privileged ports, Linux capabilities and Java

Under Unices (including Linux), running a listening service on low numbered privileged TCP ports (< 1024) can usually only be done by root (superuser). This does not necessarily mean that service needs to run with effective user id of root, but at service port binding time, user running the program needs to have sufficient privileges. As lot of low numbered ports are commonly used for many standard services (HTTP is usually over port 80 and HTTPS port 443, etc), the notion of privileged ports can be considered "security through convention" approach, preventing random user with UNIX shell account popping up some apparently "official" service. On the other hand, requirement for privileged account can become a security issue, if the program that needs to be run on privileged port is in some aspects untrusted.

privbind/authbind

Debian packages include privbind utility that allows to execute application as an unprivileged user with extra privilege of binding to reserved ports. Its manual is contradictory, specifying both that:

  • privbind has no SUID parts, and runs within the confines of a single process
  • privbind works by starting two processes. One drops privileges and runs (exec(2)) the command, the other remains as root.
Contradictions aside, privbind is unable to work with many current Java Virtual Machines (JVMs), as it is "using LD_PRELOAD to intercept every call to bind(2) made by the program"1, while JVM implementations can and do binding calls directly to kernel. If it works, usage can be as easy as: "privbind path_to_binary".

Similar package available on Debian is authbind, also using LD_PRELOAD mechanism and thus suffering from the same limitations.

setcap + chrpath

However, on Linux kernels with capabilities support (2.2+), using per-thread NET_BIND_SERVICE capability can be used to run service on privileged port without runtime superuser privileges. This capability can be enabled with setcap "eip" flags (effective, inheritable and permitted, execute as root), e.g. on Java binaries:

setcap cap_net_bind_service=+eip $JAVA_HOME/bin/java
setcap cap_net_bind_service=+eip $JAVA_HOME/jre/bin/java

While necessary, setcap might not be sufficient (as unprivileged user):

java: error while loading shared libraries: libjli.so: cannot open shared object file: No such file or directory
Examining the java binary with readelf shows:
xyz@sdk$ readelf -d java
Dynamic section at offset 0x71c contains 28 entries:
  Tag        Type                         Name/Value
 ... skipped ...
 0x00000001 (NEEDED)                     Shared library: [libc.so.6]
 0x0000000e (SONAME)                     Library soname: [lib.so]
 0x0000000f (RPATH)                      Library rpath: [$ORIGIN/../lib/amd64/jli]
According to thread in openjdk distro-pkg-dev list, glibc disallows relative paths and $ORIGIN expansion when running binary with capabilities as ordinary user (for security reasons). One solution to that is to change the RPATH encoded in ELF binary to absolute path. From Debian packages chrpath can be used for this:
chrpath -r $JAVA_HOME/lib/amd64/jli/ $JAVA_HOME/bin/java
chrpath -r $JAVA_HOME/jre/lib/amd64/jli/ $JAVA_HOME/jre/bin/java

setcap + patchelf

Changing RPATH can also be done with patchelf, not currently included in Debian packages. Sylvain Duloutre's blog post describes granting identical port binding capabilities to JVM binaries with setcap and patchelf, with RPATH change performed like this:

patchelf --set-rpath $JAVA_HOME/lib/amd64/jli $JAVA_HOME/bin/java
patchelf --set-rpath $JAVA_HOME/jre/lib/amd64/jli $JAVA_HOME/jre/bin/java

NB!

Granting capabilities to (JVM) binaries can introduce security concerns and should only be done where access to such binaries is suitably restricted.


1 privbind-devel: privbind not working with Java

Saturday, July 25, 2009

No RTFMing The Obvious

After installing PostgreSQL with Kubuntu package manager, hope was that knowing the name of the database client program, the journey could start. But:
taimo@deficiency:~$ psql
psql: FATAL: Ident authentication failed for user "taimo"

taimo@deficiency:~$ psql --help
This is psql 8.3.7, the PostgreSQL interactive terminal.

Usage:
psql [OPTIONS]... [DBNAME [USERNAME]]

General options:
-d DBNAME specify database name to connect to (default: "taimo")
-c COMMAND run only single command (SQL or internal) and exit
-f FILENAME execute commands from file, then exit
-1 ("one") execute command file as a single transaction
-l list available databases, then exit
Heh. Database might just not exist. Will see.
taimo@deficiency:~$ psql  -l
psql: FATAL: Ident authentication failed for user "taimo"
Hmm. Maybe this ident authentication thingy is all wrong?
taimo@deficiency:~$ ls /etc/postgresql/8.3/main/
environment pg_hba.conf pg_ident.conf postgresql.conf start.conf
That pg_ident.conf looked suspicious, but turned out to be empty, only noting that if ident user names coincide with PostgreSQL user names, this file is not needed. Instead special mapping 'sameuser' should be used in pg_hba.conf. And that file indeed seems to have the mapping. So what is wrong?
taimo@deficiency:~$ ls /usr/share/doc/postgresql-8.3/
changelog.Debian.gz changelog.gz copyright README README.Debian.gz
Ah. The Debian README has instructions for actually creating the database with createdb command. So the database is not even there yet!
taimo@deficiency:~$ man createdb
Normally, the database user who executes this command becomes the owner of the new database.
taimo@deficiency:~$ createdb
createdb: could not connect to database postgres: FATAL: Ident authentication failed for user "taimo"
Ah. Misread the instructions. First switch to postgres had to be done, then the PostgreSQL user with desired name and rights created, including database creation rights.
taimo@deficiency:~$ sudo -u postgres sh
[sudo] password for taimo:
$ createuser -drS taimo
$ exit
taimo@deficiency:~$ createdb

taimo@deficiency:~$ psql
Welcome to psql 8.3.7, the PostgreSQL interactive terminal.

Type: \copyright for distribution terms
\h for help with SQL commands
\? for help with psql commands
\g or terminate with semicolon to execute query
\q to quit
Yay! Seamless ident auth after creating the db user.