Usando cURL com um nome de usuário e senha?

468

Quero acessar um URL que exija um nome de usuário / senha. Eu gostaria de tentar acessá-lo com curl. No momento, estou fazendo algo como:

curl http://api.somesite.com/test/blah?something=123

Eu recebo um erro. Eu acho que preciso especificar um nome de usuário e senha junto com o comando acima.

Como eu posso fazer isso?

user246114
fonte

Respostas:

695

Use o -usinalizador para incluir um nome de usuário e o curl solicitará uma senha:

curl -u username http://example.com

Você também pode incluir a senha no comando, mas sua senha ficará visível no histórico do bash:

curl -u username:password http://example.com
Finbarr
fonte
109
Observe que se você fizer isso no console, a senha permanecerá no histórico que está ... errada. Você deve especificar apenas -u usuário e o CURL solicitará a senha no modo sem eco.
Cristian Vrabie
25
@CristianVrabie Tecnicamente correto, mas incorreto se você o estiver executando a partir de um script automatizado que não permite avisos. Seria curioso sobre uma solução para esse problema.
Ligemer 12/03
26
@OmarOthman, se você estiver executando curl a partir de um script, as credenciais (obviamente) não serão incluídas no seu histórico, mas serão visíveis no ps (1). correção:print -- '-u username:password' > somewhere && curl -K somewhere http://...
apenas alguém
7
@ Jay As variáveis ​​de ambiente serão avaliadas antes da execução do comando. A senha ainda estará visível na saída ps.
Robert Važan
8
Não para enfatizar o ponto, mas acredito que minha resposta ( stackoverflow.com/a/27894407/758174 ou seja, usando --netrc-file) é mais segura. Ele mantém a senha fora do histórico, ps, seu script etc. Essa é a única forma que eu uso em todos os meus scripts e para todos os usos autenticados de curl.
Pierre D
255

É mais seguro fazer:

curl --netrc-file my-password-file http://example.com

... passar uma linha simples de usuário / senha na linha de comando é uma má idéia.

O formato do arquivo de senha é (conforme man curl):

machine <example.com> login <username> password <password>

Nota:

  1. O nome da máquina não deve incluir https://ou semelhante! Apenas o nome do host.
  2. As palavras ' machine', ' login' e ' password' são apenas palavras-chave; as informações reais são o material após essas palavras-chave.
Pierre D
fonte
10
Sim, isso mantém a senha fora da lista de processos e do histórico de comandos. Far maneira preferível fazer isso, e só um pouco mais de trabalho :)
AC Capehart
8
Definitivamente, essa deve ser a resposta aceita; senhas na linha de comando são uma prática horrível. (E isso é um fato amplamente conhecido.)
ELLIOTTCABLE
6
Você também pode usar o sinalizador -K <file>ou --config <file>para receber sinalizadores de ondulação via arquivo ou entrada padrão. (Atenção: não deve ser confundido com -kou --insecure!)
Rufflewind
2
Esse método curl mantém as credenciais fora do histórico e do status do processo, mas deixa o nome de usuário e a senha em texto não criptografado no arquivo my-password, criando outro vetor de ataque - pior do que ter informações no arquivo do histórico: o bash, por exemplo, restringe automaticamente as permissões do arquivo de histórico. Um problema semelhante surge se o uso de variáveis ​​de ambiente com, por exemplo, um script para definir o nome de usuário / senha. Se o script não for seguro, as credenciais também não serão.
Steven the Facilly Divertido
5
@SteventheEasilyAmused eu discordo, é muito melhor usar um cleartext .netrcarquivo com permissões adequadamente rigorosas, portanto, apenas o seu usuário possa lê-lo, do que outros mecanismos (por exemplo, argumentos de linha de comando) que permitem que outros usuários leiam as informações.
Ken Williams
77

Ou a mesma coisa, mas com sintaxe diferente

curl http://username:[email protected]/test/blah?something=123
Daniel Magnusson
fonte
1
Eu uso essa sintaxe, porque pode ser usada em muitas outras situações. Como em um cmd do Windows sem cURL e sem wGet, usando start "" "http://username:[email protected]/test/blah?something=123". Pode ser lançado de qualquer lugar. Isso também se aplica a logons de ftp; D
m3nda
9
Você precisa codificar URL o nome de usuário e senha para usar personagens engraçados
diachedelic
2
Eu sei que a maioria das pessoas sabe que não deve enviar senhas (ou mesmo nomes de usuário) no URL como este exemplo, pois é fácil farejar. Com isso dito; Não recomendo, mas uso apenas quando você sabe o que está fazendo.
LosManos 3/17/17
1
Isso é suuuuuper arcaico e não deve ser usado. Isto é dos dias do FTP: o
Qix - MONICA FOI ERRADA EM 21/03
2
Infelizmente, isso deixa a senha visível na lista de processos.
Mark Ribau
63

