cipherdyne.org

Michael Rash, Security Researcher



Chapter 12: Port Knocking vs. Single Packet Authorization

Passive authorization is becoming increasingly important for keeping networked services secure. The damaging scope of zero-day vulnerabilities can be severely limited by using such a technology, but not all passive authorization paradigms are robust enough for critical deployments. Chapter 12 compares and contrasts two passive authorization mechanisms: port knocking and Single Packet Authorization (SPA).

As mentioned in the chapter, a script that uses the checksum field in the UDP header can be downloaded here (or see below). You can also download a rudimentary script for generating an encrypted list of port values for port knocking applications. This script is for illustration purposes only, and is far exceeded by the capabilities offered by fwknop.

#!/usr/bin/perl -w
#
#############################################################################
#
# File: craft_udp_checksum.pl
#
# Purpose: To allow the checksum portion of the UDP header to be manually
#          set to a specific value from the command line and then sent to an
#          arbitrary port at a destination IP address.  This script was
#          written for the No Starch Press book "Linux Firewalls: Attack
#          Detection and Response".
#
# Copyright (C) 2006 Michael Rash (mbr@cipherdyne.org)
#
# License (GNU Public License):
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program; if not, write to the Free Software
#   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
#   USA
#
#
#############################################################################
#
# $Id: index.html 2980 2011-01-09 15:27:41Z mbr $
#

use Net::RawIP;
use strict;

my $src  = $ARGV[0] || &usage();
my $dst  = $ARGV[1] || &usage();
my $port = $ARGV[2] || &usage();
my $sum  = $ARGV[3] || 0;

$sum = hex $sum;

my $raw_udp = new Net::RawIP({
    ip => {
        saddr => $src,
        daddr => $dst
    },
    udp =>{}}
);

$raw_udp->set({
    ip  => {
        saddr => $src,
        daddr => $dst
    },
    udp => {
        source => 30401,
        dest   => $port,
        check  => $sum
    },
});

printf "[+] Sending UDP packet $src -> $dst ($port) with checksum %x\n",
    $sum;
$raw_udp->send();

exit 0;

sub usage() {
    die "[*] $0 <src> <dst> <port> <checksum>";
}