]> git.ipfire.org Git - thirdparty/xtables-addons.git/commitdiff
xt_SYSRQ: include host address in digest
authorJohn Haxby <john.haxby@oracle.com>
Fri, 24 Jun 2011 13:14:14 +0000 (14:14 +0100)
committerJan Engelhardt <jengelh@medozas.de>
Fri, 24 Jun 2011 22:03:28 +0000 (00:03 +0200)
The xt_SYSRQ hash now includes the destination IPv4 or IPv6 address
which makes it harder to replay a request to many different machines
in the hope that some of them are using the same password.

doc/changelog.txt
extensions/libxt_SYSRQ.man
extensions/xt_SYSRQ.c

index d74b2d83a682171c030a711eb8273f9279c7aa48..e61924fcdf2dff9c85e5cc337a12608a0aef3e1e 100644 (file)
@@ -3,6 +3,7 @@ HEAD
 ====
 Fixes:
 - xt_SYSRQ: make IPv6 trigger work again
+- xt_SYSRQ: improve security: include host address in digest
 - xt_TARPIT: fix a kernel oops in --reset mode
 
 
index 89878e0c610b6302eae4abf1bc3a5e6ae18712cb..5470066fe463e8c9c65351891016583e83c13a53 100644 (file)
@@ -36,6 +36,8 @@ The SYSRQ password can be changed through
 .IP
 echo \-n "password" >/sys/module/xt_SYSRQ/parameters/password
 .PP
+The module will not respond to sysrq requests until a password has been set.
+.PP
 Alternatively, the password may be specified at modprobe time, but this is
 insecure as people can possible see it through ps(1). You can use an option
 line in e.g. /etc/modprobe.d/xt_sysrq if it is properly guarded, that is, only
@@ -60,12 +62,13 @@ password="password"
 seqno="$(date +%s)"
 salt="$(dd bs=12 count=1 if=/dev/urandom 2>/dev/null |
     openssl enc \-base64)"
+ipaddr=10.10.25.7
 req="$sysrq_key,$seqno,$salt"
-req="$req,$(echo \-n "$req,$password" | sha1sum | cut \-c1\-40)"
+req="$req,$(echo \-n "$req,$ipaddr,$password" | sha1sum | cut \-c1\-40)"
 
-echo "$req" | socat stdin udp\-sendto:10.10.25.7:9
+echo "$req" | socat stdin udp\-sendto:$ipaddr:9
 # or
-echo "$req" | netcat \-uw1 10.10.25.7 9
+echo "$req" | netcat \-uw1 $ipaddr 9
 .fi
 .PP
 See the Linux docs for possible sysrq keys. Important ones are: re(b)oot,
@@ -73,8 +76,10 @@ power(o)ff, (s)ync filesystems, (u)mount and remount readonly. More than one
 sysrq key can be used at once, but bear in mind that, for example, a sync may
 not complete before a subsequent reboot or poweroff.
 .PP
+An IPv4 address should have no leading zeros, an IPv6 address should
+be in the form recommended by RFC 5952.  The debug option will log the
+correct form of the address.
+.PP
 The hashing scheme should be enough to prevent mis-use of SYSRQ in many
 environments, but it is not perfect: take reasonable precautions to
-protect your machines.  Most importantly ensure that each machine has a
-different password; there is scant protection for a SYSRQ packet being
-applied to a machine that happens to have the same password.
+protect your machines.
index 787204b2b936f48d8156614b0f43245bc19a3ded..a276744209c4cae4275a47b2d11309ea378e825d 100644 (file)
@@ -4,6 +4,8 @@
  *
  *     Based upon the ipt_SYSRQ idea by Marek Zalem <marek [at] terminus sk>
  *
+ *     Security additions John Haxby <john.haxby [at] oracle com>
+ *
  *     This program is free software; you can redistribute it and/or
  *     modify it under the terms of the GNU General Public License
  *     version 2 or 3 as published by the Free Software Foundation.
@@ -58,13 +60,13 @@ static char *sysrq_hexdigest;
  * is a series of sysrq requests; <seqno> is a sequence number that must be
  * greater than the last sequence number; <salt> is some random bytes; and
  * <hash> is the hash of everything up to and including the preceding ","
- * together with the password.
+ * together with "<dstaddr>,<password>".
  *
  * For example
  *
  *   salt=$RANDOM
  *   req="s,$(date +%s),$salt"
- *   echo "$req,$(echo -n $req,secret | sha1sum | cut -c1-40)"
+ *   echo "$req,$(echo -n $req,10.10.25.1,secret | sha1sum | cut -c1-40)"
  *
  * You will want a better salt and password than that though :-)
  */
@@ -121,7 +123,6 @@ static unsigned int sysrq_tg(const void *pdata, uint16_t len)
        sg_init_table(sg, 2);
 #endif
        sg_set_buf(&sg[0], data, n);
-       strcpy(sysrq_digest_password, sysrq_password);
        i = strlen(sysrq_digest_password);
        sg_set_buf(&sg[1], sysrq_digest_password, i);
        ret = crypto_hash_digest(&desc, sg, n + i, sysrq_digest);
@@ -223,6 +224,8 @@ sysrq_tg4(struct sk_buff **pskb, const struct xt_action_param *par)
                       ": " NIPQUAD_FMT ":%u -> :%u len=%u\n",
                       NIPQUAD(iph->saddr), htons(udph->source),
                       htons(udph->dest), len);
+       sprintf(sysrq_digest_password, NIPQUAD_FMT ",%s",
+               NIPQUAD(iph->daddr), sysrq_password);
        return sysrq_tg((void *)udph + sizeof(struct udphdr), len);
 }
 
@@ -253,6 +256,8 @@ sysrq_tg6(struct sk_buff **pskb, const struct xt_action_param *par)
                       ": " NIP6_FMT ":%hu -> :%hu len=%u\n",
                       NIP6(iph->saddr), ntohs(udph->source),
                       ntohs(udph->dest), len);
+       sprintf(sysrq_digest_password, NIP6_FMT ",%s",
+               NIP6(iph->daddr), sysrq_password);
        return sysrq_tg((void *)udph + sizeof(struct udphdr), len);
 }
 #endif
@@ -340,7 +345,9 @@ static int __init sysrq_crypto_init(void)
        sysrq_hexdigest = kmalloc(2 * sysrq_digest_size + 1, GFP_KERNEL);
        if (sysrq_hexdigest == NULL)
                goto fail;
-       sysrq_digest_password = kmalloc(sizeof(sysrq_password), GFP_KERNEL);
+       sysrq_digest_password =
+           kmalloc(sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255") +
+                   sizeof(sysrq_password), GFP_KERNEL);
        if (sysrq_digest_password == NULL)
                goto fail;
        do_gettimeofday(&now);