cipherdyne.org

Michael Rash, Security Researcher



fwknop    [Summary View]

« Previous

Software Release - fwknop-2.0.4

fwknop-2.0.4 released The 2.0.4 release of fwknop is available for download. This release includes new support for fuzzing the SPA protocol powered by the perl FKO module along with a set of patches designed to break libfko in subtle ways, and also includes several bug fixes and small enhancements. Among the most important of these include a new check for fwknop chains on iptables firewalls after the initial fwknopd start up (so the fwknop chains can be deleted out from under the fwknop daemon without affecting SPA operations), and a new 'upstart' config for systems running the upstart daemon. Many other changes were contributed by the open source community, and these are acknowledged in the complete fwknop-2.0.4 ChangeLog below:

  • [client] Misc fixes and the addition of save_args and last command (.fwknop.last) support on the Windows platform.
  • [client] Fixed bug in username determination code where a valid value could be overrwritten in certain circumstances.
  • [server] Added upstart config at extras/upstart/fwknop.conf. This allows the fwknopd to easily be managed with upstart via commands like "service fwknop start" and "service fwknop stop".
  • [server] (Vlad Glagolev) Submitted a patch to fix ndbm/gdbm usage when --disable-file-cache is used for the autoconf configure script. This functionality was broken in be4193d734850fe60f14a26b547525ea0b9ce1e9 through improper handling of #define macros from --disable-file-cache.
  • [server] (Vlad Glagolev) Submitted a patch to fix command exec mode under SPA message type validity test. Support for command exec mode was also added to the test suite.
  • (Vlad Glagolev) Submitted an OpenBSD port for fwknop-2.0.3, and this has been checked in under the extras/openbsd/ directory.
  • [server] Bug fix to allow GPG_ALLOW_NO_PW to result in not also having to specify a Rijndael key.
  • [Android] Added new .properties files to allow the fwknop client to build and function properly on the latest Android release (4.1.2).
  • [client] Added '-P udpraw' to allow the client to send SPA packets over UDP with a spoofed source IP address. This is in addition to the original 'tcpraw' and 'icmp' protocols that also support a spoofed source IP.
  • [libfko] Bug fix to check b64_decode() return value to ensure that non-base64 encoded data is never used. Even though other validation routines checked decoded results, it is important to discard invalid data as early as possible. Note too that such invalid data would only be provided to b64_decode() after proper decryption, so the client must provide authentic SPA data.
  • [libfko] Added validation of NAT access strings in the various NAT modes.
  • [libfko] Restricted usernames embedded in SPA packets to be alpha-numeric along with "-" chars.
  • [client] (Franck Joncourt) Contributed a patch to allow the fwknop client to be stopped during the password entry prompt with Ctrl-C before any SPA packet is sent on the wire.
  • [client+server] Applied patch from Franck Joncourt to remove unnecessary chmod() call when creating client rc file and server replay cache file. The permissions are now set appropriately via open(), and at the same time this patch fixes a potential race condition since the previous code used fopen() followed by chmod().
  • [server] Bug fix to accept SPA packets over ICMP if the fwknop client is executed with '-P icmp' and the user has the required privileges.
  • [test suite] Applied patch from Franck Joncourt to have the perl FKO module link against libfko in the local directory (if it exists) so that it doesn't have to have libfko completely installed in the /usr/lib/ directory. This allows the test suite to run FKO tests without installing libfko.
  • [test suite] Significant update to include a set of fuzzing SPA packets that are built using a patched version of libfko. These packets are located in the test/fuzzing/bogus_spa_packets file, and are designed to ensure proper validation of SPA packet data. This validation is performed in --enable-perl-module-checks mode via the perl FKO module.
  • [client] Added --icmp-type and --icmp-code arguments so the user can control the icmp type/code combination for spoofed SPA packets ('-P icmp') mode.
  • [client] Updated default TTL value to 64 for spoofed SPA packets. This is closer to more OS default TTL values than the previous 255.
  • Updated build CFLAGS and LDFLAGS to conform to the Debian hardening-includes file for PIE support (e.g. '-fPIE' for CFLAGS and '-fPIE -pie' for LDFLAGS).
  • [test suite] For GnuPG tests that require a passphrase associated with a gpg key, added a pinentry check to see if the local gpg engine requires it. If so, the gpg test that require a key are excluded since.
  • [server] Added a new '--pcap-file <file>' option to allow pcap files to be processed directly by fwknopd instead of sniffing an interface. This feature is mostly intended for debugging purposes.
  • [server] Added chain_exists() check to SPA rule creation so that if any of the fwknop chains are deleted out from under fwknopd they will be recreated on the fly. This mitigates scenarios where fwknopd might be started before a system level firewall policy is applied due to init script ordering, or if an iptables policy is re-applied without restarting fwknopd.
