O que é especial sobre "! xxx% s% s% s% s% s% s% s% s"?

4

Eu estava vinculado ao Manual do Unix-Haters e tropecei em (página 149):

Subject: Relevant Unix bug

October 11, 1991

Fellow W4115x students—

While we’re on the subject of activation records, argument passing, and calling conventions, did you know that typing:

!xxx%s%s%s%s%s%s%s%s

to any C-shell will cause it to crash immediately? Do you know why?

Questions to think about:

  • What does the shell do when you type !xxx?
  • What must it be doing with your input when you type !xxx%s%s%s%s%s%s%s%s?
  • Why does this crash the shell?
  • How could you (rather easily) rewrite the offending part of the shell so as not to have this problem?

Puramente por curiosidade, alguém pode explicar qual foi o problema? Não é novidade que pesquisar no Google pela string não ajuda. Procurar por outras citações da mensagem só me deu outras cópias da mensagem, mas nenhuma explicação.

    
por Alexey Romanov 25.04.2017 / 13:45

1 resposta

6

Eu não sinto vontade de procurar pelas fontes de shells de 25 anos, mas

Pode ser uma vulnerabilidade format-string .

Se o shell contiver código como

printf(str);

em que str é uma string retirada da entrada do usuário, o conteúdo da string será a string de formatação que printf usa. O %s diz ao printf para imprimir uma string apontada por um argumento. Se os argumentos não forem fornecidos (como acima, há apenas a string de formatação), a função lerá alguns outros dados da pilha e os seguirá como ponteiros. Provavelmente acessando memória não mapeada e travando o processo.

De certa forma, acho que o texto da mensagem sugere uma solução como essa também. Se você digitar !xxx , o que a shell faz visivelmente é imprimir uma mensagem de erro como !xxx: event not found . A partir daí, não é um grande salto tentar também imprimir !xxx%s%s%s%s%s%s%s%s: event not found , com a implicação de uma vulnerabilidade de string de formato.

Eu não deveria, mas dei uma olhada na fonte aqui ( 4.3BSD-Tahoe/usr/src/bin/csh , as datas são de 1988).

findev(cp, anyarg) em sh.lex.c parece que pode ser a função para encontrar um evento de histórico correspondente: percorre uma lista vinculada de struct Hist chamada Histlist . Se não encontrar nada, chama seterr2(cp, ": Event not found"); a noev() . cp aqui parece ser a string pesquisada no histórico.

seterr2() define a variável err como concatenação dos argumentos e err é usado como if (err) error(err); em alguns locais em process() , em sh.c . Finalmente, error() (em sh.err.c ) contém uma vulnerabilidade de string de formato clássico: if (s) printf(s, arg), printf(".\n");

Em alguns outros lugares, error() é chamado com um argumento, como error("Unknown user: %s", gpath + 1); , então a ideia é que o primeiro argumento para error() pode ser uma string de formato.

Eu não seria honesto se dissesse que entendi as funções de substituição de histórico na íntegra. É bastante uncommented manipulação de seqüência de caracteres manual em C. % tem um significado especial na substituição de histórico, mas só posso vê-lo sendo tratado especialmente como o primeiro caractere (como em !% ) ou após findev() é chamado.

    
por 25.04.2017 / 14:37