[하루한줄] CVE-2022-0778: OpenSSL 무한 루프 유도를 통한 서비스 거부 공격 취약점

URL

https://github.com/drago-96/CVE-2022-0778

Target

  • OpenSSL 1.0.2
  • OpenSSL 1.1.1
  • OpenSSL 3.0

Explain

OpenSSL에서 공격자가 조작된 인증서를 통해 무한 루프를 발생시켜 서비스 거부를 유도할 수 있는 취약점이 발견되었습니다.

이 취약점은 인증서 파싱시 사용되는 BN_mod_sqrt 함수로 인해 발생하였습니다.

설명에 앞서 a, p에 대하여 $r^2 = a \pmod p$ 를 만족하는 r 을 modular 제곱근이라고 합니다.

BN_mod_sqrt 함수는 Tonelli–Shanks algorithm을 이용해 modular 제곱근을 찾는 함수입니다.

문제가 되는 부분은 $b^{2^i} = 1 \pmod p$ 를 만족하는 i를 찾는 과정에서 발생합니다.

// crypto/bn/bn_sqrt.c L310-L318
while (!BN_is_one(t)) {
  i++;
  if (i == e) {
      ERR_raise(ERR_LIB_BN, BN_R_NOT_A_SQUARE);
      goto end;
  }
  if (!BN_mod_mul(t, t, t, p, ctx))
      goto end;
}

알고리즘에 따르면 고정된 e와 증가하는 i에 대해 해당 loop는 i == e인 시점에 끝나야 합니다.

하지만 특수한 입력값을 주어 i=1, e=1 인 상태로 해당 loop에 진입하도록 유도한다면 무한 loop가 발생하여 서비스 거부가 발생하게 됩니다.

해당 취약점은 i == e 를 종료 조건으로 가지는 for문으로 바꾸는 방법으로 패치되었습니다.

/* Find the smallest i, 0 < i < e, such that b^(2^i) = 1. */
for (i = 1; i < e; i++) {
    if (i == 1) {
        if (!BN_mod_sqr(t, b, p, ctx))
            goto end;

    } else {
        if (!BN_mod_mul(t, t, t, p, ctx))
            goto end;
    }
    if (BN_is_one(t))
        break;
}
/* If not found, a is not a square or p is not prime. */
if (i >= e) {
    ERR_raise(ERR_LIB_BN, BN_R_NOT_A_SQUARE);
    goto end;
}

Reference