No Linux, você pode sobrescrever o valor das strings do ambiente na pilha.
Assim, você pode ocultar a entrada sobrescrevendo-a com zeros ou qualquer outra coisa:
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char* argv[], char* envp[]) {
char cmd[100];
while (*envp) {
if (strncmp(*envp, "k=", 2) == 0)
memset(*envp, 0, strlen(*envp));
envp++;
}
sprintf(cmd, "cat /proc/%u/environ", getpid());
system(cmd);
return 0;
}
Executar como:
$ env -i a=foo k=v b=bar ./wipe-env | hd
00000000 61 3d 66 6f 6f 00 00 00 00 00 62 3d 62 61 72 00 |a=foo.....b=bar.|
00000010
o k=v
foi substituído por
. setenv("k", "", 1)
"k="
k
Observe que setenv()
para sobrescrever o valor não funcionará como nesse caso, uma nova string putenv()
é alocada.
Se você não modificasse a variável de ambiente k=v
com k=v
/ k=v1
, também deveria ser capaz de fazer algo assim para obter o endereço da string k=v2
na pilha ( bem, de um deles):
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char* argv[]) {
char cmd[100];
char *e = getenv("k");
if (e) {
e -= strlen("k=");
memset(e, 0, strlen(e));
}
sprintf(cmd, "cat /proc/%u/environ", getpid());
system(cmd);
return 0;
}
Observe, entretanto, que remove apenas uma das entradas k=v
recebidas no ambiente. Normalmente, há apenas um, mas nada impede que alguém passe tanto execve()
como bash
(ou /proc/pid/environ
duas vezes) na lista de env passada para /proc/pid/cmdline
. Essa foi a causa de vulnerabilidades de segurança no passado, como CVE-2016-2381 . Ele poderia realmente acontecer com /proc/pid/environment
antes do shellshock ao exportar uma variável e uma função com o mesmo nome.
Em qualquer caso, sempre haverá uma pequena janela durante a qual a string env var ainda não foi sobrescrita, então você pode querer encontrar outra maneira de passar as informações do segredo para o comando ( como um pipe, por exemplo) se expor via /proc/pid/environ
é uma preocupação.
Observe também que ao contrário de %code% , %code% é acessível apenas por processos com o mesmo euid ou raiz (ou raiz apenas se euid e ruid do processo não forem os mesmos).
Você pode ocultar esse valor deles em %code% , mas eles ainda poderão obter qualquer outra cópia que você tenha feito da string na memória, por exemplo, anexando um depurador a ela.
Consulte o link para saber como evitar que usuários não-root façam isso.