首页 >> 网络安全 >>漏洞利用 >> CVE-2022-0778 的概念证明,由于 BN_mod_sqrt 中的错误而触发解析 X.509 证书的无限循环
详细内容

CVE-2022-0778 的概念证明,由于 BN_mod_sqrt 中的错误而触发解析 X.509 证书的无限循环

时间:2022-03-17     【转载】   来自:github   阅读

CVE-2022-0778

BN_mod_sqrt()发现的漏洞在解析 X.509 证书时会触发 OpenSSL 功能的无限循环。


发生这种情况是因为p参数应该是素数,但在函数内部没有检查它,最重要的是在解析证书时在调用堆栈中没有任何位置。


如何测试

先决条件是安装gcc了 OpenSSL 的易受攻击版本。


编译gcc -o my_bad_sqrt my_bad_sqrt.c -lcrypto,运行./my_bad_sqrt并观察它永远挂起!:D


击中循环

该函数BN_mod_sqrt()实现了用于查找模平方根的Tonelli-Shanksa算法,即给定一个整数和一个素数p,返回一个值r,使得r^2 == a (mod p)。


分析修补漏洞的提交,我们看到罪魁祸首是找到最小索引的循环,i其中b^(2^i)==1 (mod p), whereb是之前在算法中定义的。

i = 1;
if (!BN_mod_sqr(t, b, p, ctx))
   goto end;
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;
}

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;
}

在第二种情况下,有一个受变量限制的 for 循环e;然而,在原始代码中,只有i==e一个 while 循环内的案例检查。

由于这些循环位于一个更大的循环中,每次迭代都将 的新值设置e为 的当前值i,我们尝试以下攻击策略:


在外循环的第一次执行中,i=1最后执行;为此,我们需要那个b^2=1 (mod p)。

这样,在第二次执行期间,我们将有e=1,如果我们可以进入内部循环,则i==e检查将始终失败

如果我们设法一直拥有t != 1 (mod p),那么我们将永远留在循环中

请注意,前两个步骤实际上可以在“正常”执行中发生,即使用素数p。但是,如果p是复合我们也可以满足第三步!


一些数学

Tonelli-Shanks 算法通过写来工作p - 1 = 2^e * q,奇数q. 这也是整数乘法组模的顺序,以及在执行过程中将多次使用p的值;但是,如果不是素数,则乘法群的阶将不是,这将有助于我们进入无限循环。eqpp-1


特别是,b被初始化为b = a^q (mod p),这意味着如果p是素数,那么b将具有 的一些幂2,然后我们将使用循环找到它。


但是如果我们设置p = r * s,乘法组的顺序是(r-1)*(s-1) = r*s - r - s + 1而不是r*s-1。该算法使用该值精确地q获得一个有序元素;但是,当不是素数时,该值对于阶数没有特殊意义,因此该元素将不具有阶模 2 的幂。y2^epqyp=r*s


由于在第一个外部循环结束时b设置为b = b*y^(e-i) (mod p),因此在第二次迭代中,内部循环将尝试找到 的值i,但由于不再保证其为 2 的幂b^(2^i) == 1 (mod p),因此将失败。y


漏洞利用

漏洞利用中的数字非常简单:我们取r=17,s=41,给出p=r*s=697。这意味着 和 的计算值e将q是p-1 = 2^5 * 87。

然后我们选择a=696,这意味着在初始化时a == -1 (mod p)也是如此。b == -1 (mod p)这将满足e=1以下外部循环的第 1 步设置。

然后b将被设置为一个元素,其顺序不是 的幂,并且内部循环将被卡住,2试图找到 和i。b^(2^i)==1 (mod p)

技术支持: 建站ABC | 管理登录