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.