echo를 사용하여 민감한 데이터를 chpasswd에 전달하는 것이 안전합니까?


17

를 사용하여 몇 가지 사용자 계정 암호를 대량으로 설정하려고합니다 chpasswd. 암호는 무작위로 생성되어 인쇄되어 있어야합니다 stdout(암호 저장소에 적어 두거나 암호 저장소에 넣어야합니다) chpasswd.

순진하게, 나는 이것을 이렇게 할 것입니다

{
  echo student1:$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 13 ; echo '')
  echo student2:$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 13 ; echo '')
} | tee >(chpasswd)

그러나 나는에 명령 줄 인수로 새 암호를 통과 걱정 echo인수가 다른 사용자에게 일반적으로 볼 수 있기 때문에, ps -aux(나는 본 적이 있지만, 어떤 echo라인에 나타납니다 ps).

반환 된 비밀번호에 값을 추가 한 다음 전달하는 다른 방법이 chpasswd있습니까?


6
echo쉘 내장입니다. 프로세스 테이블에 나타나지 않습니다.
Kusalananda

답변:


15

echo쉘이 내장되어 있으므로 프로세스 테이블에 표시되지 않으므로 코드가 안전해야합니다 .

대체 솔루션은 다음과 같습니다.

#!/bin/bash

n=20
paste -d : <( seq -f 'student%.0f' 1 "$n" ) \
           <( tr -cd 'A-Za-z0-9' </dev/urandom | fold -w 13 | head -n "$n" ) |
tee secret.txt | chpasswd

이렇게하면 n명령의 명령 행에 암호를 전달하지 않고 학생 이름과 암호를 작성합니다 .

paste유틸리티는 여러 파일을 열로 붙이고 그 사이에 구분 기호를 삽입합니다. 여기서는 :구분자로 사용하여 두 개의 "파일"(프로세스 대체)을 제공합니다. 첫 번째는 seq20 개의 학생 사용자 이름을 생성 하는 명령의 출력을 포함하고 두 번째는 길이가 13 인 임의의 20 개의 문자열을 생성하는 파이프 라인의 출력을 포함합니다.

사용자 이름이 이미 생성 된 파일이있는 경우 :

#!/bin/bash

n=$(wc -l <usernames.txt)

paste -d : usernames.txt \
           <( tr -cd 'A-Za-z0-9' </dev/urandom | fold -w 13 | head -n "$n" ) |
tee secret.txt | chpasswd

secret.txt터미널에서 생성 된 비밀번호를 표시하는 대신 비밀번호와 사용자 이름을 파일에 저장합니다 .


2
즉 필요가없는 똑똑한 솔루션의 echo또는 printf그러나 코드가 해독 조금 어색,
닐스 베르너

@NilsWerner 조금 더 설명을 추가했습니다. 내가 확장하고 싶은 특별한 것이 있으면 알려주세요.
Kusalananda

1
echo그러나 쉘 내장 에 의존해서는 안됩니다 . 대부분의 껍질에는 그것이 있지만, 그 염에 대한 요구 사항은 전혀 없습니다.
Austin Hemmelgarn

1
@Kusalananda 그냥 궁금해서, 사이의 효과 차이가 tee secret.txt > >(chpasswd)tee secret.txt | chpasswd? 후자는 훨씬 일반적으로
보이므로 왜

1
@ChristopherShroba 이미 문제가있는 코드와 비슷한 이유는 없습니다 (프로세스 대체 사용 tee). 당신이 지적 했으므로, 나는 실제로 그것을 바꿀 것이라고 생각합니다 (더 좋아 보입니다). 감사.
Kusalananda

8

echo쉘에 내장되어 있으므로 ps별도의 프로세스로 표시되지 않습니다 .

그러나 명령 대체를 사용할 필요는 없습니다. 파이프 라인의 출력을 직접 다음과 chpasswd같이 할 수 있습니다 .

{  printf "%s:" "$username";
   head /dev/urandom | tr -dc A-Za-z0-9 | head -c 13 ; echo ''
} | chpasswd 

한 번의 실행으로 여러 개의 비밀번호를 변경 chpasswd하려면 필수 부분을 반복하는 것이 쉬워야합니다. 또는 함수로 만드십시오.

genpws() {
    for user in "$@"; do
        printf "%s:" "$user";
        head /dev/urandom | tr -dc A-Za-z0-9 | head -c 13
        echo
    done
}
genpws username1 username2... | chpasswd 

제쳐두고 : 그것은 라인 지향적이 아니기 head /dev/urandom때문에 조금 이상하게 느낍니다 urandom. 사용 가능한 엔트로피에 대한 커널의 개념에 영향을 미쳐 결과적으로 /dev/random블로킹으로 이어질 수 있습니다 . 고정 된 양의 데이터를 읽고 base64임의의 바이트를 인쇄 가능한 문자로 변환하는 것과 같은 것을 사용하는 것이 더 깨끗할 수 있습니다 (단, 바이트의 약 3/4를 버리는 대신).

이와 같은 것은 당신에게 대략을 줄 것입니다. 16 자 및 숫자 :

head -c 12 /dev/urandom | base64 | tr -dc A-Za-z0-9 

(즉, 16 이하의 금액입니다 +/문자의 출력에 base64적어도 14 개 문자를 떠나는 99 %의 확률에 대해 제공하는, 내가 바로 내 조합론을 가지고있는 경우 하나의 가능성이 있으므로, 문자 당 1/32이다. 그리고 99.99 % 확률로 12 이상 남음.)


귀하의 printf솔루션은 내 원래 코드의 기능을 수행하지 않습니다. 여러 사용자 이름에 대해 여러 줄을 반환하지만 귀하의 의견에 감사드립니다.head urandom
Nils Werner

@NilsWerner, 글쎄, 여러 사용자로의 확장은 분명합니다. 그러나 여러 사용자를 위해 username : password 쌍을 한 번에 생성하는 기능을 만들 수 있습니다. (편집 참조)
ilkkachu

3
당신은 정말 당신이 원하는 문자를 충분히 포함 urandom에서 처음 10 "줄"에 의존 할 수 없습니다. 대신 tr을 통해 직접 urandom을 실행하십시오.
Kusalananda

@ Kusalananda, 내 head -c 10 | base64파이프 라인 을 의미 head | tr합니까? 랜덤 바이트의 10 개의 "라인"은 수백 바이트 일 가능성이 높습니다 (256 개 중 1 개만 줄 바꿈이 됨). 이론 상으로는 정확히 10 바이트 일 수 있지만 그 가능성은 완전히 무시할 수 있습니다. 마찬가지로을 사용할 때 base64임의의 바이트가 just라고 말하면 \xffbase64는 슬래시 문자열 일뿐이지만 그럴 가능성도 거의 없습니다. 당신이 걱정한다면, 당신은 10 바이트 이상을 읽을 수 있으며, 그 확률을 줄이고 결과 출력의 길이를 줄입니다.
ilkkachu

1
@ilkkachu 두 코드를 모두 언급하고 있습니다. 임의의 바이트를 읽고 원하지 않는 것을 필터링 한 후 특정 길이의 것을 원하면 필요한 것을 얻을 때까지 데이터 소스를 잘라 내지 마십시오. 당신이 말했듯이, 에서 10 개의 줄 바꿈 문자열을 얻을 가능성거의/dev/urandom 없지만 위험은 0 %가 아닙니다.
Kusalananda
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.