65 lines
2.3 KiB
Diff
65 lines
2.3 KiB
Diff
From abd8e0d987ab56013d360077202bf2aca20a42dd Mon Sep 17 00:00:00 2001
|
|
From: Richard Weinberger <richard@nod.at>
|
|
Date: Tue, 3 Sep 2024 16:14:58 +0200
|
|
Subject: [PATCH] chap: Use proper entropy source
|
|
|
|
The challenge sent to the initiator is based on a poor
|
|
source of randomness, it uses rand() without seeding it by srand().
|
|
So the glibc PRNG is always seeded with 1 and as a consequence the
|
|
sequence of challenges is always the same.
|
|
|
|
An attacker which is able to monitor network traffic can apply a replay
|
|
attack to bypass the CHAP authentication. All the attacker has to do
|
|
is waiting for the server or the service to restart and replay with a
|
|
previously record CHAP session which fits into the sequence.
|
|
|
|
To overcome the issue, use getrandom() to query the kernel random
|
|
number generator.
|
|
Also always send a challenge of length CHAP_CHALLENGE_MAX, there is no
|
|
benefit in sending a variable length challenge.
|
|
|
|
Signed-off-by: Richard Weinberger <richard@nod.at>
|
|
---
|
|
usr/iscsi/chap.c | 12 +++++-------
|
|
1 file changed, 5 insertions(+), 7 deletions(-)
|
|
|
|
diff --git a/usr/iscsi/chap.c b/usr/iscsi/chap.c
|
|
index aa0fc671..b89ecabd 100644
|
|
--- a/usr/iscsi/chap.c
|
|
+++ b/usr/iscsi/chap.c
|
|
@@ -28,6 +28,7 @@
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
+#include <sys/random.h>
|
|
|
|
#include "iscsid.h"
|
|
#include "tgtd.h"
|
|
@@ -359,22 +360,19 @@ static int chap_initiator_auth_create_challenge(struct iscsi_connection *conn)
|
|
sprintf(text, "%u", (unsigned char)conn->auth.chap.id);
|
|
text_key_add(conn, "CHAP_I", text);
|
|
|
|
- /*
|
|
- * FIXME: does a random challenge length provide any benefits security-
|
|
- * wise, or should we rather always use the max. allowed length of
|
|
- * 1024 for the (unencoded) challenge?
|
|
- */
|
|
- conn->auth.chap.challenge_size = (rand() % (CHAP_CHALLENGE_MAX / 2)) + CHAP_CHALLENGE_MAX / 2;
|
|
+ conn->auth.chap.challenge_size = CHAP_CHALLENGE_MAX;
|
|
|
|
conn->auth.chap.challenge = malloc(conn->auth.chap.challenge_size);
|
|
if (!conn->auth.chap.challenge)
|
|
return CHAP_TARGET_ERROR;
|
|
|
|
+ if (getrandom(conn->auth.chap.challenge, conn->auth.chap.challenge_size, 0) != conn->auth.chap.challenge_size)
|
|
+ return CHAP_TARGET_ERROR;
|
|
+
|
|
p = text;
|
|
strcpy(p, "0x");
|
|
p += 2;
|
|
for (i = 0; i < conn->auth.chap.challenge_size; i++) {
|
|
- conn->auth.chap.challenge[i] = rand();
|
|
sprintf(p, "%.2hhx", conn->auth.chap.challenge[i]);
|
|
p += 2;
|
|
}
|