The complete fwknop-2.0.4 ChangeLog can also be found here via the fwknop gitweb interface.

Tutorial on Single Packet Authorization with fwknop

Single Packet Authorization: The fwknop Approach One thing that has been requested a few times is a tutorial on how to use fwknop, so here it is: "Single Packet Authorization: A Comprehensive Guide to Strong Service Hardening with fwknop". This document attempts to cover most usages of fwknop to wrap an SPA layer around arbitrary services, though some less used scenarios such as SPA over Tor and SPA packet spoofing are covered as well. Please contact me if you find any errors, or if you would like to see material added on a particular fwknop use case. The complete table of contents appears below:

Single Packet Authorization: The fwknop Approach

Single Packet Authorization: The fwknop Approach Update: The fwknop design material in this blog post has been updated in the fwknop tutorial.

There are many different port knocking implementations out there, and a few that take things to the next level with Single Packet Authorization. All PK/SPA implementations have three primary goals: 1) the deployment of a default-drop firewall policy for a service (such as SSHD) in order to protect against scans, potential vulnerabilities, and brute force password guessing attempts, 2) the passive monitoring of specially constructed authentication information from the PK/SPA client, and 3) the dynamic reconfiguration of the firewall to allow temporary access to the concealed service.

The PK/SPA server never acknowledges any data from the client, so it is infeasible to scan not only for any properly implemented PK/SPA server, but also for any protected service. Effectively, services become invisible to the Internet - except for those that can produce the necessary authentication information, or those that are in a privileged position to sniff traffic between an authenticated PK/SPA client and the target service.

Users of firewalls find value in the idea that traffic to a service can be blocked from all but a few pre-defined networks according to the firewall policy. Few people question whether this is valuable from a security perspective - firewalls generally enhance security (the occasional firewall vulnerability not withstanding). The PK/SPA strategy extends the notion of filtering traffic for a set of services by adding a lightweight crypto layer to allow temporary access from networks that cannot be anticipated when the firewall policy is written. This provides concealment by default, and the SPA strategy asserts that there is value in this. This can apply to all sorts of services from SSHD and OpenVPN to mail protocols like POP and IMAP and even to HTTP. Anyone scanning for services to target will never see a service protected by SPA.

If the above describes unifying aspects of PK/SPA software, this is where the similarities in PK/SPA software ends.

