Como posso criar e acessar com segurança arquivos temporários a partir de scripts de shell?

11

Eu li que redirecionar a saída para um arquivo de nome fixo em /tmp pode ser um risco de segurança, porque se um invasor (ou descontente) perceber que um arquivo /tmp/tmpfileformyscript.tmp é criado quando eu executo meu script (mesmo ele não tem acesso de leitura ao meu script), ele pode, por exemplo, fazer um link simbólico ln -s ~wildcard/.bashrc /tmp/tmpfileformyscript.tmp , o que fará com que eu destrua meu arquivo .bashrc quando eu executar meu script.

Então, posso usar algo como filename="tmpfile.tmp.$RANDOM" ; echo outputtext > "$filename" .

No entanto, eu gostaria de usar um arquivo tmp para armazenar em cache, às vezes, nesse caso, eu gostaria de saber se "tmpfile.tmp. *" corresponde a qualquer coisa em /tmp e, se for, use esse arquivo em vez de criar um novo. Infelizmente, test e o equivalente [ -f filename ] não suportam globulação de arquivos, até onde eu sei.

Assim, minha pergunta é dupla:

  1. Como posso criar um arquivo temporário com segurança? A "predictablename.$RANDOM" é uma prática aceitável ou existe uma maneira melhor (mais segura e mais fácil)?
  2. Como posso acessar facilmente o arquivo e / ou estabelecer sua existência mais tarde verificando predictablename ?
por Wildcard 14.10.2015 / 06:31

2 respostas

11

Use o formato mktemp utilitário para criar um arquivo temporário com um nome imprevisível. Não é padronizado pelo POSIX, mas está disponível no * BSD assim como no Linux.

> /tmp/predictable.$RANDOM não é uma boa escolha porque é mais previsível¹, o que abre seu script para um ataque em que o invasor pode enganar seu script para sobrescrever um arquivo ao qual você tem acesso de gravação ou conceder acesso ao arquivo temporário. Esta é uma vulnerabilidade arquivo temporário inseguro . mktemp não possui esta vulnerabilidade porque cria o arquivo com segurança (ele não substituirá um arquivo existente, mesmo se links simbólicos estiverem envolvidos) e usa um nome suficientemente imprevisível para evitar uma negação de serviço.

Se criar um arquivo temporário e trabalhar com ele não for suficiente, crie um diretório temporário com mktemp -d e trabalhe nele.

mktemp também toma o cuidado de usar $TMPDIR se a variável estiver definida, voltando a /tmp se não estiver definida.

Mais e mais distribuições configuram TMPDIR para ser um diretório privado, por exemplo, /run/1234/tmp onde 1234 é seu UID. Isso elimina o risco de vulnerabilidades de arquivos temporários, ao custo de não poder mais compartilhar arquivos temporários entre usuários (o que ocasionalmente é útil, mas não com muita frequência; /tmp ainda está disponível, apenas não TMPDIR ).

Se você precisar de um nome de arquivo reproduzível, crie um arquivo com um nome bem definido (sem componente aleatório) no diretório inicial do usuário. A convenção moderna é a especificação do diretório de usuários XDG . Se o arquivo puder ser removido sem causar perda de dados, use a variável de ambiente XDG_CACHE_HOME , com o padrão ~/.cache . Você provavelmente deve criar um subdiretório com o nome do seu aplicativo e trabalhar nele.

CACHE_DIR="${XDG_CACHE_HOME:-"$HOME/.cache"}"/Wildcard-scripts
[ -d "$CACHE_DIR" ] || mkdir -p -- "$CACHE_DIR"
CACHE_FILE="$CACHE_DIR/tmpfileformyscript"

¹ Não só $RANDOM leva apenas 32767 valores possíveis, mas é fácil de prever sem tentar muitos valores. O gerador de números aleatórios do Bash é um LCG criado pelo PID e pela hora do primeiro uso. O Zsh's é o rand da plataforma com o tempo de inicialização. ATT Ksh's é o rand da plataforma semeado pelo PID. O Mksh's é um LCG com uma semente mais complexa, mas ainda sem qualidade de segurança. Todos eles podem ser previstos por outro processo com uma chance bastante grande de sucesso.

    
por 15.10.2015 / 02:49
8

O mktemp foi projetado para isso. Na página do manual:

TMPFILE='mktemp /tmp/example.XXXXXXXXXX' || exit 1
echo "program output" >> $TMPFILE

O mktemp criará o arquivo ou sairá com um status de saída diferente de zero. O lógico ou (||) garante que o script sairá se o mktemp não puder criar o arquivo. Após este comando, você pode ter certeza de que o arquivo está disponível. Não há necessidade de verificar novamente. A única coisa que você pode precisar adicionar é a limpeza do arquivo no final do seu script.

E possivelmente também quando o script é encerrado por um sinal. Se isso é necessário ou não é algo que você tem que decidir.

Ambos podem ser feitos usando o comando trap .

    
por 14.10.2015 / 06:42