Percebi há algum tempo que nomes de usuário e senhas dados curl
como argumentos de linha de comando não aparecem na ps
saída (embora, é claro, eles possam aparecer no seu histórico do bash).
Da mesma forma, eles não aparecem /proc/PID/cmdline
.
(Porém, a duração do argumento combinado de nome de usuário / senha.)
Demonstração abaixo:
[root@localhost ~]# nc -l 80 &
[1] 3342
[root@localhost ~]# curl -u iamsam:samiam localhost &
[2] 3343
[root@localhost ~]# GET / HTTP/1.1
Authorization: Basic aWFtc2FtOnNhbWlhbQ==
User-Agent: curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.15.3 zlib/1.2.3 libidn/1.18 libssh2/1.4.2
Host: localhost
Accept: */*
[1]+ Stopped nc -l 80
[root@localhost ~]# jobs
[1]+ Stopped nc -l 80
[2]- Running curl -u iamsam:samiam localhost &
[root@localhost ~]# ps -ef | grep curl
root 3343 3258 0 22:37 pts/1 00:00:00 curl -u localhost
root 3347 3258 0 22:38 pts/1 00:00:00 grep curl
[root@localhost ~]# od -xa /proc/3343/cmdline
0000000 7563 6c72 2d00 0075 2020 2020 2020 2020
c u r l nul - u nul sp sp sp sp sp sp sp sp
0000020 2020 2020 0020 6f6c 6163 686c 736f 0074
sp sp sp sp sp nul l o c a l h o s t nul
0000040
[root@localhost ~]#
Como esse efeito é alcançado? Está em algum lugar no código fonte de curl
? (Presumo que seja um curl
recurso, não um ps
recurso? Ou é um recurso do kernel de algum tipo?)
Além disso: isso pode ser alcançado fora do código-fonte de um executável binário? Por exemplo, usando comandos de shell, provavelmente combinados com permissões de root?
Em outras palavras, eu poderia, de alguma forma, mascarar um argumento que apareça na saída /proc
ou na ps
saída (mesma coisa, acho) que passei para algum comando arbitrário do shell? (Eu acho que a resposta para isso é "não", mas parece valer a pena incluir essa meia pergunta extra.)
environ
diretamente para acessar variáveis de ambiente? - a linha inferior: a lista de argumentos, como a lista de variáveis de ambiente, está na memória de processo de leitura / gravação do usuário e pode ser modificada pelo processo do usuário.grep
padrão em uma classe de caracteres. Por exemplops -ef | grep '[c]url'
curl
corresponde,curl
mas[c]url
não corresponde[c]url
. Se você precisar de mais detalhes, faça uma nova pergunta e ficarei feliz em responder.Respostas:
Quando o kernel executa um processo, copia os argumentos da linha de comando para ler / gravar a memória pertencente ao processo (na pilha, pelo menos no Linux). O processo pode gravar nessa memória como qualquer outra memória. Quando
ps
exibe o argumento, ele lê de volta o que estiver armazenado naquele endereço específico na memória do processo. A maioria dos programas mantém os argumentos originais, mas é possível alterá-los. A descrição POSIX dosps
estados queA razão pela qual isso é mencionado é que a maioria das variantes do unix reflete a mudança, mas as implementações do POSIX em outros tipos de sistemas operacionais podem não.
Esse recurso é de uso limitado porque o processo não pode fazer alterações arbitrárias. No mínimo, o comprimento total dos argumentos não pode ser aumentado, porque o programa não pode alterar o local onde
ps
buscará os argumentos e não pode estender a área além do tamanho original. O comprimento pode efetivamente ser diminuído colocando bytes nulos no final, porque os argumentos são seqüências terminadas em nulo no estilo C (isso é indistinguível de ter um monte de argumentos vazios no final).Se você realmente deseja cavar, pode procurar a fonte de uma implementação de código aberto. No Linux, a fonte de
ps
não é interessante, tudo o que você verá lá é que ele lê os argumentos da linha de comando do sistema de arquivos proc , em . O código que gera o conteúdo desse arquivo está no kernel, em . A parte da memória do processo (acessada com ) vai do endereço para ; esses endereços são registrados no kernel quando o processo é iniciado e não podem ser alterados posteriormente./proc/PID/cmdline
proc_pid_cmdline_read
fs/proc/base.c
access_remote_vm
mm->arg_start
mm->arg_end
Alguns daemons usam essa capacidade para refletir seu status, por exemplo, eles mudam
argv[1]
para uma string comostarting
ouavailable
ouexiting
. Muitas variantes unix têm umasetproctitle
função para fazer isso. Alguns programas usam essa capacidade para ocultar dados confidenciais. Observe que isso é de uso limitado, pois os argumentos da linha de comando são visíveis enquanto o processo é iniciado.A maioria dos idiomas de alto nível copia os argumentos para objetos de sequência e não permite modificar o armazenamento original. Aqui está um programa em C que demonstra essa capacidade alterando
argv
elementos diretamente.Saída de amostra:
Você pode ver a
argv
modificação no código fonte do curl. Curl define uma funçãocleanarg
nasrc/tool_paramhlp.c
qual é usado para alterar um argumento para todos os espaços usandomemset
. Emsrc/tool_getparam.c
esta função é utilizada algumas vezes, por exemplo, por redacting a senha do usuário . Como a função é chamada a partir da análise de parâmetro, isso acontece no início de uma chamada de curvatura, mas o despejo da linha de comando antes que isso aconteça ainda mostrará as senhas.Como os argumentos são armazenados na própria memória do processo, eles não podem ser alterados do lado de fora, exceto usando um depurador.
fonte
ps
argumentos de relatório dessa parte da memória do kernel, ignorando as alterações feitas na memória de leitura e gravação dos processos? Mas (se eu entendi direito?) A maioria das variações do UNIX nem sequer faz o primeiro, então você não pode fazer umaps
implementação com o último sem modificações no kernel, já que os dados originais não são mantidos em lugar algum?argv
entradas seja alterado (você não pode definirargv[i]
, mas pode escreverargv[i][0]
atéargv[i][strlen(argv[i])]
), portanto, deve haver uma cópia na memória do processo.ps
saída, muitos argumentos vazios parecem não ter nada lá, mas sim, faz diferença se você verificar quantos espaços existem e poderá observar mais diretamente/proc/PID/cmdline
.As outras respostas respondem bem à pergunta de maneira geral. Para responder especificamente " Como esse efeito é alcançado? Ele está em algum lugar no código fonte do curl? ":
Na seção de análise de argumento do código-fonte de ondulação , a
-u
opção é tratada da seguinte maneira:E a
cleanarg()
função é definida da seguinte maneira:Portanto, podemos ver explicitamente que o argumento nome de usuário: senha
argv
é substituído por espaços, conforme descrito pelas outras respostas.fonte
cleanarg
declare explicitamente que está fazendo o que a pergunta está fazendo!Um processo pode não apenas ler seus parâmetros, mas também escrevê-los.
Não sou desenvolvedor, portanto não estou familiarizado com essas coisas, mas pode ser possível externamente com uma abordagem semelhante à alteração dos parâmetros do ambiente:
https://stackoverflow.com/questions/205064/is-there-a-way-to-change-another-processs-environment-variables
fonte
bash -c 'awk 1 /proc/$$/cmdline; set -- something; awk 1 /proc/$$/cmdline'
mostra que, pelo menos no shell, definir os parâmetros é diferente de modificar o que o kernel vê como parâmetros do processo.