Below are the design choices that guide fwknop development. Other PK/SPA software make different design choices, and whether you prefer fwknop vs. another implementation depends at least partially on whether you agree with the following:

  • No heavyweight interpreted languages:
    Many people don't want to install perl, python, or ruby on a firewall or network gateway device. Such languages are large and complex, and are implemented by similarly complex binaries that are usually themselves written in a language like C. Firewalls are frequently stripped down systems that are designed to just filter network traffic, provide administrative interfaces and sometimes VPN services, and not do much else. Both the fwknop client and server are entirely written in C - there is no requirement for perl, python, or any other interpreted language.

  • Support embedded devices:
    A consequence of fwknop being developed in C is that it only uses minimal system resources and can therefore support embedded devices that don't have a lot of computing power or main memory. For example, where the older perl version of fwknop could not run on Linksys routers supported by OpenWRT, these same routers can run the newer C version of fwknop.

  • Don't require admin access to run the SPA client:
    There are many computing environments where users don't have privileged accounts. This should not present a barrier to using the SPA client. In fwknop, SPA packets are (by default) sent over a regular UDP socket and therefore require no special privileges.

  • Don't require the manipulation of raw packet headers:
    There are some SPA implementations that communicate information within specially modified fields within IP or TCP headers. Such manipulation requires that the user have the ability to acquire a raw socket from the OS, and this requires admin level privileges. In addition, depending on how the SPA client manipulates packet headers when building an SPA packet, other monitoring systems such as an IDS or a passive OS fingerprinter may produce event data that unnecessarily calls attention to the SPA communications. This is not to say that that is impossible to detect SPA packets generated by fwknop - it is just that a monitoring system is more likely to flag communications that involve manipulated packet headers than to generate an event for packets produced by fwknop. For example, intrusion detection systems track TCP connections, and spoofed TCP ACK's that are not part of a proper connection (assuming non-asymmetric routing) may potentially be flagged. Also, manipulated TCP options fields that don't conform to OS defaults will cause an OS to appear to change under the observation of things like p0f. While sometimes this is an expected behavior such as if a VM is being run or a system is actually a NAT device with other systems behind it, there are plenty of deployment scenarios where this is not expected. Addressing this issue at length could be a separate blog post in itself.

  • Don't trust the IP header:
    Any SPA implementation that trusts the source IP address in the IP header of the SPA packet is vulnerable to a MITM attack. An inline device that can intercept an SPA packet can hold the original packet and retransmit it but with the source IP changed to whatever the attacker wants. If the SPA server relies on the source IP in the IP header, then it has no way to know that it isn't legitimate. If an SPA implementation is going to go to the trouble of leveraging cryptography - certainly important since replay attacks among other problems can't be prevented without it - then the IP should be made part of an encrypted payload. This is exactly what fwknop does with the -a or -R arguments on the fwknop command line. An attacker can intercept an SPA packet produced by fwknop, change the source IP and retransmit, but SPA server will only allow access to the IP that was originally encrypted within the SPA payload.

  • Support server-side NAT:
    There are plenty of networks with a border firewall where a remote user actually wants access to a service that is running on an internal system and not on the firewall itself. Typical ways of accessing such a service involve running VPN software, but with an SPA implementation that can manipulate NAT rules on the border firewall it is possible to transparently grant SPA users access to internal services through the firewall. With fwknop, the capability to leverage server-side NAT has been built in for a long time.

  • Support multiple firewalls:
    Because fwknop does not rely on specialized logging infrastructure or link against libraries that are tied to one firewall architecture or another, it can easily support multiple firewalls just by executing the local firewall admin command line interface. It currently supports iptables on Linux, ipfw on FreeBSD and Mac OS X, and pf on OpenBSD.

  • Minimize library dependencies:
    Given the design decisions made by fwknop above, it is important to minimize library dependencies and to audit the source code. Here are all library dependencies in the fwknopd daemon including GnuPG support (this is optional):
    $ ldd ./server/.libs/fwknopd
        linux-vdso.so.1 =>  (0x00007ffeebf820e0)
        libfko.so.0 => /usr/lib/libfko.so.0 (0x00007f1a6ae930e0)
        libpcap.so.0.8 => /usr/lib/x86_64-linux-gnu/libpcap.so.0.8 (0x00007e1a6a85c0e0)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007e1a6a49e0a0)
        libgpgme.so.11 => /usr/lib/libgpgme.so.11 (0x00007f1aeaee800e)
        /lib64/ld-linux-x86-64.so.2 (0x00007e1a6aede0e0)
        libgpg-error.so.0 => /lib/x86_64-linux-gnu/libgpg-error.so.0 (0x0000ef1a6a06e0e0)
    
    The libfko library is developed by the fwknop project for SPA encryption, decryption, and validation. libpcap is a standard C library that is leveraged by a lot of security projects including intrusion detection systems and more. The gpgme libraries are only used if you want GnuPG support, and the remaining libraries are standard system libraries that typical Linux binaries need. That's it. One may certainly question the use of libpcap, and in defense of this choice note that: 1) fwknopd by default does not put the sniffing interface into promiscuous mode, 2) fwknopd by default only pays attention to UDP packets to port 62201, 3) if you examine Metasploit you'll see that there only a few exploits for pcap-based software and they target what rides on top of libpcap vs. libpcap itself, and 4) even if there is a vulnerability in libpcap, the exploit model is different than it is for normal server software that you can easily scan for, and being different in this game is good.

  • Support both symmetric and asymmetric ciphers:
    Some users prefer the security properties that asymmetric crypto systems have over those provided by symmetric algorithms like Rijndael, or vice versa. fwknop supports both Rijndael and GnuPG for SPA encryption/decryption.

  • Support HMAC in the encrypt-then-authenticate model:
    Authenticated encryption with an HMAC is supported by fwknop as of the 2.5 release for both symmetric and asymmetric encryption modes. The implementation is careful to apply an HMAC to SPA packets according to the encrypt-then-authenticate model which provides strong resistance to certain kinds of cryptanalytic attacks. In addition, on the fwknopd server side, verification of the HMAC is a more simplistic operation than sending data through a set of decryption routines, so this provides an additional security benefit by reducing the complexity of code the malicious traffic can interact with. This is particularly true for SPA packets that are encrypted with GnuPG.

Software Release - fwknop-2.0.3

fwknop-2.0.3 released The fwknop-2.0.3 release of fwknop is available for download. This is an important release that tightens up the code in several areas based on excellent research performed by Fernando Arnaboldi of IOActive. I wish to thank Fernando for this work, and also Erik Gomez of IOActive as well for making this research possible. Fernando's research turned up potential DoS and/or code execution vulnerabilities in the fwknopd server for malicious authenticated clients, insecure filesystem permissions handling, and more. All of these issues have been fixed in the 2.0.3 release.

