bash에서 사용자가 입력한 비밀번호를 프로그램의 표준 입력의 일부로 만드는 가장 안전하고 쉬운 방법은 무엇입니까?

bash에서 사용자가 입력한 비밀번호를 프로그램의 표준 입력의 일부로 만드는 가장 안전하고 쉬운 방법은 무엇입니까?

나는 (1) 사용자가 bash 쉘 프롬프트에 비밀번호를 입력하고 해당 비밀번호가 프로그램의 표준 입력의 일부가 되도록 하는 가장 안전하고 (2) 가장 쉬운 방법을 찾고 있습니다.

이것이 stdin의 모습입니다: {"username":"myname","password":"<my-password>"}, <my-password>쉘 프롬프트에 입력된 내용은 어디에 있습니까? 프로그램의 표준 입력을 제어할 수 있다면 비밀번호를 안전하게 입력하고 제자리에 두도록 수정할 수 있지만 다운스트림은 표준 범용 명령입니다.

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

  • 사용자는 명령줄에 비밀번호를 입력합니다. 비밀번호는 화면에 표시되며 "ps"를 통해 모든 사용자에게 표시됩니다.
  • 쉘 변수는 외부 프로그램의 매개변수(예 ...$PASSWORD...: )에 삽입됩니다. 비밀번호는 여전히 "ps"를 통해 모든 사용자에게 표시됩니다.
  • 환경 변수(환경에 남아 있는 경우): 암호는 모든 하위 프로세스에 표시됩니다. 신뢰할 수 있는 프로세스라도 진단 중에 핵심을 덤프하거나 환경 변수를 덤프하면 암호가 노출될 수 있습니다.
  • 비밀번호는 엄격한 권한이 있는 파일에도 오랫동안 파일에 저장됩니다. 사용자는 실수로 비밀번호를 노출할 수 있으며 루트는 실수로 비밀번호를 볼 수 있습니다.

현재 솔루션을 아래 답변으로 남겨두겠습니다. 하지만 누군가가 더 나은 답변을 제안하면 기꺼이 더 나은 답변을 선택하겠습니다. 더 간단한 것이 있어야 한다고 생각합니다. 아니면 누군가 제가 놓친 보안 문제를 발견했을 수도 있습니다.

답변1

또는 :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. 그렇지 않으면분할+전역연산자가 적용됩니다.

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

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

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

그리고 bash:

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

답변2

내 솔루션은 다음과 같습니다(테스트됨).

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

설명하다:

  1. read -s화면에 줄을 표시하지 않고 표준 입력(암호) 줄을 읽습니다. 이는 쉘 변수 PASSWORD에 저장됩니다.
  2. echo -n $PASSWORD개행 없이 표준 출력에 비밀번호를 입력하십시오. (echo는 쉘에 내장되어 있으므로 새 프로세스가 생성되지 않으므로 (AFAIK) echo 인수인 비밀번호가 ps에 표시되지 않습니다.)
  3. Perl이 호출되어 stdin에서 비밀번호를 읽습니다.$_
  4. Perl은 비밀번호를 $_전체 텍스트로 입력하고 표준 출력으로 인쇄합니다.

이것이 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

read귀하의 버전이 이를 지원하지 않는 경우 -sPOSIX 호환성을 사용해 보십시오 .이 답변.

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다음 명령/출력이 새 줄에서 시작되도록 하는 것입니다.

관련 정보