bash에서 사용자 유형의 암호를 프로그램의 표준으로 사용하는 가장 안전하고 간단한 방법은 무엇입니까?


12

나는 bash 쉘 프롬프트에서 사용자가 암호를 입력하고 그 암호가 프로그램에 stdin의 일부가되도록하는 (1) 가장 안전하고 (2) 가장 간단한 방법을 찾고 있습니다.

이것은 stdin이 다음과 같이 보일 것입니다 : {"username":"myname","password":"<my-password>"}, <my-password>쉘 프롬프트에 입력 된 곳 은 어디 입니까? 프로그램 stdin을 제어했다면 암호를 안전하게 입력하라는 메시지를 표시하고 제자리에 넣을 수 있지만 다운 스트림은 표준 범용 명령입니다.

다음을 사용하는 접근법을 고려하고 거부했습니다.

  • 명령 행에 비밀번호를 입력 한 사용자 : 비밀번호가 화면에 표시되고 "ps"를 통해 모든 사용자에게 표시됩니다.
  • 외부 프로그램에 대한 인수로 쉘 변수 보간 (예 :) ...$PASSWORD...: 비밀번호는 여전히 "ps"를 통해 모든 사용자에게 표시됩니다.
  • 환경 변수 (환경에 남아있는 경우) : 모든 하위 프로세스에서 비밀번호를 볼 수 있습니다. 신뢰할 수있는 프로세스조차도 진단의 일부로 코어 또는 덤프 환경 변수를 덤프하면 비밀번호가 노출 될 수 있습니다.
  • 긴밀한 권한을 가진 파일조차도 파일에 장기간 저장된 암호 : 사용자가 실수로 암호를 노출하고 루트 사용자가 실수로 암호를 볼 수 있음

현재 솔루션을 아래 답변으로 제시하지만 누군가가 해결책을 찾으면 더 나은 답변을 선택합니다. 더 간단한 것이 있거나 누군가 내가 놓친 보안 문제를 볼 수 있다고 생각합니다.


(전체 사용 사례는 암호가 HTTPS 서버에 대한 POST 본문의 일부에 필요하지만이 질문을 지나치게 구체적으로 만들고 싶지는 않습니다. stdin은 curl "-d @를 통해 POST 본문이됩니다. - ".)
Jim Hoagland

답변:


14

bashzsh:

unset -v password # make sure it's not exported
set +o allexport  # make sure variables are not automatically exported
IFS= read -rs password < /dev/tty &&
  printf '{"username":"myname","password":"%s"}\n' "$password" | cmd

없이 IFS=, read최고의 당신이 입력 한 암호에서 후행 공백을 제거합니다.

이 없으면 -r백 슬래시를 인용 문자로 처리합니다.

터미널에서만 읽도록하십시오.

echo안정적으로 사용할 수 없습니다. 에서 bash하고 zsh, printf그 명령 라인의 출력에 표시하지 않을 수 있도록 내장입니다 ps.

에서 bash, 당신은 인용 할 필요 $password는 AS 달리 분할 + 글로브의 연산자가 적용됩니다.

해당 문자열을 JSON으로 인코딩해야하기 때문에 여전히 잘못되었습니다. 예를 들어, 큰 따옴표와 백 슬래시는 적어도 문제가 될 것입니다. 해당 문자의 인코딩에 대해 걱정해야 할 수도 있습니다. 프로그램에 UTF-8 문자열이 필요합니까? 터미널은 무엇을 보내나요?

프롬프트 문자열을 추가하려면 다음을 사용하십시오 zsh.

IFS= read -rs 'password?Please enter a password: '

bash:

IFS= read -rsp 'Please enter a password: ' password

printf-이것이 펄 호출을 피하기 위해 필요한 것입니다-좋은 팁. 그것은 당신이를 가지고 좋은 unset password그리고 set +a당신이 현재 쉘에 대한 자세한 가정을 할 수있는 경우는 생략 할 수 있지만,이. -r 옵션에 대한 좋은 점은 IFS=다양한 암호를 사용하여 일반성을 높이기 위해 읽고 사용하는 것입니다. 터미널에서 강제로 입력하려면 / dev / tty에서 이동하는 것이 좋습니다.
Jim Hoagland

