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: Fixes:
- xt_SYSRQ: make IPv6 trigger work again - 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 - xt_TARPIT: fix a kernel oops in --reset mode

View File

@@ -36,6 +36,8 @@ The SYSRQ password can be changed through
.IP .IP
echo \-n "password" >/sys/module/xt_SYSRQ/parameters/password echo \-n "password" >/sys/module/xt_SYSRQ/parameters/password
.PP .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 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 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 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)" seqno="$(date +%s)"
salt="$(dd bs=12 count=1 if=/dev/urandom 2>/dev/null | salt="$(dd bs=12 count=1 if=/dev/urandom 2>/dev/null |
openssl enc \-base64)" openssl enc \-base64)"
ipaddr=10.10.25.7
req="$sysrq_key,$seqno,$salt" 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 # or
echo "$req" | netcat \-uw1 10.10.25.7 9 echo "$req" | netcat \-uw1 $ipaddr 9
.fi .fi
.PP .PP
See the Linux docs for possible sysrq keys. Important ones are: re(b)oot, 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 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. not complete before a subsequent reboot or poweroff.
.PP .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 The hashing scheme should be enough to prevent mis-use of SYSRQ in many
environments, but it is not perfect: take reasonable precautions to environments, but it is not perfect: take reasonable precautions to
protect your machines. Most importantly ensure that each machine has a protect your machines.
different password; there is scant protection for a SYSRQ packet being
applied to a machine that happens to have the same password.

View File

@@ -4,6 +4,8 @@
* *
* Based upon the ipt_SYSRQ idea by Marek Zalem <marek [at] terminus sk> * 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 * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
* version 2 or 3 as published by the Free Software Foundation. * 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 * 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 * greater than the last sequence number; <salt> is some random bytes; and
* <hash> is the hash of everything up to and including the preceding "," * <hash> is the hash of everything up to and including the preceding ","
* together with the password. * together with "<dstaddr>,<password>".
* *
* For example * For example
* *
* salt=$RANDOM * salt=$RANDOM
* req="s,$(date +%s),$salt" * 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 :-) * 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); sg_init_table(sg, 2);
#endif #endif
sg_set_buf(&sg[0], data, n); sg_set_buf(&sg[0], data, n);
strcpy(sysrq_digest_password, sysrq_password);
i = strlen(sysrq_digest_password); i = strlen(sysrq_digest_password);
sg_set_buf(&sg[1], sysrq_digest_password, i); sg_set_buf(&sg[1], sysrq_digest_password, i);
ret = crypto_hash_digest(&desc, sg, n + i, sysrq_digest); 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_FMT ":%u -> :%u len=%u\n",
NIPQUAD(iph->saddr), htons(udph->source), NIPQUAD(iph->saddr), htons(udph->source),
htons(udph->dest), len); 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); 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_FMT ":%hu -> :%hu len=%u\n",
NIP6(iph->saddr), ntohs(udph->source), NIP6(iph->saddr), ntohs(udph->source),
ntohs(udph->dest), len); 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); return sysrq_tg((void *)udph + sizeof(struct udphdr), len);
} }
#endif #endif
@@ -340,7 +345,9 @@ static int __init sysrq_crypto_init(void)
sysrq_hexdigest = kmalloc(2 * sysrq_digest_size + 1, GFP_KERNEL); sysrq_hexdigest = kmalloc(2 * sysrq_digest_size + 1, GFP_KERNEL);
if (sysrq_hexdigest == NULL) if (sysrq_hexdigest == NULL)
goto fail; 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) if (sysrq_digest_password == NULL)
goto fail; goto fail;
do_gettimeofday(&now); do_gettimeofday(&now);