Here is the complete fwknop-2.0.3 ChangeLog:

  • [server] Fernando Arnaboldi from IOActive found several DoS/code execution vulnerabilities for malicious fwknop clients that manage to get past the authentication stage (so a such a client must be in possession of a valid access.conf encryption key). These vulnerabilities manifested themselves in the handling of malformed access requests, and both the fwknopd server code along with libfko now perform stronger input validation of access request data. These vulnerabilities affect pre-2.0.3 fwknop releases.
  • [server] Fernando Arnaboldi from IOActive found a condition in which the server did not properly validate allow IP addresses from malicious authenticated clients. This has been fixed with stronger allow IP validation.
  • [client+server] Fernando Arnaboldi from IOActive found that strict filesystem permissions for various fwknop files are not verified. Added warnings whenever permissions are not strict enough, and ensured that files created by the fwknop client and server are only set to user read/write.
  • [client] Fernando Arnaboldi from IOActive found a local buffer overflow in --last processing with a maliciously constructed ~/.fwknop.run file. This has been fixed with proper validation of .fwknop.run arguments.
  • [server] Fernando Arnaboldi from IOActive found several conditions in which the server did not properly throw out maliciously constructed variables in the access.conf file. This has been fixed along with new fuzzing tests in the test suite.
  • [test suite] Added a new fuzzing capability to ensure proper server-side input validation. Fuzzing data is constructed with modified fwknop client code that is designed to emulate malicious behavior.
  • Fixed RPM builds by including the $(DESTDIR) prefix for uninstall-local and install-exec-hook stages in Makefile.am.
The fwknop-2.0.3 ChangeLog can also be found here via the fwknop gitweb interface.

On GnuPG Encrypted SPA Cross-Packet Entropy

fwknop GnuPG SPA packet entropy After writing about SPA cross-packet entropy using the Rijndael symmetric cipher and seeing good randomization across every byte position, I thought it would be informative to perform the same analysis for SPA packets that are encrypted with GnuPG. Prior to this analysis, I would have thought that GnuPG would produce similar results in that there should not be specific byte positions that would exhibit low levels of entropy, but it turns out that there are positions where measured entropy falls off significantly. Further, even though entropy is reduced at these positions, there is a good reason for this and does not indicate an issue with how fwknop leverages GnuPG (or with GnuPG itself).

First, recall that for Rijndael, the set of SPA packets as profiled by the spa-entropy.pl script along with the ent program produced the following graph that shows about 7.80 bits of entropy per byte on average: SPA entropy for CBC mode Given this graph, it is apparent that Rijndael comes pretty close to producing data that looks quite random across every byte position and there are no significant outliers. Now, let us run the spa-entropy.pl script in --gpg mode in order to instruct the fwknop client to generate SPA packets that are encrypted with GnuPG:
$ ./spa-entropy.pl -f 1000_pkts.data -r -c 1000 --base64-decode --gpg
[+] Running fwknop client via the following command:

LD_LIBRARY_PATH=../../lib/.libs ../../client/.libs/fwknop -A tcp/22 -a 127.0.0.2 -D 127.0.0.1 --get-key ../../test/local_spa.key -B 1000_pkts.data -b -v --test --gpg-recipient-key 361BBAD4 --gpg-signer-key 6A3FAD56 --gpg-home-dir ../../test/conf/client-gpg 2> /dev/null

[+] Read in 1000 SPA packets...
[+] Min entropy: 0.00 at byte: 1
[+] Max entropy: 7.85 at byte: 654
[+] Creating entropy.gif gnuplot graph...
This results in the following gnuplot graph: SPA entropy for GnuPG cipher Wow, it is immediately apparent that there is something quite different about the measured entropy for GnuPG SPA packets. There are three areas of interest: 1) the first four bytes, 2) two bytes or so around byte 275, and 3) four bytes around byte 525. Why does the entropy fall off so drastically at these locations? The first region is most likely an artifact of the usage of the same GnuPG key across all SPA packets along with the fact that the fwknop client only strips off the first two bytes if they match the string "hQ" in the base64 encoded SPA data. This string corresponds to the same values that the /etc/magic database provides to the file command - it is the same across all GnuPG encrypted data regardless of which keys are used. But, the next four bytes aren't as predictable, and must vary from key to key so the fwknop client can't use a simple strategy of removing these bytes before an SPA packet is placed on the wire. (The whole reason for removing the bytes in the first place is to make it slightly more difficult to write a simplistic Snort signature for SPA packet detection.) The next two regions can be explained by the fact that the OpenPGP protocol (see: RFC 4880) often results in messages that are created with partial body lengths and corresponding length headers must be added into the data. Because SPA packets created by fwknop are usually nearly identical in size, these length headers would be added around the same positions and have the same data - this results in the entropy dips around bytes 275 and 525 across multiple SPA packets.