1
예, 우리는 여전히 큰 따옴표와 백 슬래시와 몇 가지 다른 문자에 문제가 있습니다. JSON BLOB의 큰 따옴표로 묶은 필드에 넣기 전에 인코딩해야합니다. curl이 UTF-8을 기대하는지 확실하지 않습니다.
Jim Hoagland

1
python3 -c 'import json; print(json.dumps({"username": "myname", "password": input()}))'파이썬이 주위에 있다면. Python 2의 경우 s / input / raw_input /. 해당 명령에 비밀번호를 파이프하면 적절한 JSON이 추출됩니다.
케빈

Kevin, 암호를 stdin에 안전하게 넣고 파이썬을 호출하는 것을 신경 쓰지 않는다면 좋은 제안이 될 것입니다. 이것은 즉시 JSON을 구성합니다. 저장된 암호를 반복적으로 사용할 수는 없지만 파이썬 내부에서 getpass.getpass ()를 사용하면 잘 작동합니다.
Jim Hoagland

2

다음은 내가 가지고있는 솔루션입니다 (테스트되었습니다).

$ read -s PASSWORD
<user types password>
$ echo -n $PASSWORD | perl -e '$_=<>; print "{\"username\":\"myname\",\"password\":\"$_\"}"'

설명:

  1. read -s화면에 줄을 표시하지 않고 stdin 줄 (암호)을 읽습니다. 쉘 변수 PASSWORD에 저장됩니다.
  2. echo -n $PASSWORD줄 바꿈없이 비밀번호를 stdout에 넣습니다. (echo는 쉘 내장 명령이므로 새 프로세스가 작성되지 않으므로 echo에 대한 인수로서의 암호는 (AFAIK) ps에 표시되지 않습니다.)
  3. perl이 호출되고 stdin에서 다음으로 암호를 읽습니다. $_
  4. perl은 암호를 $_전체 텍스트 에 넣고 stdout에 인쇄합니다.

이것이 HTTPS POST가 될 경우 두 번째 줄은 다음과 같습니다.

echo -n $PASSWORD | perl -e '$_=<>; print "{\"username\":\"myname\",\"password\":\"$_\"}"' | curl -H "Content-Type: application/json" -d@- -X POST <url-to-post-to>

3
이것은 꽤 좋아 보인다. 나는 펄을 전혀 호출 할 이유가 없다. printf '{"username":"myname","password":"%s"}' $PASSWORD같은 보안 속성을 유지하고 외부 프로세스를 저장하는 등의 작업을 완벽하게 수행 할 수 있습니다 .
Tom Hunt

2
read-s 플래그를 지원하지 않는 명령에 대한 솔루션을 일반화 하려면 "stty -echo; PASSWORD; stty echo"를 사용하십시오.
Jeff Schaller

2
파이프는 각 측면에 하나씩 두 개의 새로운 프로세스를 시작합니다. 대신 here-string을 사용하십시오 perl -e '...' <<< "$PASSWORD".
chepner

2
@chepner 는 콘텐츠를 더 나쁜 임시 파일 <<<bash저장합니다.
Stéphane Chazelas

1
TLDP에 따르면 파일을 생성하지만 다른 프로세스에서 읽을 수는 없습니다. "여기에서 문서는 임시 파일을 생성하지만이 파일은 연 후에 삭제되며 다른 프로세스에서는 액세스 할 수 없습니다." 예 19-12 직후 tldp.org/LDP/abs/html/here-docs.html
dragon788

0

귀하의 버전이 read지원하지 않으면 이 답변-s 에서 볼 수있는 POSIX 호환 방법을 시도하십시오 .

echo -n "USERNAME: "; read uname
echo -n "PASSWORD: "; set +a; stty -echo; read passwd; command <<<"$passwd"; set -a; stty echo; echo
passwd= # get rid of passwd possibly only necessary if running outside of a script

set +a환경 변수의 자동 "수출"을 방지하기 위해 가정된다. 에 대한 매뉴얼 페이지를 확인해야 stty합니다. 사용할 수있는 옵션이 많이 있습니다. 은 <<<"$passwd"좋은 암호에 공백을 가질 수 있기 때문에 인용된다. 마지막 echo으로 활성화 한 후 stty echo다음 명령 / 출력을 새 줄에서 시작합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.