OpenVPN 키를 생성하는 데 임시 파일이 필요하지 않습니다
키 자료를 메모리에 두면 파일 수명 주기를 피할 뿐, 유출을 피하는 것은 아닙니다. 출력과 오류 스트림을 분리하고, 그 뒤에는 키를 비밀로 취급하세요.
키 생성에는 임시 파일이 필요하지 않으며, 그것을 생략해도 대부분의 안내서가 암시하는 것보다 적게 고쳐진다. 이것이 없애는 것은 파일 수명 주기와 그 주변의 정리 경쟁이다. 손대지 않고 남기는 것은 나중에 비밀을 유출할 모든 기회다. 이런 스크립트의 정확성 문제는 진단과 키 자료가 서로 다른 스트림으로 이동하기 때문에 보통 다른 곳에 자리한다.
파일은 당신이 생각한 노출이 아니었다
임시 파일은 모든 사람이 읽을 수 있을 때, 충돌에서 살아남을 때, 또는 예외 후 정리 단계를 건너뛸 때 구체적인 위험이다. 그것들은 실재하며 고칠 가치가 있다. 그것들은 또한 국소적이고 눈에 보이며 시험하기 쉽다. 변경이 단지 겉모습이었다고 결론짓기 전에 자기 스크립트에서 각각을 지목하라.
더 조용한 위험은 하류에 있다: 디버깅 중에 출력되는 키, 결과 객체 전체를 직렬화하는 예외, 코어 덤프를 쓰는 충돌 처리기, 파일 경로를 받은 다음 내용을 받는 로그 수집기. 임시 파일을 피하는 것은 그중 어느 것에도 아무것도 하지 않으며, 반대로 믿는 것이 선의의 재작성이 비밀을 이전보다 더 노출된 채로 남기는 길이다. 변경을 일련의 개선 하나로 다루고, 해결책으로 보지 말라.
파일 이름이 주어지지 않을 때 클라이언트가 쓰는 것
클라이언트의 현재 버전은 출력 경로 없이 키 명령이 주어지면 생성된 키를 표준 출력으로 보낸다. 바로 이 문서화된 동작이 메모리 내 접근을 실행 가능하게 만들고, 도구를 장치 경로로 향하게 하는 옛 속임수의 필요를 없앤다.
import subprocess
proc = subprocess.run(
["openvpn", "--genkey", "tls-crypt"],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
check=True,
)
key_material = proc.stdout
명령을 목록으로 전달하라. 여기서는 셸 확장이 필요하지 않으며, 셸을 켜면 인수 경계가 당신이 통제하지 않는 인용 부호에 의존하게 된다. 스크립트가 예상과 다른 검색 경로로 실행될 수 있다면 의도한 실행 파일을 절대 경로로 사용하라.
반환 코드 검사는 실패한 호출 후에 성공 경로가 계속되는 것을 막는다. 그것이 없으면 빈 바이트 문자열이 앞으로 흘러가 훨씬 나중에, 키가 사용되는 지점에서 실패하며, 그때 오류 메시지는 생성에 대해 전혀 언급하지 않는다.
두 스트림, 두 의미
표준 출력은 키를 나른다. 표준 오류는 도구가 당신에게 말하고 싶은 모든 것을 나르며, 구성과 버전과 키 유형에 대한 경고도 포함한다. 둘 다 하나의 버퍼로 돌리는 것이 그럴듯해 보이는 키의 중간에 문장을 꿰매 넣는 실수다.
실패 경로도 분리해 두라. 호출이 실패하면 실패한 명령과 종료 상태를 보고하고, 그다음 표준 오류의 어느 부분이 보여도 안전한지 의식적으로 결정하라. 결과 객체 전체를 로그로 쏟아붓는 것이 흔한 지름길이며, 키를 함께 실어 나를 수 있다.
나중에 자료를 해시하거나 비교한다면 바이너리 안전 읽기가 중요하다. 예상치 못한 인코딩의 텍스트 모드는 텍스트가 되도록 의도된 적 없는 바이트를 바꿀 수 있고, 바뀐 키는 핸드셰이크가 실패할 때까지 잘못된 키와 구별되지 않는다.
그래도 저장한다면 의식적으로 하라
대부분의 배포는 결국 키를 디스크나 게이트웨이, 또는 비밀 저장소에 필요로 한다. 생성 시점부터 제한적 권한으로 한 번 쓰고, 나중의 chmod에 기대지 말며, 쓰기를 원자적으로 만들어 부분 파일이 서비스가 시작할 때 읽는 파일이 되지 않게 하라. 같은 디렉터리의 경로에서 이름을 바꾸는 것으로 보통 충분하다. 실패 분기에서는 준비 경로를 제거하라, 실패한 쓰기가 바로 사람들이 잊는 사본이기 때문이다.
파일을 만들 때 모드를 설정하고, 디렉터리 모드도 제한적으로 유지하라. 백업 작업이 생각 없이 쓸어가는 위치 아래의 경로는 피하라. 야간 백업 속의 비밀은 그 백업의 모든 사본 속의 비밀이므로, 같은 논리가 다른 서비스가 읽을 수 있는 공유 볼륨에도 적용된다.
공유 키는 신원이 아니다
이 자료를 생성해도 인증서가 발급되지 않고, 클라이언트가 등록되지 않으며, 누가 접속하는지도 확립되지 않는다. 공유 키는 이미 서로를 신뢰하는 당사자 사이의 채널을 보호하며, 신원은 여전히 인증서와 그 앞에 놓인 어떤 인증에서 온다.
키 유형도 서로 교환할 수 없다. 한 기능을 위한 대칭 키가 다른 기능을 위한 그대로의 대체품은 아니며, 새 릴리스는 양쪽 끝에서 서로 다른 파일을 가진 자체 변형을 더한다. 구성이 실제로 지목하는 유형을 생성하고, 그 유형이 정의하는 역할에서 사용하라.
파일 크기를 살피는 대신 실제 연결로 결과를 시험하라. 핸드셰이크가 완료되고 로그에 키 경고가 없다면 생성 경로는 옳고, 키가 합쳐진 스트림으로 잘렸다면 연결은 스크립트가 아니라 상대를 가리키는 방식으로 실패했을 것이다.