An interesting next step might be to run the same analysis on systems with poor entropy sources. On such a system, it would then be informative to have the fwknop client switch to Dan Kaminsky's new dakarand entropy source that is based on clock drift and see if things improve.

Software Release - fwknop-2.0.2

fwknop-2.0.2 released The fwknop-2.0.2 release of fwknop is available for download. This release includes new support for SPA using GPG keys in automated environments, and this particularly affects fwknopd server deployments on systems where the GnuPG engine seems to require gpg-agent or pinentry for passphrase entry associated with GnuPG keys. In addition, a couple of important bug fixes were made to ensure replay attack detection is properly done when SPA packet prefixes are added/removed (this is done to increase the difficulty of using Snort or other IDS to detection SPA packets on the wire).

Here is the complete fwknop-2.0.2 ChangeLog:

  • [server] For GPG mode, added a new access.conf variable "GPG_ALLOW_NO_PW" to make it possible to leverage a server-side GPG key pair that has no associated password. This comes in handy when a system requires the user to leverage gpg-agent / pinentry which can present a problem in automated environments as required by the fwknopd server. Now, it might seem like a problem to remove the passphrase from a GPG key pair, but it's important to note that simply doing this is little worse than storing the passphrase in the clear on disk anyway in the access.conf file. Further, this link helps provide additional detail:

    http://www.gnupg.org/faq/GnuPG-FAQ.html#how-can-i-use-gnupg-in-an-automated-environment

  • [client] In IP resolution mode (-R) changed HTTP connection type to 'close' since there is no need for connection persistence, and indeed the client expects to just get the IP and the connection to be closed. Jonathan Schulz submitted a patch for this.
  • [client] Bug fix to ensure that all data is read via recv() from a remote webserver IP resolution mode (-R). Previously IP resolution could fail if HTTP headers were transferred separately from the data (for whatever reason). Jonathan Schulz submitted a patch for this.
  • [client] Added backup check against a cipherdyne.com 'myip' cgi instance in -R mode if the normal check against cipherdyne.org fails.
  • [server] Bug fix to implement FLUSH_IPT_AT_INIT and FLUSH_IPT_AT_EXIT functionality. These are enabled by default, and now iptables rules added by fwknopd can be made persistant by setting these variables to "N" in the fwknopd.conf file (this is not a recommended setting however).
  • [server] Added FLUSH_IPFW_AT_INIT and FLUSH_IPFW_AT_EXIT for ipfw firewalls to emulate the corresponding functionality that is implemented for iptables firewalls. This was suggested by Jonathan Schulz.
  • [server] Replay attack bug fix to ensure that an attacker cannot force a replay attack by intercepting an SPA packet and the replaying it with the base64 version of "Salted__" (for Rindael) or the "hQ" prefix (for GnuPG). This is an important fix. The following comment was added into the fwknopd code:

    /* Ignore any SPA packets that contain the Rijndael or GnuPG prefixes
     * since an attacker might have tacked them on to a previously seen
     * SPA packet in an attempt to get past the replay check.  And, we're
     * no worse off since a legitimate SPA packet that happens to include
     * a prefix after the outer one is stripped off won't decrypt properly
     * anyway because libfko would not add a new one.
    */
    
  • [server] Fixed a memory leak bug in the replay attack detection code. The leak was found with the test suite in --enable-valgrind mode, and here is the valgrind trace that exposed it:

    44 bytes in 1 blocks are definitely lost in loss record 2 of 2
       at 0x482BE68: malloc (in
       /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
       by 0x490EA50: strdup (strdup.c:43)
       by 0x10CD69: incoming_spa (incoming_spa.c:162)
       by 0x10E000: process_packet (process_packet.c:200)
       by 0x4862E63: ??? (in /usr/lib/i386-linux-gnu/libpcap.so.1.1.1)
       by 0x4865667: pcap_dispatch (in /usr/lib/i386-linux-gnu/libpcap.so.1.1.1)
       by 0x10DABF: pcap_capture (pcap_capture.c:226)
       by 0x10A798: main (fwknopd.c:299)
    
  • [test suite] Added GPG tests for keyrings that have no associated passphrases.
  • [server] Implemented a new check to ensure that the iptables 'comment' match exists to ensure the proper environment for fwknopd operations. This check is controlled by the new ENABLE_IPT_COMMENT_CHECK variable, and was suggested by Hank Leininger.
  • [server] 'make install' fix to ensure restrictive permissions on the /etc/fwknop/ directory and /etc/fwknop/* files. Also updated the 'make install' step to not overwrite any existing config files in /etc/fwknop/ and instead install new copies from the source tree at /etc/fwknop/fwknopd.conf.inst and /etc/fwknop/access.conf.inst
The complete fwknop-2.0.2 ChangeLog can be found here via the fwknop gitweb interface.

HOPE 9 Talk: Recent Advances in Single Packet Authorization

SPA talk slides from the HOPE 9 conference About a week ago at the HOPE Number Nine conference in NYC I gave a talk entitled "Recent Advances in Single Packet Authorization" (slides). In some respects this talk was a follow up to my talk on SPA and fwknop from the Last HOPE conference in 2008. Back then, the work on the all-C implementation of fwknop had just begun and this work was designed to address some of the questions that were brought up such as "have you audited all of the code in the perl module dependencies?" and "does the fwknop client run on the iPhone?". With the fwknop-2.0 release, the client does run on the iPhone and many other devices besides, and auditing huge code bases from dependent perl modules is no longer necessary.

Beyond this, fwknop strives to make sophisticated usage of NAT for authenticated connections, and this is realized with a use case whereby fwknop is used to protect against the recent Windows RDP vulnerability (CVE-2012-0002) within Amazon Virtual Private Cloud (VPC) networks. Of course, at this point the vulnerability has been patched, but for a time it wasn't and this is where SPA comes in. One challenge for this is the fact that fwknopd does not directly support a Windows firewall. The solution is to deploy a virtual Linux instance on the VPC network and then use either the normal SNAT/DNAT capabilities in fwknopd, or use the new FORCE_NAT mode. Either way, RDP connections can be made to internal Windows systems through the Linux "jump host" after a proper SPA packet is sent. Further, only one Amazon Elastic IP is required in order for this to work - the IP is bound to the Linux host and no externally routable IP is given to the Windows host. The Windows system only ever sees what appears to be a connection from the Linux host even though it has really been NAT'd through from the external Internet. Below is a network diagram that illustrates this, and more detail can be found in the slides. .

Software Release - fwknop-2.0.1

fwknop-2.0.1 released The fwknop-2.0.1 release is fwknop is available for download. This is mainly a bug fix release before the new HMAC-SHA256 work is ready for general consumption. A couple of the fixes are important for PF users on OpenBSD and for people who use the same encryption key within multiple access stanzas.

Here is the complete fwknop-2.0.1 ChangeLog:

  • [server] Bug fix where the same encryption key used for two stanzas in the access.conf file would result in access requests that matched the second stanza to always be treated as a replay attack. This has been fixed for the fwknop-2.0.1 release, and was reported by Andy Rowland. Now the fwknopd server computes the SHA256 digest of raw incoming payload data before decryption, and compares this against all previous hashes. Previous to this commit, fwknopd would add a new hash to the replay digest list right after the first access.conf stanza match, so when SPA packet data matched the second access.conf stanza a matching replay digest would already be there.
  • [server] Updated PCAP_LOOP_SLEEP default to 1/10th of a second (in microseconds). This was supposed to be the default anyway, but C Anthony Risinger reported a bug where fwknopd was consuming more resources than necessary, and the cause was PCAP_LOOP_SLEEP set by default to 1/100th of a second - this has been fixed.
  • [libfko] Added SPA message validation calls to fko decoding routines to help ensure that SPA messages conform to expected values.
  • Bug fix for PF firewalls: updated the PF anchor check to not rely on listing the PF policy - fwknopd now uses 'pfctl -s Anchor' instead.
  • [test suite] Added parsing of valgrind output to produce a listing of functions that have been flagged - this assists in the development process to ensure that fwknop is not leaking memory.
  • [test suite] Bug fix on Mac OS X systems to account for libfko.dylib path instead of libfko.so. This fixes the existence check for libfko.
  • [test suite] Added tests for --nat-local mode.
  • [client] Fixed several minor memory leaks caught by valgrind.
  • [libfko] Minor gcc warning fix: fko_decode.c:43:17: warning: variable ‘edata_size’ set but not used [-Wunused-but-set-variable].
  • Updated fwknopd init script for Debian systems (contributed by Franck Joncourt).
The complete fwknop-2.0.1 ChangeLog can be found here via the fwknop gitweb interface.

On SPA Cross-Packet Ciphertext Entropy

fwknop SPA packet entropy With fwknop now re-written in C for the 2.0 release, I thought it would be a good idea to take a look at how close encrypted SPA packet data comes to having high levels of entropy - as understood to be a measure of randomness - from one packet to the next. If fwknop is properly using encryption, and the ciphers themselves are also well-implemented (fwknop can use either Rijndael or GPG), then we would expect there to be no obvious relationship between SPA packets even for repeated access requests to the same service. If there are any such relationships in the encrypted data across multiple SPA packets, then an adversary might be able to infer things about the underlying plaintext - precisely what strong encryption is supposed to make difficult. This blog post covers SPA packet entropy for AES (Rijndael) CBC and ECB encryption modes, and leaves GPG to another post.

Although this post has some similarities with an older blog entry "Visualizing SPA Packet Randomness", a more rigorous and automated way of measuring cross-packet SPA entropy will be presented. In addition, we'll take a look at what happens when (normally) random salt values for AES encrypted SPA packets are artificially forced to be constant. This helps to highlight some real differences in AES electronic codebook (ECB) and cipher block chaining (CBC) encryption modes.

First, the next release of fwknop will most likely offer the ability to select different AES encryption modes (such as cipher feedback (CFB) mode and output feedback (OFB) mode), and a dedicated "crypto_update" branch has been created for this work. The default AES encryption mode used by fwknop is cipher block chaining (CBC) mode as defined here. Within the crypto_update branch there is a new script "spa-entropy.pl" that is designed to execute the fwknop client multiple times, collect the encrypted SPA packet data, use the ent program to measure the entropy in slices for each byte position across the SPA data set, and then plot the results with gnuplot. What does this accomplish? It allows us to easily see for any given byte position within a collection of SPA packets whether there is a relation from one to the next. If there is such a relation, then the cipher used to encrypt the data was not very good at achieving high levels of entropy in the ciphertext across multiple packets.

As a motivating example from Wikipedia, AES in ECB mode encrypts identical plaintext blocks into identical ciphertext blocks, and this results in patterns in plaintext data being preserved to some extent in the ciphertext. So, an adversary can make good guesses about the underlying plaintext just by looking at the ciphertext! Wikipedia does a nice job of illustrating this with the following two images of the Linux kernel mascot "Tux" - before and after AES encryption in ECB mode:

plaintext Tux       AES ECB encryption ->                     AES ECB encrypted Tux
Encryption Fail.

Now, let's take a look at SPA packet entropy with the spa-entropy.pl script. For reference, fwknop builds SPA packets according to the following data format before encryption:

[random data: 16 bytes]:[username]:[timestamp]:[version]:[message type]:[access request]:[digest]

So, if a user wants repeated access to the same service protected behind fwknopd on some system, then several fields above will be identical across the corresponding SPA packets before they are encrypted. The username, version, message type, and access request fields will likely be the same. If fwknop has made proper use of encryption, then the fact that these fields are the same across multiple SPA packets should not matter. After encryption, an observer should not be able to tell anything about the underlying plaintext (other than perhaps size since AES is a block cipher). Let's verify this for 1,000 SPA packets encrypted with the default CBC mode - they are all encrypted with the same key 'fwknoptest' by the spa-entropy.pl script: $ ./spa-entropy.pl -f 1000_pkts.data -r -c 1000 --base64-decode
[+] Running fwknop client via the following command:

LD_LIBRARY_PATH=../../lib/.libs ../../client/.libs/fwknop -A tcp/22 -a 127.0.0.2 -D 127.0.0.1 --get-key local_spa.key -B 1000_pkts.data -b -v --test -M cbc

[+] Read in 1000 SPA packets...
[+] Min entropy: 7.75 at byte: 54
[+] Max entropy: 7.86 at byte: 115
[+] Creating entropy.gif gnuplot graph...
This produces the gnuplot graph below. Perfectly random data would produce 8 bits of entropy per byte, and the min/max values of 7.75 and 7.86 along with the fairly uniform distribution of similar values across all of the SPA byte positions implies that there is little relation from one SPA packet to the next - good. SPA entropy for CBC mode As an aside, here is what ent reports against the local /dev/urandom entropy source on my Linux system, and it is the "Entropy =" line that spa-entropy.pl parses for each SPA byte slice: $ dd if=/dev/urandom count=1000 |ent
1000+0 records in
1000+0 records out
512000 bytes (512 kB) copied, 0.128497 s, 4.0 MB/s
Entropy = 7.999625 bits per byte.

Optimum compression would reduce the size
of this 512000 byte file by 0 percent.

Chi square distribution for 512000 samples is 265.77, and randomly
would exceed this value 50.00 percent of the times.

Arithmetic mean value of data bytes is 127.5076 (127.5 = random).
Monte Carlo value for Pi is 3.138715386 (error 0.09 percent).
Serial correlation coefficient is -0.001293 (totally uncorrelated = 0.0).
Now, let's switch to ECB mode and see what happens (just run the spa-entropy.pl script with '-e ecb'): SPA entropy for ECB mode Well, that still looks pretty good. Revisiting the ECB encrypted image of Tux above for a moment - the reason that the Tux outline can be seen in the encrypted version is that in the JPG image file there must be identical blocks in multiple locations to represent the solid black regions. These blocks are all encrypted in the same way by AES in ECB mode, so the outline persists. But, this is one instance of ECB encryption against a file that has multiple identical blocks. For the encrypted SPA packets, we're dealing with 1,000 separate instances of encrypted data (all with the same key). Across this data set there are certainly lots of identical plaintext blocks (all of the SPA packets request access for source IP 127.0.0.2 to destination port tcp/22 for example), but the encrypted data still shows a high level of entropy. This source of entropy is provided by the random salt values that are used to generate the initialization vector and final encryption key for each encrypted SPA packet. As proof, if we apply the following patch to force the salt to zero for all SPA packets (of course, one would not want to use this patch in practice): $ git diff lib/cipher_funcs.c
diff --git a/lib/cipher_funcs.c b/lib/cipher_funcs.c
index 0a0ce3b..32c8bd6 100644
--- a/lib/cipher_funcs.c
+++ b/lib/cipher_funcs.c
@@ -153,6 +153,8 @@ rij_salt_and_iv(RIJNDAEL_context *ctx, const char *pass, const unsigned char *da
         get_random_data(ctx->salt, 8);
     }

+    memset(ctx->salt, 0x00, 8);
+
     /* Now generate the key and initialization vector.
      * (again it is the perl Crypt::CBC way, with a touch of
      * fwknop).
Here is what spa-entropy.pl reports after recompiling fwknop with the patch above: SPA entropy for ECB mode zero salt Now we can easily see where there are identical blocks across the SPA packet data set. The first eight bytes contains the salt, so these are all zero (note that fwknop strips the usual "Salted__" prefix before transmitting an SPA packet on the wire). The next 16 bytes are the random bytes that fwknop includes in every SPA packet so these bytes have high entropy. Next up are the username and timestamp - the later changes with each second, so there is some entropy there since it takes a few seconds to create the 1,000 SPA packet data set. Then the entropy goes back to zero with the next fields and there isn't any decent entropy until the final message digest.

As a final contrasting case, let's leave the patch applied to force the salt to zero, but now switch back to CBC mode: SPA entropy for CBC mode zero salt In CBC mode, the random data included by the fwknop client now results in decent entropy even though the salt is zero. This is because every ciphertext block in CBC mode depends on all previous plaintext blocks, so randomness in one plaintext block implies that every subsequent encrypted block will look different from one SPA packet to the next. This graphically shows that CBC mode is a better choice for strong security. Now, if the pseudo random number generator on the local operating system is poorly implemented, this will negatively impact ciphertext entropy regardless of the encryption mode, but still CBC mode is a better alternative than ECB mode.

Although spa-entropy.pl is geared towards measuring SPA packet entropy, this technique could certainly be generalized to arbitrary collections of ciphertext. If you know of such an implementation, please email me.

Software Release - fwknop-2.0

fwknop-2.0 released After a long development cycle, fwknop-2.0 has been released. This is the first production release of the fully re-written C version of fwknop, and is the culmination of an effort to provide Single Packet Authorization to multiple open source firewalls, embedded systems, mobile devices, and more. On the "server" side, supported firewalls now include iptables on Linux, ipfw on FreeBSD and Mac OS X, and pf on OpenBSD. The fwknop client is known to run on all of these platforms, and also functions on Windows systems running under Cygwin. There is also an Android client, and a good start on a iPhone client as well. On a personal note, I wish to thank Damien Stuart for a heroic effort to port most of the original perl code over to C. Also, several other people have made significant contributions including Jonathan Bennet, Max Kastanas, Sebastien Jeanquier, Ozmart, and others. If there are any issues, please get in touch with me directly or send an email to the fwknop mailing list.

Update 01/03: Both libfko library that powers much of fwknop operations and the fwknop client can be compiled as native Windows executables. In addition, there are perl and python bindings to libfko as well.

Update 01/07: Damien Stuart has built RPM files for fwknop on RHEL5, RHEL6, Fedora 15, 16, and 17 and for other architectures the Fedora koji build system can produce.
« Previous