Você também pode enviar o nome de usuário escrevendo:

curl -u USERNAME http://server.example

O Curl solicitará a senha e a senha não estará visível na tela (ou se você precisar copiar / colar o comando).

Kristian
fonte
28

Para passar com segurança a senha em um script (ou seja, impedir que ela apareça no ps auxf ou nos logs), você pode fazê-lo com o sinalizador -K- (leia a configuração do stdin) e um heredoc:

curl --url url -K- <<< "--user user:password"
Matt Fleming
fonte
2
Obrigado pela referência à --configopção (-K) ... possivelmente uma solução melhor seria colocar "--user user: password" em um arquivo e simplesmente -K the filepara que você tenha apenas uma cópia da senha e uma cópia em cada script . Muito mais fácil proteger um único arquivo.
Chris Cogdon
1
Opção semelhante, onde apenas a senha está no arquivo: cat "${password_filepath}" | sed -e "s/^/-u ${username}:/" | curl --url "${url}" -K-. Eu tive que colocar -K-antes do URL para o antigo macOS bash, YMMV.
Mark Ribau
12

Geralmente, o comando CURL se refere como

curl https://example.com\?param\=ParamValue -u USERNAME:PASSWORD

se você não tiver nenhuma senha ou desejar pular o prompt de comando para exigir senha, deixe a seção de senha em branco.

ie curl https://example.com\?param\=ParamValue -u USERNAME:

