Converter senha com caracteres especiais para uso com script de espera

2

Eu tenho um script de espera que se conecta a um site SFTP e envia alguns arquivos. O ID e a senha estão contidos em arquivos de texto locais. O script expect lê esses arquivos como uma variável e depois passa para o servidor SFTP.

O problema que estou enfrentando é que estamos fornecendo senhas com complexidade que incluem caracteres especiais ($ \ ,!) etc. Por exemplo, se a senha for $ word, o $ passa como especial em vez de como literal. Sendo isto está sendo passado através de uma variável (vários sites e IDs)

Eu não consigo usar '$ pw', pois ele literalmente passa $ pw para o servidor e o uso de "$ pw" envia caracteres especiais. Eu preciso passar a senha exatamente como está.

Eu tenho escapado deles manualmente até agora (por exemplo, passar \ $ word), mas isso é entediante e eu gostaria de fazer isso de forma scriptica.

O script se parece com isso (nomes e lugares alterados para proteger os inocentes)

#!/bin/bash

home=/data/ftp/vf/drop/
un='cat /home/vf/workflow/.udf/.u/.u$1'
pw='cat /home/vf/workflow/.udf/.p/.p$1'
sl='cd /home/vf/workflow/scheduler; grep $1 upload*|cut -d \: -f1'

/usr/bin/expect -c "
spawn /usr/bin/sftp -o KexDHMin=1024 $un@$sl.mysteriouslocation.com
set timeout -1
expect *Authentication
expect Password*
send \"$pw\r\"
expect sftp*
send \"mput /$home/$1/transfer/*\r\"
expect sftp*
send \"ls \r\"
expect sftp*
send \"bye\r\"
expect eof
exit

Como posso passar a senha para o script expect para que ela envie os caracteres literais e não lhes dê um significado especial? Eu não acho que eu possa escrever um "conserto" para o arquivo de senha em si, ou seja, entrar e toda vez que ele vir um caractere especial, escapar por meio de sed ou outros meios, pois o próprio caractere de escape é especial e pode acabar um loop.

Sua ajuda é muito apreciada!

    
por Keith 05.12.2017 / 17:18

3 respostas

1

Um pequeno snippet Perl pode ser usado para escapar (barra invertida) todos os caracteres ASCII que não combinam /[A-Za-z_0-9]/ usando quotemeta função. A linha de comando Perl é facilmente incorporada ao seu script de shell:

#/bin/sh
pstr='$x%y!zpass' # plain, un-escaped string
estr=$(perl -e 'print quotemeta shift(@ARGV)' "${pstr}")
echo ${estr}      # show escaped string

produz:

\$x\%y\!zpass
    
por 05.12.2017 / 18:37
5

Passe os valores como variáveis de ambiente. Isso também evitará as vulnerabilidades de injeção de comando e mostrará a senha em ps output!

#! /bin/sh -

home=/data/ftp/vf/drop
un=$(cat /home/vf/workflow/.udf/.u/.u"$1")
pw=$(cat /home/vf/workflow/.udf/.p/.p"$1")
sl=$(cd /home/vf/workflow/scheduler &&
  grep -Fe "$1" upload*|cut -d : -f1)

export home un sl pw

user=$1 /usr/bin/expect -c '
spawn /usr/bin/sftp -o KexDHMin=1024 $env(un)@$env(sl).mysteriouslocation.com
set timeout -1
expect *Authentication
expect Password*
send $env(pw)\r
expect sftp*
send "mput /$env(home)/$env(user)/transfer/*\r"
expect sftp*
send ls\r
expect sftp*
send bye\r
expect eof
exit'

(bem, ainda pode ser uma vulnerabilidade de injeção de comando se a variável contiver texto que tornaria o comando sftp run como !reboot ).

    
por 05.12.2017 / 17:47
2

Você poderia colocar o programa expect em um script separado (vamos chamá-lo de sftp.expect ) e passar o nome de usuário / senha como argumentos para ele.

Isto tem o problema que os argumentos da linha de comando são visíveis para outros usuários no sistema , então esta não é a melhor maneira de lidar com senhas, e você realmente não quero fazer isso com senhas em um sistema compartilhado.

#!/usr/bin/expect -f
set un [lindex $argv 0];
set pw [lindex $argv 1];
set sl [lindex $argv 2];

spawn /usr/bin/sftp -o KexDHMin=1024 $un@$sl.mysteriouslocation.com
set timeout -1
expect *Authentication
expect Password*
send "$pw\r"

Em seguida, execute isso a partir do script de shell com

#!/bin/bash
un=$(cat /home/vf/workflow/.udf/.u/.u"$1")
pw=...
sl=...
expect -f sftp.expect "$un" "$pw" "$sl"

Ou se você quiser manter o script esperado dentro do mesmo script de shell, coloque-o em um documento here:

#!/bin/bash    
un=foo
# ...
expect -f - "$un" <<'EOF'
set un [lindex $argv 0];
send "user is: $un\r\n"
# ...
EOF

(observe as aspas em torno de EOF , não queremos que o shell interprete as variáveis no heredoc.)

    
por 05.12.2017 / 17:40