Expect 스크립트와 함께 사용하기 위해 특수 문자로 비밀번호를 변환하십시오.

Expect 스크립트와 함께 사용하기 위해 특수 문자로 비밀번호를 변환하십시오.

SFTP 사이트에 연결하고 일부 파일을 업로드하는 예상 스크립트가 있습니다. ID와 비밀번호는 로컬 텍스트 파일에 포함되어 있습니다. Expect 스크립트는 이러한 파일을 변수로 읽고 SFTP 서버에 전달합니다.

제가 겪고 있는 문제는 우리가 제공하는 비밀번호가 복잡하고 특수 문자($\, !) 등이 포함되어 있다는 것입니다. 예를 들어, 비밀번호가 pass$word인 경우 $는 리터럴이 아닌 특수 문자로 전달됩니다. 이는 변수(여러 사이트 및 ID)를 통해 전달됩니다.

"$pw"는 $pw를 서버에 직접 전달하기 때문에 사용할 수 없지만 "$pw"를 사용하면 특수 문자를 보냅니다. 비밀번호를 그대로 전달하려면 필요합니다.

지금까지는 수동으로(예: pass\$word) 이스케이프 처리했지만 이는 지루한 일이므로 스크립트 방식으로 처리하고 싶습니다.

스크립트는 다음과 같습니다. (무고한 이들을 보호하기 위해 이름과 위치가 변경되었습니다.)

#!/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

특별한 의미를 부여하지 않고 리터럴 문자를 보내도록 Expect 스크립트에 비밀번호를 어떻게 전달할 수 있습니까? 비밀번호 파일 자체에 대한 "수정" 스크립트를 작성할 수 없다고 생각합니다. 즉, 특수 문자를 볼 때마다 sed 또는 다른 수단을 통해 이스케이프 문자를 이스케이프 처리한다는 의미입니다. 이스케이프 문자 자체는 특별하고 A로 끝날 수 있기 때문입니다. 주기.

도와주셔서 감사합니다!

답변1

값을 환경 변수로 전달합니다. 이는 또한 명령 주입 취약점을 방지하고 ps출력에 비밀번호를 표시합니다!

#! /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'

( sftp변수에 실행 명령을 다음과 같이 보이게 만드는 텍스트가 포함되어 있으면 여전히 명령 주입 취약점일 수 있습니다 !reboot.)

답변2

/[A-Za-z_0-9]/다음을 사용하여 일치하지 않는 모든 ASCII 문자를 이스케이프(백슬래시)하는 데 작은 Perl 조각을 사용할 수 있습니다.참조 요소기능. Perl 명령줄은 쉘 스크립트에 쉽게 통합될 수 있습니다.

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

생산하다:

\$x\%y\!zpass

답변3

Expect 프로그램을 별도의 스크립트(라고 부르겠습니다 sftp.expect)에 넣고 사용자 이름/비밀번호를 매개변수로 전달할 수 있습니다.

이는 시스템의 다른 사용자에게 명령줄 매개변수가 표시되는 문제가 있습니다., 따라서 이는 비밀번호를 처리하는 가장 좋은 방법은 아니며진짜공유 시스템의 비밀번호에 대해 이 작업을 수행하고 싶지 않습니다.

#!/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"

그런 다음 쉘 스크립트에서 실행하십시오.

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

또는 동일한 셸 스크립트에 Expect 스크립트를 유지하려면 여기에 문서에 붙여넣으세요.

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

(주위 따옴표에 주의하십시오 EOF. 쉘이 이 문서의 변수를 해석하는 것을 원하지 않습니다.)

관련 정보