xt_SYSRQ: include host address in digest

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.
This commit is contained in:
John Haxby
2011-06-24 14:14:14 +01:00
committed by Jan Engelhardt
parent 33db992c39
commit 77b29a62ee
3 changed files with 23 additions and 10 deletions

View 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

View 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.

View 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);