Touseef Murtaza
fonte
1
NOTA: A senha seria visível no histórico do shell e na lista de processos.
Mark Ribau
10
curl -X GET -u username:password  {{ http://www.example.com/filename.txt }} -O
user128364
fonte
1
NOTA: A senha seria visível no histórico do shell e na lista de processos.
Mark Ribau
8

Para deixar a senha pelo menos não aparecer na sua .bash_history:

curl -u user:$(cat .password-file) http://example-domain.tld
sjas
fonte
6
Nesse caso, a senha ainda aparecerá na lista de processos, por exemplo, é visível para alguém que está fazendo ps auxw |grep curlna hora certa. Da mesma forma, a senha será registrada se for executada viasudo
Adam Katz
1
Com esse método, a senha está presente em um arquivo (.password-file) que pode ser mais inseguro que o histórico do .bash. A parte boa disso é que é apenas a senha - o URL e o nome de usuário não são divulgados no arquivo .password.
Steven o facilmente divertido
7

bem fácil, faça o seguinte:

curl -X GET/POST/PUT <URL> -u username:password
Preyas
fonte
Não há nenhuma exigência de segurança sobre a questão
Victor Polo De Gyves Montero
1
NOTA: Password seria visível na lista de história e processo shell
Mark Ribau
6

Outras respostas sugeriram ao netrc para especificar nome de usuário e senha, com base no que li, concordo. Aqui estão alguns detalhes de sintaxe:

https://ec.haxx.se/usingcurl-netrc.html

Como outras respostas, gostaria de enfatizar a necessidade de prestar atenção à segurança em relação a essa pergunta.

Embora eu não seja um especialista, achei esses links interessantes:

https://ec.haxx.se/cmdline-passwords.html

Para resumir:

O uso das versões criptografadas dos protocolos (HTTPS vs HTTP) (FTPS vs FTP) pode ajudar a evitar vazamento de rede.

O uso do netrc pode ajudar a evitar vazamento da linha de comando.

Para dar um passo adiante, parece que você também pode criptografar os arquivos netrc usando gpg

https://brandur.org/fragments/gpg-curl

Com isso, suas credenciais não estão "em repouso" (armazenadas) como texto sem formatação.

Brian Davis
fonte
5

De maneira clara e simples, a maneira mais segura seria usar variáveis ​​de ambiente para armazenar / recuperar suas credenciais. Assim, um comando curl como:

curl -Lk -XGET -u "${API_USER}:${API_HASH}" -b cookies.txt -c cookies.txt -- "http://api.somesite.com/test/blah?something=123"

Chamaria sua API repousante e passaria o WWW_Authenticationcabeçalho http com os valores codificados em Base64 de API_USERe API_HASH. O -Lkjust diz ao curl para seguir os redirecionamentos http 30x e usar o tratamento inseguro de tls (ou seja, ignorar erros de ssl). Enquanto o double --é apenas bash sugar sugar para parar o processamento de sinalizadores de linha de comando. Além disso, os sinalizadores -b cookies.txte -c cookies.txtlidam com cookies com o -benvio de cookies e-c armazenando cookies localmente.

O manual tem mais exemplos de métodos de autenticação .

Dwight Spencer
fonte
1
Lembre-se de que o uso de "-Lk" pode abrir você para ataques MITM (man-in-the-middle), portanto, tenha cuidado com essa opção.
precisa saber é o seguinte
4
Isso não funciona ... como o bash expande essas variáveis ​​para você, a expansão aparece na lista de processos.
Chris Cogdon
4

A maneira mais segura de passar credenciais para ondular deve ser solicitada para inseri-las. É o que acontece ao passar o nome de usuário, conforme sugerido anteriormente (-u USERNAME ).

Mas e se você não puder passar o nome de usuário dessa maneira? Por exemplo, o nome de usuário pode precisar fazer parte do URL e apenas a senha fazer parte de uma carga útil do json.

tl; dr: Isto é como usar o curl com segurança neste caso:

read -p "Username: " U; read -sp "Password: " P; curl --request POST -d "{\"password\":\"${P}\"}" https://example.com/login/${U}; unset P U

read solicitará o nome de usuário e a senha na linha de comando e armazenará os valores enviados em duas variáveis ​​que podem ser referências em comandos subseqüentes e finalmente desabilitadas.

Vou explicar por que as outras soluções não são ideais.

Por que as variáveis ​​de ambiente são inseguras

  1. O modo de acesso e exposição do conteúdo de uma variável de ambiente não pode ser rastreado (ps -eww), pois o ambiente está implicitamente disponível para um processo
  2. Geralmente, os aplicativos capturam todo o ambiente e registram-no para fins de depuração ou monitoramento (às vezes em arquivos de log em texto sem formatação no disco, especialmente depois que um aplicativo falha)
  3. Variáveis ​​de ambiente são passadas para processos filhos (quebrando, portanto, o princípio do menor privilégio)
  4. Mantê-los é um problema: os novos engenheiros não sabem que estão lá e não estão cientes dos requisitos ao seu redor - por exemplo, para não repassá-los aos subprocessos - já que eles não são impostos ou documentados.

Por que não é seguro digitá-lo diretamente em um comando na linha de comando? Porque seu segredo acaba sendo visível por qualquer outro usuário em execução, ps -auxuma vez que lista os comandos enviados para cada processo em execução no momento. Também porque o seu segredo acaba no histórico do bash (quando o shell termina).

Por que não é seguro incluí-lo em um arquivo local? A restrição estrita de acesso POSIX no arquivo pode reduzir o risco nesse cenário. No entanto, ainda é um arquivo no seu sistema de arquivos, não criptografado em repouso.

iammyr
fonte
2
Parece que esse método ainda mostraria a senha na lista de processos?
Mark Ribau
4

Eu tinha a mesma necessidade no bash (Ubuntu 16.04 LTS) e os comandos fornecidos nas respostas não funcionaram no meu caso. Eu tive que usar:

curl -X POST -F 'username="$USER"' -F 'password="$PASS"' "http://api.somesite.com/test/blah?something=123"

As aspas duplas nos -Fargumentos serão necessárias apenas se você estiver usando variáveis, portanto, a partir da linha de comando ... -F 'username=myuser' ..., tudo bem.

Aviso de segurança relevante: como o Sr. Mark Ribau aponta nos comentários, este comando mostra a senha (variável $ PASS, expandida) na lista de processos!

Marco
fonte
1
Parece que isso ainda mostra o valor de $ PASS na lista de processos?
Mark Ribau
Sim, infelizmente sim.
Marco Marco
1

Se você estiver em um sistema com o aplicativo de chaveiro Gnome, uma solução que evite expor a senha diretamente é usar gkeyring.py para extrair a senha do chaveiro:

server=server.example.com
file=path/to/my/file
user=my_user_name
pass=$(gkeyring.py -k login -tnetwork -p user=$user,server=$server -1)

curl -u $user:$pass ftps://$server/$file -O
Eliot Blennerhassett
fonte
1
NOTA: A senha estaria visível na lista de processos. (E a história se isso não é parte de um script.)
Mark Ribau
1

Isso é MUITO mais do que o OP pediu, mas como esse é o melhor resultado para a passagem segura de senhas curl, estou adicionando essas soluções aqui para outras pessoas que chegam aqui procurando por isso.


NOTA: -sarg para o readcomando não é POSIX e, portanto, não está disponível em todos os lugares, portanto não será usado abaixo. Vamos usar stty -echoe, em stty echovez disso.

NOTA: Todas as variáveis ​​bash abaixo podem ser declaradas como locais se estiverem em uma função, em vez de serem desmarcadas.

NOTA: perlé muito geralmente disponíveis em todos os sistemas que eu tentei, devido a ser uma dependência para muitas coisas, enquanto rubye pythonnão são, portanto, usando perlaqui. Se você pode garantir ruby/ pythononde está fazendo isso, pode substituir o perlcomando pelo equivalente.

NOTA: Testado em bash3.2.57 no macOS 10.14.4. Alguma pequena tradução pode ser necessária para outros shells / instalações.


Solicite com segurança ao usuário uma senha (reutilizável) a ser transmitida. Particularmente útil se você precisar chamar o enrolamento várias vezes.

Para cascas modernas, onde echoestá um embutido (verifique via which echo):

url='https://example.com'
printf "Username: "
read username
printf "Password: "
stty -echo  # disables echoing user input, POSIX equivalent for 'read -s'
read pass
printf "\n" # we need to move the line ahead
stty echo   # re-enable echoing user input
echo ${pass} | sed -e "s/^/-u ${username}:/" | curl --url "${url}" -K-
unset username
unset pass

Para shells mais antigos, onde echoé algo parecido /bin/echo(onde tudo o que ecoa pode ser visto na lista de processos):
ESTA VERSÃO NÃO PODE REUTILIZAR A SENHA , veja em baixo.

url='https://example.com'
printf "Username: "
read username
printf "Password: "
stty -echo  # disables echoing user input, POSIX equivalent for 'read -s'
perl -e '
    my $val=<STDIN>;
    chomp $val;
    print STDERR "\n";  # we need to move the line ahead, but not send a newline down the pipe
    print $val;
' | sed -e "s/^/-u ${username}:/" | curl --url "${url}" -K-
stty echo   # re-enable echoing user input
unset username



Se você precisar armazenar temporariamente a senha em um arquivo, reutilizá-la para vários comandos antes de limpá-la (por exemplo, você está usando funções para reutilização de código e não deseja repetir o código e não pode passe o valor através de eco). (Sim, eles parecem um pouco engenhosos neste formulário, não sendo funções em bibliotecas diferentes; tentei reduzi-los ao código mínimo necessário para mostrá-lo.)

Quando o eco é embutido (isso é especialmente artificial, pois o eco é um embutido, mas é fornecido com integridade):

url='https://example.com'
filepath="$(mktemp)"  # random path, only readable by current user
printf "Username: "
read username
printf "Password: "
stty -echo  # disables echoing user input, POSIX equivalent for 'read -s'
read pass
echo "${pass}" > "${filepath}"
unset pass
printf "\n" # we need to move the line ahead
stty echo   # re-enable echoing user input

cat "${filepath}" | sed -e "s/^/-u ${username}:/" | curl --url "${url}" -K-

rm "${filepath}"  # don't forget to delete the file when done!!
unset username

Quando eco é algo como /bin/echo:

url='https://example.com'
filepath="$(mktemp)"  # random path, only readable by current user
printf "Username: "
read username
printf "Password: "
stty -echo  # disables echoing user input, POSIX equivalent for 'read -s'
$(perl -e '
    my $val=<STDIN>;
    chomp $val;
    open(my $fh, ">", $ARGV[0]) or die "Could not open file \"$ARGV[0]\" $\!";
    print $fh $val;
    close $fh;
' "$filepath")
printf "\n" # we need to move the line ahead
stty echo   # re-enable echoing user input

cat "${filepath}" | sed -e "s/^/-u ${username}:/" | curl --url "${url}" -K-

rm "${filepath}"  # don't forget to delete the file when done!!
unset username
Mark Ribau
fonte