安全研究

安全漏洞
MIT Kerberos多个内存破坏漏洞

发布日期:2007-12-06
更新日期:2007-12-10

受影响系统:
MIT Kerberos 5
描述:
BUGTRAQ  ID: 26750
CVE(CAN) ID: CVE-2007-5894,CVE-2007-5901,CVE-2007-5902,CVE-2007-5971,CVE-2007-5972

Kerberos是一款广泛使用的使用强壮的加密来验证客户端和服务器端的网络协议。MIT Kerberos 5是一种常用的开源Kerberos实现。

Kerberos的实现上存在多个内存破坏漏洞,远程攻击者可能利用这些漏洞导致服务程序崩溃。

gssftp的ftpd是Kerberos加密的FTP服务器,可通过Kerberos 5认证。在ftpd.c的reply()函数中存在未初始化的指针:

void reply(int n, char *fmt, ...)
        {
...
(1)  int length, kerror; <---- declared length  without initializer

                        if (n) sprintf(in, "%d%c", n, cont_char);
                        else in[0] = '\0';
                        strncat(in, buf, sizeof (in) - strlen(in) - 1);
        #ifdef KRB5_KRB4_COMPAT
                        if (strcmp(auth_type, "KERBEROS_V4") == 0) {
                                if (clevel == PROT_P)
                                        length = krb_mk_priv((unsigned char
*)in,
                                                             (unsigned char
*)out,
                                                             strlen(in),
                                                             schedule,
&kdata.session,
                                                             &ctrl_addr,
                                                             &his_addr);
                                else
                                        length = krb_mk_safe((unsigned char
*)in,
                                                             (unsigned char
*)out,
                                                             strlen(in),
                                                             &kdata.session,
                                                             &ctrl_addr,
                                                             &his_addr);
                                if (length == -1) {
                                        syslog(LOG_ERR,
                                               "krb_mk_%s failed for
KERBEROS_V4",
                                               clevel == PROT_P ? "priv" :
"safe");
                                        fputs(in,stdout);
                                }
                        } else
        #endif /* KRB5_KRB4_COMPAT */
        #ifdef GSSAPI
                        /* reply (based on level) */
                        if (strcmp(auth_type, "GSSAPI") == 0) {
                                gss_buffer_desc in_buf, out_buf;
                                OM_uint32 maj_stat, min_stat;
                                int conf_state;

                                in_buf.value = in;
                                in_buf.length = strlen(in);
                                maj_stat = gss_seal(&min_stat, gcontext,
                                                    clevel == PROT_P, /*
private */
                                                    GSS_C_QOP_DEFAULT,
                                                    &in_buf, &conf_state,
                                                    &out_buf);
                                if (maj_stat != GSS_S_COMPLETE) {
        #if 0
        /* Don't setup an infinite loop */
                                        /* generally need to deal */
                                        secure_gss_error(maj_stat, min_stat,
                                                       (clevel==PROT_P)?
                                                         "gss_seal ENC didn't
complete":
                                                         "gss_seal MIC didn't
complete");
        #endif /* 0 */
                                } else if ((clevel == PROT_P) && !conf_state) {
        #if 0
        /* Don't setup an infinite loop */
                                        secure_error("GSSAPI didn't encrypt
message");
        #endif /* 0 */
                                } else {
                                        memcpy(out, out_buf.value,
                                               length=out_buf.length);
                                        gss_release_buffer(&min_stat,
&out_buf);
                                }
                        }
        #endif /* GSSAPI */
                        /* Other auth types go here ... */
(2)  if (length >= sizeof(in) / 4 * 3) {        <------using uninitialized
length

在(1)处未经初始化便声明了长度,如果为其他认证类型的话就会在(2)使用未初始化的变量。

mit-krb5中捆绑有kdb库。在lib/kdb/kdb_default.c文件的krb5_def_store_mkey函数中存在双重释放漏洞:

......
175         enctype = key->enctype;
176         if ((fwrite((krb5_pointer) &enctype,
177                     2, 1, kf) != 1) ||
178             (fwrite((krb5_pointer) &key->length,
179                     sizeof(key->length), 1, kf) != 1) ||
180             (fwrite((krb5_pointer) key->contents,
181                     sizeof(key->contents[0]), (unsigned) key->length,
182                     kf) != key->length)) {
183             retval = errno;
(1)Pointer "kf" first freed by fclose.
184 (void) fclose(kf);
185         }
(2)Double free of pointer "kf" when fclose it again!
186 if (fclose(kf) == EOF)
187             retval = errno;
188     #if HAVE_UMASK
189         (void) umask(oumask);
190     #endif
191         return retval;
192     }
......

远程攻击者可以利用这个漏洞导致mit krb5中的krb5kdc或其他使用这个函数的第三方应用崩溃。

gssapi库是mit-krb5中所捆绑的加密库。k5sealv3.c文件中的gss_krb5int_make_seal_token_v3函数存在双重释放漏洞:

......
235             if (message2->length)
236                 memcpy(outbuf + 16, message2->value, message2->length);
237    
238             sum.contents = outbuf + 16 + message2->length;
239             sum.length = ctx->cksum_size;
240    
241             err = krb5_c_make_checksum(context, ctx->cksumtype, key,
242                                        key_usage, &plain, &sum);
243             zap(plain.data, plain.length);
244             free(plain.data);
245             plain.data = 0;
246             if (err) {
247                 zap(outbuf,bufsize);
(1)Pointer outbuf freed by function free
248             free(outbuf);
249                 goto error;
250             }
251             if (sum.length != ctx->cksum_size)
252                 abort();
......
287     error:
(2) Double free of pointer outbuf in free(outbuf)
288 free(outbuf);
289         token->value = NULL;
290         token->length = 0;
291         return err;
292     }
293
......

远程攻击者可以利用这个漏洞导致使用mit-krb5中gssapi库的应用或服务崩溃。

此外mit-krb5的gssapi和rpc库中还存在另外一个释放后使用漏洞,具体位于g_initialize.c文件中对gss_indicate_mechs(minorStatus, mechSet)函数的引用:

......
197             for (i = 0; i < (*mechSet)->count; i++) {
198                     curItem = &((*mechSet)->elements[i]);
199                     curItem->elements =
200                             (void *) malloc(g_mechSet.elements[i].length);
201                     if (curItem->elements == NULL) {
202                             (void) k5_mutex_unlock(&g_mechSetLock);
203                             /*
204                              * must still free the allocated elements for
205                              * each allocated gss_OID_desc
206                              */
207                             for (j = 0; j < i; j++) {
208                                     free((*mechSet)->elements[j].elements);
209                             }
210                             free((*mechSet)->elements);
(1)Pointer "mechSet" freed by "free"
211                             free(mechSet);
(2)Dereferencing freed pointer "mechSet"
212                             *mechSet = NULL;
213                             return (GSS_S_FAILURE);
214                     }
215                     g_OID_copy(curItem, &g_mechSet.elements[i]);
216             }
217             (void) k5_mutex_unlock(&g_mechSetLock);
218             return (GSS_S_COMPLETE);
219     } /* gss_indicate_mechs */
......

svc_auth_gss.c文件中的svcauth_gss_get_principal函数中存在整数溢出漏洞:

666  svcauth_gss_get_principal(SVCAUTH *auth)
667     {
668             struct svc_rpc_gss_data *gd;
669             char *pname;
670    
671             gd = SVCAUTH_PRIVATE(auth);
672    
673             if (gd->cname.length == 0)
674                     return (NULL);
675

如果将cnname.length设置为0xffffffff,就会在679行触发整数溢出:
    
676 if ((pname = malloc(gd->cname.length + 1)) == NULL)
677                     return (NULL);
678    
679             memcpy(pname, gd->cname.value, gd->cname.length);
680             pname[gd->cname.length] = '\0';
681    
682             return (pname);
683     }      

远程攻击者可以利用这个漏洞导致使用mit-krb5中的gssapi或rpc库的应用或服务崩溃。

根据MIT所述,这些漏洞大部分都是不可利用的,且可利用的漏洞仅在极端的条件下才存在理论上的利用可能性。

<*来源:Venustech AD-LAB
  
  链接:http://marc.info/?l=full-disclosure&m=119704386404261&w=2
        http://bugs.gentoo.org/show_bug.cgi?format=multiple&id=199205
        http://bugs.gentoo.org/show_bug.cgi?format=multiple&id=199211
        http://bugs.gentoo.org/show_bug.cgi?format=multiple&id=199212
        http://bugs.gentoo.org/show_bug.cgi?format=multiple&id=199214
        http://marc.info/?l=full-disclosure&m=119743235325151&w=2
        http://security.gentoo.org/glsa/glsa-200803-31.xml
*>

测试方法:

警 告

以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!

http://bugs.gentoo.org/show_bug.cgi?format=multiple&id=199214

建议:
厂商补丁:

Gentoo
------
Gentoo已经为此发布了一个安全公告(GLSA-200803-31)以及相应补丁:
GLSA-200803-31:MIT Kerberos 5: Multiple vulnerabilities
链接:http://security.gentoo.org/glsa/glsa-200803-31.xml

所有MIT Kerberos 5用户都应升级到最新版本:

    # emerge --sync
    # emerge --ask --oneshot --verbose ">=app-crypt/mit-krb5-1.6.3-r1"

浏览次数:3619
严重程度:0(网友投票)
本安全漏洞由绿盟科技翻译整理,版权所有,未经许可,不得转载
绿盟科技给您安全的保障