
eu estava ligado aO Manual dos Odiadores do Unixe tropeçou (página 149):
Assunto: Bug Unix relevante
11 de outubro de 1991
Colegas alunos W4115x—
Já que estamos falando sobre registros de ativação, passagem de argumentos e convenções de chamada, você sabia que digitar:
!xxx%s%s%s%s%s%s%s%s
para qualquer C-shell fará com que ele trave imediatamente? Você sabe por quê?
Perguntas para pensar:
- O que o shell faz quando você digita
!xxx
?- O que deve estar fazendo com sua entrada quando você digita
!xxx%s%s%s%s%s%s%s%s
?- Por que isso trava o shell?
- Como você poderia (com bastante facilidade) reescrever a parte ofensiva do shell para não ter esse problema?
Puramente por curiosidade, alguém pode explicar qual foi o problema? Não é novidade que pesquisar a string no Google não ajuda. A pesquisa por outras citações da mensagem só me deu outras cópias da mensagem, mas nenhuma explicação.
Responder1
Não estou com vontade de procurar fontes de conchas de 25 anos, mas
Poderia ser umvulnerabilidade de string de formato.
Se o shell contiver código como
printf(str);
onde str
está alguma string retirada da entrada do usuário, o conteúdo da string será a string de formato printf
usada. O %s
's diz printf
para imprimir uma string apontada por um argumento. Se os argumentos não forem fornecidos (como acima, há apenas a string de formato), 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, penso que o texto da mensagem também sugere uma solução como esta. Se você digitar !xxx
, o que o shell faz visivelmente é imprimir uma mensagem de erro como !xxx: event not found
. A partir daí, não é um grande salto tentar também print !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 fonteaqui( 4.3BSD-Tahoe/usr/src/bin/csh
, as datas são de 1988).
findev(cp, anyarg)
emsh.lex.c
parece que pode ser a função para encontrar um evento de histórico correspondente: ele percorre uma lista vinculada de struct Hist
chamados Histlist
. Se não encontrar nada, ele seterr2(cp, ": Event not found");
chama noev()
. cp
aqui parece ser a string que está sendo pesquisada no histórico.
seterr2()
define a variável err
como concatenação dos argumentos e err
é usada if (err) error(err);
em alguns lugares em process()
, emsh.c
. Finalmente, error()
(emsh.err.c
) contém uma vulnerabilidade clássica de string de formato: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 claramente a ideia é que o primeiro argumento to error()
possa ser uma string de formato.
Eu não seria honesto se dissesse que entendi completamente as funções de substituição de histórico. É praticamente um tratamento manual de strings não comentado em C. %
tem um significado especial na substituição de histórico, mas só posso vê-lo sendo tratado especialmente quando o primeiro caractere (como em !%
) ou depois findev()
é chamado.