ASA-2019-00485 – Das U-Boot: memcpy sem definição de limite com falha na verificação de tamanho nas funções nfs_read_reply()/store_block()


For the English version of this alert, click here.

Allele Security Alert

ASA-2019-00485

Identificador(es)

ASA-2019-00485, CVE-2019-14198

Título

memcpy sem definição de limite com falha na verificação de tamanho nas funções
nfs_read_reply()/store_block()

Fabricante(s)

DENX Software Engineering

Produto(s)

Das U-Boot

Versão(ões) afetada(s)

Desconhecido

Versão(ões) corrigida(s)

Desconhecido

Prova de conceito

Desconhecido

Descrição

O problema existe no caso NFSv3 na função nfs_read_reply() ao ler um arquivo e armazená-lo em outro meio (flash ou memória física) para processamento posterior. Os dados e a duração são totalmente controlados pelo usuário e nunca são validados.

Detalhes técnicos

static int nfs_read_reply(uchar *pkt, unsigned len)
{        [...]

    if (supported_nfs_versions & NFSV2_FLAG) {
        rlen = ntohl(rpc_pkt.u.reply.data[18]); // <-- rlen is attacker-controlled could be 0xFFFFFFFF
        data_ptr = (uchar *)&(rpc_pkt.u.reply.data[19]);
    } else {  /* NFSV3_FLAG */
        int nfsv3_data_offset =
            nfs3_get_attributes_offset(rpc_pkt.u.reply.data);

        /* count value */
        rlen = ntohl(rpc_pkt.u.reply.data[1 + nfsv3_data_offset]); // <-- rlen is attacker-controlled
        /* Skip unused values :
            EOF:        32 bits value,
            data_size:  32 bits value,
        */
        data_ptr = (uchar *)
            &(rpc_pkt.u.reply.data[4 + nfsv3_data_offset]);
    }

    if (store_block(data_ptr, nfs_offset, rlen)) // <-- We pass to store_block source and length controlled by the attacker
            return -9999;

    [...]
}

Concentrando-se na parte de memória física da função store_block(), ela tenta reservar alguma memória usando a função específica map_physmem(), e chamando phys_to_virt(). É possível observar na implementação x86, ao reservar a memória física, que ela claramente ignora o comprimento e fornece um ponteiro sem verificar se as áreas adjacentes estão reservadas (ou não) para outros propósitos.

static inline void *phys_to_virt(phys_addr_t paddr)
{
        return (void *)(unsigned long)paddr;
}

Em seguida, em store_block(), há um memcpy buffer overrun com comprimento e origem controlados pelo usuário.

static inline int store_block(uchar *src, unsigned offset, unsigned len)
{

[...]

 void *ptr = map_sysmem(load_addr + offset, len); // <-- essentially this is ptr = load_addr + offset
 memcpy(ptr, src, len); // <-- unrestricted overflow happens here
 unmap_sysmem(ptr);

[...]

}

Créditos

Fermín Serna, Pavel Avgustinov e Kevin Backhouse

Referência(s)

U-Boot RCE Vulnerabilities Affecting IoT Devices
https://blog.semmle.com/uboot-remote-code-execution-vulnerability/

U-Boot NFS RCE Vulnerabilities (CVE-2019-14192)
https://blog.semmle.com/uboot-rce-nfs-vulnerability/

[U-Boot] Remote code execution vulnerabilities in U-Boot’s NFS and other IP parsing code
https://lists.denx.de/pipermail/u-boot/2019-July/378001.html

CVE-2019-14198
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-14198

CVE-2019-14198
https://nvd.nist.gov/vuln/detail/CVE-2019-14198

Se encontrou algum erro neste alerta ou deseja uma análise compreensiva, entre em contato.

Última modificação: 11 agosto 2019

Não somos responsáveis por qualquer perda de dados, corrupção de dispositivos ou qualquer outro tipo de problema devido ao uso de qualquer informação mencionada em nossos alertas de segurança.