189 lines
8.1 KiB
XML
189 lines
8.1 KiB
XML
<?xml version='1.0' encoding='utf-8' ?>
|
|
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
|
]>
|
|
<chapter id="chap-Defensive_Coding-Authentication">
|
|
<title>Authentication and Authorization</title>
|
|
|
|
<section id="sect-Defensive_Coding-Authentication-Server">
|
|
<title>Authenticating servers</title>
|
|
<para>
|
|
When connecting to a server, a client has to make sure that it
|
|
is actually talking to the server it expects. There are two
|
|
different aspects, securing the network path, and making sure
|
|
that the expected user runs the process on the target host.
|
|
There are several ways to ensure that:
|
|
</para>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>
|
|
The server uses a TLS certificate which is valid according
|
|
to the web browser public key infrastructure, and the client
|
|
verifies the certificate and the host name.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
The server uses a TLS certificate which is expectedby the
|
|
client (perhaps it is stored in a configuration file read by
|
|
the client). In this case, no host name checking is
|
|
required.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
On Linux, UNIX domain sockets (of the
|
|
<literal>PF_UNIX</literal> protocol family, sometimes called
|
|
<literal>PF_LOCAL</literal>) are restricted by file system
|
|
permissions. If the server socket path is not
|
|
world-writable, the server identity cannot be spoofed by
|
|
local users.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
Port numbers less than 1024 (<emphasis>trusted
|
|
ports</emphasis>) can only be used by
|
|
<literal>root</literal>, so if a UDP or TCP server is
|
|
running on the local host and it uses a trusted port, its
|
|
identity is assured. (Not all operating systems enforce the
|
|
trusted ports concept, and the network might not be trusted,
|
|
so it is only useful on the local system.)
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
<para>
|
|
TLS (<xref linkend="chap-Defensive_Coding-TLS"/>) is the
|
|
recommended way for securing connections over untrusted
|
|
networks.
|
|
</para>
|
|
<para>
|
|
If the server port number is 1024 is higher, a local user can
|
|
impersonate the process by binding to this socket, perhaps after
|
|
crashing the real server by exploiting a denial-of-service
|
|
vulnerability.
|
|
</para>
|
|
</section>
|
|
|
|
<section id="sect-Defensive_Coding-Authentication-Host_based">
|
|
<title>Host-based authentication</title>
|
|
<para>
|
|
Host-based authentication uses access control lists (ACLs) to
|
|
accept or deny requests from clients. Thsis authentication
|
|
method comes in two flavors: IP-based (or, more generally,
|
|
address-based) and name-based (with the name coming from DNS or
|
|
<filename>/etc/hosts</filename>). IP-based ACLs often use
|
|
prefix notation to extend access to entire subnets. Name-based
|
|
ACLs sometimes use wildcards for adding groups of hosts (from
|
|
entire DNS subtrees). (In the SSH context, host-based
|
|
authentication means something completely different and is not
|
|
covered in this section.)
|
|
</para>
|
|
<para>
|
|
Host-based authentication trust the network and may not offer
|
|
sufficient granularity, so it has to be considered a weak form
|
|
of authentication. On the other hand, IP-based authentication
|
|
can be made extremely robust and can be applied very early in
|
|
input processing, so it offers an opportunity for significantly
|
|
reducing the number of potential attackers for many services.
|
|
</para>
|
|
<para>
|
|
The names returned by <function>gethostbyaddr</function> and
|
|
<function>getnameinfo</function> functions cannot be trusted.
|
|
(DNS PTR records can be set to arbitrary values, not just names
|
|
belong to the address owner.) If these names are used for ACL
|
|
matching, a forward lookup using
|
|
<function>gethostbyaddr</function> or
|
|
<function>getaddrinfo</function> has to be performed. The name
|
|
is only valid if the original address is found among the results
|
|
of the forward lookup (<emphasis>double-reverse
|
|
lookup</emphasis>).
|
|
</para>
|
|
<para>
|
|
An empty ACL should deny all access (deny-by-default). If empty
|
|
ACLs permits all access, configuring any access list must switch
|
|
to deny-by-default for all unconfigured protocols, in both
|
|
name-based and address-based variants.
|
|
</para>
|
|
<para>
|
|
Similarly, if an address or name is not matched by the list, it
|
|
should be denied. However, many implementations behave
|
|
differently, so the actual behavior must be documented properly.
|
|
</para>
|
|
<para>
|
|
IPv6 addresses can embed IPv4 addresses. There is no
|
|
universally correct way to deal with this ambiguity. The
|
|
behavior of the ACL implementation should be documented.
|
|
</para>
|
|
</section>
|
|
|
|
<section id="sect-Defensive_Coding-Authentication-UNIX_Domain">
|
|
<title>UNIX domain socket authentication</title>
|
|
<para>
|
|
UNIX domain sockets (with address family
|
|
<literal>AF_UNIX</literal> or <literal>AF_LOCAL</literal>) are
|
|
restricted to the local host and offer a special authentication
|
|
mechanism: credentials passing.
|
|
</para>
|
|
<para>
|
|
Nowadays, most systems support the
|
|
<literal>SO_PEERCRED</literal> (Linux) or
|
|
<literal>LOCAL_PEERCRED</literal> (FreeBSD) socket options, or
|
|
the <function>getpeereid</function> (other BSDs, MacOS X).
|
|
These interfaces provide direct access to the (effective) user
|
|
ID on the other end of a domain socket connect, without
|
|
cooperation from the other end.
|
|
</para>
|
|
<para>
|
|
Historically, credentials passing was implemented using
|
|
ancillary data in the <function>sendmsg</function> and
|
|
<function>recvmsg</function> functions. On some systems, only
|
|
credentials data that the peer has explicitly sent can be
|
|
received, and the kernel checks the data for correctness on the
|
|
sending side. This means that both peers need to deal with
|
|
ancillary data. Compared to that, the modern interfaces are
|
|
easier to use. Both sets of interfaces vary considerably among
|
|
UNIX-like systems, unfortunately.
|
|
</para>
|
|
<para>
|
|
If you want to authenticate based on supplementary groups, you
|
|
should obtain the user ID using one of these methods, and look
|
|
up the list of supplementary groups using
|
|
<function>getpwuid</function> (or
|
|
<function>getpwuid_r</function>) and
|
|
<function>getgrouplist</function>. Using the PID and
|
|
information from <filename>/proc/PID/status</filename> is prone
|
|
to race conditions and insecure.
|
|
</para>
|
|
</section>
|
|
|
|
<section id="sect-Defensive_Coding-Authentication-Netlink">
|
|
<title><literal>AF_NETLINK</literal> authentication of origin</title>
|
|
<!-- ??? kernel change may make this obsolete:
|
|
https://bugzilla.redhat.com/show_bug.cgi?id=851968 -->
|
|
<para>
|
|
Netlink messages are used as a high-performance data transfer
|
|
mechanism between the kernel and the userspace. Traditionally,
|
|
they are used to exchange information related to the network
|
|
statck, such as routing table entries.
|
|
</para>
|
|
<para>
|
|
When processing Netlink messages from the kernel, it is
|
|
important to check that these messages actually originate from
|
|
the kernel, by checking that the port ID (or PID) field
|
|
<literal>nl_pid</literal> in the <literal>sockaddr_nl</literal>
|
|
structure is <literal>0</literal>. (This structure can be
|
|
obtained using <function>recvfrom</function> or
|
|
<function>recvmsg</function>, it is different from the
|
|
<literal>nlmsghdr</literal> structure.) The kernel does not
|
|
prevent other processes from sending unicast Netlink messages,
|
|
but the <literal>nl_pid</literal> field in the sender's socket
|
|
address will be non-zero in such cases.
|
|
</para>
|
|
<para>
|
|
Applications should not use <literal>AF_NETLINK</literal>
|
|
sockets as an IPC mechanism among processes, but prefer UNIX
|
|
domain sockets for this tasks.
|
|
</para>
|
|
</section>
|
|
</chapter>
|
|
|