From abd8e0d987ab56013d360077202bf2aca20a42dd Mon Sep 17 00:00:00 2001 From: Richard Weinberger 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 Upstream-Status: Backport [https://github.com/fujita/tgt/commit/abd8e0d987ab56013d360077202bf2aca20a42dd] CVE: CVE-2024-45751 Signed-off-by: Hitendra Prajapati --- 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 aa0fc67..b89ecab 100644 --- a/usr/iscsi/chap.c +++ b/usr/iscsi/chap.c @@ -28,6 +28,7 @@ #include #include #include +#include #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; } -- 2.25.1