Single Packet Authorization with Fwknop
March, 2014, Note: This article proposed the fwknop vision for
SPA in 2005, and concept has been greatly extended and enhanced since then. The most updated
information about SPA can be found in the fwknop tutorial
and the fwknop design goals.
Michael Rash
Founder | Cipherdyne.org
December, 2005
Introduction:
One year ago in the December, 2004 issue of USENIX ;login: Magazine, I
described a technique for combining passive OS fingerprinting with a method of
authorization called Port Knocking in the article entitled "Combining Port
Knocking and Passive OS Fingerprinting with fwknop". Since that time I have
implemented a new method of securing IP based communications called Single
Packet Authorization (SPA) [1] that draws on some of the strengths of port
knocking and fixes some of its weaknesses. Fwknop retains the ability to
generate encrypted port knock sequences and add an additional criteria on the
OS required to honor such sequences, but the default authorization method has
been switched to SPA due to the benefits this strategy has over traditional
port knocking. This article discusses Single Packet Authorization as
implemented by fwknop, why you would want to use it, and provides an example of
using fwknop to provide an additional layer of security for OpenSSH. Fwknop is
free software released under the GNU Public License (GPL) and can be downloaded
from http://www.cipherdyne.org/fwknop/.
The Chief Innovations of Port Knocking:
When the concept of port knocking [2] was announced in 2003, many competing
implementations were rapidly developed. At last count, portknocking.org lists
nearly 30 different software projects dedicated to the specific vision of port
knocking promoted by their respective authors. Some of these projects are more
complete than others, but in general they stay true to the chief innovation of
port knocking which is the communication of information across sequences of
connections to closed ports. The port numbers themselves, instead of the
application payload portion of TCP segments or UDP datagrams, transmits the
information as it is sent from the port knocking client to the server. Of
course, the term "server" only applies to the portion of the port knocking
scheme that is designed to passively receive packets; there is no traditional
server that listens via the Berkeley sockets interface. The information
typically sent in a port knock sequence communicates desired access through a
packet filter that is protecting a particular service or set of services. The
knock server gathers the knock sequence via a passive monitoring mechanism such
as using libpcap to monitor packets as they fly by on the wire, or by
monitoring firewall logs. This allows a kernel-level packet filter (such as
Netfilter in the Linux kernel) to be configured in a default drop stance so
that the only connections to a protected service that are allowed to be
established are those that have first been associated with a valid port knock
sequence. This is a powerful concept because the end result is that code paths
that are available to a would-be attacker are minimized. Even if an attacker
possesses an exploit (0-day or otherwise) for a service that is actually
deployed on a system, it is rendered useless since a connection cannot even be
established without first issuing a valid knock sequence. When an attacker uses
the venerable Nmap with all of its sophisticated machinery to enumerate all
instances of a vulnerable service that are accessible throughout a network,
those services protected in such a manner will not appear in this list.
Single Packet Authorization vs. Port Knocking:
So far we have discussed the two most important characteristics of port
knocking in terms of enhancing security; the passive communication of
authentication information, and the server side use of a packet filter to
intercept all attempts to connect with a real server that are not associated
with a knock sequence. These two features are also used in Single Packet
Authorization to increase security, but this is where the similarities between
port knocking and SPA come to an abrupt end.
In port knocking schemes, the communications of information within packet
headers as opposed to the packet payload severely limits the amount of data
that can effectively be transferred. The port fields of the TCP and UDP headers
are 16 bits wide, so only two bytes of information can be transferred per
packet in a traditional port knock sequence. This assumes that other fields
within the packet header are not also made significant in terms of the knock
sequence, but any conceivable implementation would not be able to transmit
nearly as much information as a protocol that makes use of payload data. If
only two bytes of information were all that were required to communicate the
desired access to a knock server then this would not be a significant issue,
but it is not enough to simply create a mapping between a knock sequence
(however short) and opening a port. We also desire that our messages cannot be
easily decoded by an attacker who may be in the enviable position of being able
to monitor every packet emanating from the knock client. This requirement can
be satisfied by using an encryption algorithm, but even a symmetric block
cipher with a reasonable key size of, say, 128 bits forces at least 8 packets
to be sent at two bytes per packet.
As soon as multiple packets become involved, we need to try to ensure that
the packets arrive in order. This implies that a time delay is added between
each successive packet in the knock sequence. Simply blasting the packets onto
the network as quickly as possible might result in out of order delivery by the
time the packets reach their intended target. Because the knock server is
strictly passively monitoring packets and consequently has no notion of a
packet acknowledgment scheme, a reasonable time delay is on the order of about
a half second. Given a minimum of 8 packets to send, we are up to four seconds
just to communicate the knock sequence. In addition, if there were ever a need
to send more information, say on the order of 100 bytes, the time to send such
a message is longer than most people would be willing to wait. Single Packet
Authorization has no such limitation because the application payload portion of
packets is used to send authentication data. The result is that up to the
minimum MTU number of bytes of all networks between the client and server can
be sent in a single message, and no cumbersome time delays need to be
introduced. Fwknop uses this relatively large data size to communicate not only
detailed access requirements in SPA messages, but also entire commands to be
executed by the fwknop SPA server. Of course, all SPA messages are encrypted,
and the algorithm currently supported by fwknop is the symmetric Rijndael
cipher but the upcoming 0.9.6 release will also support asymmetric encryption
via GPG key rings and associated asymmetric cipher(s).
An additional consequence of sending multiple packets in a slow sequence
is that it becomes trivial for an attacker to break any sequence as it is
being sent by the port knocking client. All the attacker needs to do is to
spoof a duplicate packet from the source address of the client as a knock
sequence is in progress. This duplicate packet would be interpreted by the
knock server as part of the sequence, and hence breaking the original
sequence. Programs like hping (see:
http://www.hping.org) make it exceedingly
easy to spoof IP packets from arbitrary IP addresses. Single Packet
Authorization does not suffer from this type of easy injection attack.
In addition to making it difficult for an attacker to decode our messages,
we also require that even if the attacker is unsuccessful in decoding them, it
should not be possible for the attacker to replay captured messages against the
knock server. A mechanism should be in place that makes it easy for the server
to know which messages have been sent before and not honor those that are
duplicates of previous messages. It is not enough just to encrypt knock
sequences even if the IP address to which the server grants access is buried
within the encrypted sequence; consider the case where a knock client
is behind a NAT device and the attacker is on the same subnet. If a knock
sequence is sent to an external knock server, then the IP address that must be
put within the encrypted sequence is the external NAT address. Because the
attacker is on the same subnet, any connection originating from the attacker's
system to the external knock server will come from the same IP as the
legitimate connection. Hence the attacker need only replay a captured knock
sequence from the client in order to be granted exactly the same access.
In the world of traditional port knocking there are methods for preventing
replay attacks such as altering knock sequences based upon time, iterating a
hashing function as in the S/KEY system [3], or even manually changing the
agreed upon encryption key for each successful knock sequence. However, each of
these methods requires keeping state at both the client and the server, and
does not scale well once lots of users become involved. It turns out that
Single Packet Authorization facilitates a more elegant solution to the replay
problem. By having the SPA client include 16 bytes of random data in every
message and then tracking the MD5 (or other hashing function) sum of every
valid SPA message, it becomes trivial for the server to not take any action for
duplicate messages. The ability to send more than just a few bytes of data
within a SPA message is the essential innovation that really what makes this
possible. Exactly this strategy is implemented by fwknop, and will be
demonstrated in the example below.
Port knocking schemes generally use the port number within the TCP or UDP
header to transmit information from the knock client to the knock server.
However, there are lots of IP protocols such as ICMP and GRE that have space
reserved for application layer data, but have no corresponding notion of a
"port". Theoretically, SPA messages can be sent over any IP protocol; not just
those that provide a port over which data is communicated. Fwknop currently
supports sending SPA messages over ICMP.
Finally, to an observer of network traffic, a port knock sequence is
indistinguishable from a port scan. I.e. it is a series of connections to
various port numbers from a single IP address. Many network intrusion detection
systems have the capability of detecting port scans, and have no way to know
that a port knock sequence is not an attempt to enumerate the set of services
that are accessible from the IP address of the client system. Hence, any
intermediate IDS that has its port scan thresholds set low enough (i.e. the
number of packets associated with a port knock sequence exceeds the thresholds
within a given period of time) will generate port scan alerts for each port
knocking sequence. Although this by itself does not create a problem for port
knocking implementations in terms of the port knocking protocol, it can create
undue attention to anyone actually using port knocking on a network that is
monitored by an IDS. By contrast Single Packet Authorization does not create a
significant network footprint for an IDS to detect and alert upon.
Fwknop Single Packet Authorization Message Format:
In order for an fwknop SPA client to authenticate and allow the subsequent
authorization criteria to be applied [4], several pieces of information must be
securely communicated to the knock server. An fwknop client transmits the
following within each SPA message:
- 16 bytes of random data
- local username
- local timestamp
- fwknop version
- mode (access or command)
- desired access (or command string)
- MD5 sum
The 16 bytes of random data ensures that each SPA message has a extremely high
probability of being unique and hence allows the fwknop server to maintain a
cache of previously seen messages in order to thwart replay attacks. The local
username enables the fwknop server to distinguish between individual users so
that different levels of access can be granted on a per username basis. The
version number allows the fwknop message format to be extended while
preserving backwards compatibility for older versions of the software. The
mode value instructs the server that the client either wishes to gain access
to a service or run a command, each of which is specified in the next field.
The MD5 sum is calculated over the entire message and then used by the server
to verify message integrity after a successful message decrypt. Each of the
above values are concatenated together with ":" characters (with base64
encoding applied where necessary so as to not bust the field separation
convention) and then the entire message is encrypted with the Rijndael
symmetric block cipher. A symmetric key up to 128 bits in length is shared
between the fwknop SPA client and the SPA server.
Fwknop in Action:
Now let us turn to a practical example to illustrate the usage of fwknop in
the default Single Packet Authorization mode to protect and gain access to the
OpenSSH daemon. First, we configure the fwknop server to allow access to TCP
port 22 to the "mbr" username once a valid SPA message is monitored. This is
accomplished by adding the following lines to the file /etc/fwknop/access.conf:
SOURCE: ANY;
OPEN_PORTS: tcp/22;
KEY: <encrypt_key>;
FW_ACCESS_TIMEOUT: 10;
REQUIRE_USERNAME: mbr;
DATA_COLLECT_MODE: ULOG_PCAP;
In server mode, fwknop can acquire packet data by using libpcap to sniff
packets directly off the wire, out of a file that is written to by a separate
sniffer process, or by using the Netfilter ulogd pcap writer [5]. In this case
the configuration keyword "DATA_COLLECT_MODE" instructs the server to respect
SPA messages that are collected via the ulogd pcap writer. For this example,
let us assume that the IP address on the server system is 192.168.10.1, that
fwknop is running in server mode, and that Netfilter has been configured to
drop all packets destined for TCP port 22 by default.
Now, on the client, we first verify that we cannot establish a TCP
connection with sshd:
[client]$ nc -v 192.168.10.1 22
So far so good. The netcat process appears to hang because we fail to even
receive a reset packet back from the TCP stack on the server; Netfilter has
dropped our SYN packet on the floor before it can hit the TCP stack. Having a
server completely inaccessible is not of much use of course, so now we execute
the following to gain access to sshd:
[client]$ fwknop -A tcp/22 -w -k 192.168.10.1
[+] Starting fwknop in client mode.
[+] Enter an encryption key. This key must match a key in the file
/etc/fwknop/access.conf on the remote system.
Encryption Key:
[+] Building encrypted single-packet authorization (SPA) message...
[+] Packet fields:
Random data: 5628557594764037
Username: mbr
Timestamp: 1132121405
Version: 0.9.5
Action: 1 (access mode)
Access: 192.168.20.2,tcp/22
MD5 sum: q8vIpYY6q3qEflaFtU3Jag
[+] Sending 128 byte message to 192.168.10.1 over udp/62201...
Sure enough, we are now able to establish a TCP connection with port 22:
[client]$ nc -v 192.168.10.1 22
192.168.10.1 22 (ssh) open
SSH-2.0-OpenSSH_3.9p1
Fwknop running on the server has reconfigured Netfilter to allow the client IP
address to talk to sshd. Even though fwknop will expire the access rule after
10 seconds, by using the Netfilter connection tracking capability to accept
packets that are part of established TCP connections before packets are
dropped, the SSH session remains active for as long as we need it.
Finally, to illustrate the ability of fwknop to detect and stop replay
attacks, suppose that an attacker were able to sniff the SPA message above as
it was sent from the client to the server (by default fwknop sends SPA
messages over UDP port 62201, but this can be changed via the -p command line
argument):
[attacker]# tcpdump -i eth0 -c 1 -s 0 -l -nn -X udp port 62201
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes
01:44:12.170787 IP 192.168.20.6.32781 > 192.168.10.1.62201: UDP, length: 128
0x0000: 4500 009c 246a 4000 4011 768f c0a8 1406 E...$j@[email protected].....
0x0010: c0a8 0a01 800d f2f9 0088 9fc3 6736 576a ............g6Wj
0x0020: 5234 7374 4941 4358 3935 4152 6541 4778 R4stIACX95AReAGx
0x0030: 3342 7848 7569 7776 786e 557a 3531 5131 3BxHuiwvxnUz51Q1
0x0040: 5532 3976 4872 7144 6e69 3330 514f 4d72 U29vHrqDni30QOMr
0x0050: 6661 5a48 4845 304c 3631 4767 636a 6e37 faZHHE0L61Ggcjn7
0x0060: 6a64 7a6e 787a 726c 4f53 314c 5051 6877 jdznxzrlOS1LPQhw
0x0070: 394b 424f 3963 6b61 5232 2b6f 5474 736c 9KBO9ckaR2+oTtsl
0x0080: 574d 484c 574f 7736 7468 4161 7a58 3976 WMHLWOw6thAazX9v
0x0090: 2b65 6746 6352 2f2f 6776 4352 +egFcR//gvCR
1 packets captured
2 packets received by filter
0 packets dropped by kernel
Now, the attacker can replay the encrypted SPA message on the network as
follows in an effort to gain the same access as the original message [6]:
[attacker]$ echo "g6WjR4stIACX95AReAGx3BxHuiwvxnUz51Q1U29vHrqDni30QOMrfaZ
HHE0L61Ggcjn7jdznxzrlOS1LPQhw9KBO9ckaR2+oTtslWMHLWOw6thAazX9v+egFcR//gvCR"
|nc -u 192.168.10.1 62201
On the server, this results in the following syslog message indicating that
fwknop monitored the message replay and took no further action:
Nov 16 01:50:11 server fwknop: attempted message replay from: 192.168.20.2
Conclusion:
Single Packet Authorization has several characteristics that make it more
powerful and flexible than port knocking for protecting network services. Its
data transmission capabilities, coupled with its clean strategy for preventing
replay attacks make it an ideal candidate for expanding the configuration of
packet filters to drop all connections to some critical services by default.
This makes the exploitation of vulnerabilities within such services much more
difficult because an arbitrary IP address cannot enumerate or interact with
these services until a valid SPA message is generated.
References:
1. MadHat was the first person to coin the term "Single Packet Authorization"
at the BlackHat Briefings in July of 2005. However, the first available
implementation of SPA was in the 0.9.0 release of fwknop in May of 2005 (with
SPA code available via the
http://www.cipherdyne.org/
Subversion repository - now decommissioned since fwknop is now a C project
with source control provided by git)
dating back to March of 2005. Please email me if you want access to this
repository.
2. Krzywinski, M. 2003. Port Knocking: Network Authentication Across Closed
Ports. SysAdmin Magazine 12: 12-17.
3. RFC 1760; The S/KEY One-Time Password System
4. The terms "authentication" and "authorization" in this context are commonly
construed to mean the same thing. However, authentication refers to the
verification that a communication from one party to another actually came from
the first party, whereas authorization essentially refers to the process of
verifying whether one party is allowed to communicate with a second party at
all.
5. See the Netfilter ulogd project:
http://www.gnumonks.org/projects/
6. Even if the replay were successful, access would only be granted for the IP
address of the client, which is encrypted within the SPA message and hence not
available to the attacker. If however the client is behind a NAT address this
may not matter because the external address would be the same, so it is
important to stop replay attacks regardless of whether the client address is
encrypted within the SPA message or not.