[java] 비밀번호에 대해 char []가 String보다 선호되는 이유는 무엇입니까?

스윙에서 암호 필드는이 getPassword()(반환 char[]대신에 보통의) 방법 getText()(반환 String) 방법을. 마찬가지로 String암호를 처리하는 데 사용하지 말 것을 제안했습니다 .

String암호와 관련하여 보안에 위협이되는 이유는 무엇 입니까? 사용하기 불편하다 char[].



답변

문자열은 변경할 수 없습니다 . 당신이 만들어지면 그 수단 String다른 프로세스가 메모리를 덤프 할 수있는 경우는, (옆에서있는 방법은 없습니다 반사 이전에 데이터를 제거 할 수) 가비지 컬렉션 에서 차기.

배열을 사용하면 데이터를 완성한 후에 데이터를 명시 적으로 지울 수 있습니다. 배열을 원하는 것으로 덮어 쓸 수 있으며 가비지 수집 전에도 시스템의 어느 곳에도 암호가 표시되지 않습니다.

그래서 그래,이 보안 문제 -하지만도 사용은 char[]공격자 만 기회의 창을 줄이고, 그것은 단지 공격이 특정 유형입니다.

주석에서 언급했듯이 가비지 수집기에 의해 이동되는 배열은 메모리에 부유 한 데이터 복사본을 남길 수 있습니다. 나는 이것이 구현에 특정 적이 라고 믿습니다. 가비지 수집기 이런 종류의 것을 피하기 위해 모든 메모리를 지울 수 있습니다 . 그렇더라도 char[]실제 문자를 공격 창으로 포함하는 시간은 여전히 ​​남아 있습니다.


답변

여기에 다른 제안이 유효 해 보이지만 다른 좋은 이유가 있습니다. 평범하게 실수로 로그 , 모니터 또는 다른 안전하지 않은 장소에 암호를 인쇄String 할 가능성이 훨씬 높습니다 . 덜 취약합니다.char[]

이걸 고려하세요:

public static void main(String[] args) {
    Object pw = "Password";
    System.out.println("String: " + pw);

    pw = "Password".toCharArray();
    System.out.println("Array: " + pw);
}

인쇄물:

String: Password
Array: [C@5829428e


답변

공식 문서를 인용하기 위해 Java Cryptography Architecture 안내서 는 암호 char[]String암호에 대해 설명합니다 (암호 기반 암호화에 관한 것이지만 암호에 대해서는 더 일반적입니다).

유형의 객체에 암호를 수집하고 저장하는 것이 논리적으로 보입니다 java.lang.String. 그러나주의해야 할 점은 다음과 같습니다. Objects 유형 String은 변경할 수 없습니다. 즉, String
사용 후 내용을 변경 (덮어 쓰기)하거나 제로화 할 수있는 정의 된 메소드가 없습니다 . 이 기능은 String개체가 사용자 암호와 같은 보안에 민감한 정보를 저장하기에 적합하지 않게합니다. char대신 보안에 민감한 정보를 항상 배열로 수집하고 저장해야
합니다.

Java 프로그래밍 언어 용 보안 코딩 지침, 버전 4.0의 지침 2-2 에도 비슷한 내용이 나와 있습니다 (원래 로깅 컨텍스트에 있음).

지침 2-2 : 매우 민감한 정보를 기록하지 마십시오

사회 보장 번호 (SSN) 및 비밀번호와 같은 일부 정보는 매우 중요합니다. 이 정보는 필요 이상으로 보거나 관리자가 볼 수있는 위치에 보관해서는 안됩니다. 예를 들어, 로그 파일로 보내지 않아야하며 검색을 통해 존재 여부를 감지 할 수 없습니다. 일부 일시적인 데이터는 char 배열과 같은 가변 데이터 구조로 유지 될 수 있으며 사용 후 즉시 지워질 수 있습니다. 데이터 구조를 지우면 객체가 메모리에서 프로그래머에게 투명하게 이동함에 따라 일반적인 Java 런타임 시스템의 효율성이 떨어집니다.

이 지침은 또한 다루고있는 데이터에 대한 의미 지식이없는 하위 레벨 라이브러리의 구현 및 사용에 영향을 미칩니다. 예를 들어, 하위 수준 문자열 구문 분석 라이브러리는 작동하는 텍스트를 기록 할 수 있습니다. 애플리케이션은 라이브러리와 SSN을 구문 분석 할 수 있습니다. 이로 인해 로그 파일에 액세스 할 수있는 관리자가 SSN을 사용할 수있는 상황이 발생합니다.


답변

문자 배열 ( char[])은 사용 후 각 문자를 0으로 설정하고 문자열을 설정하지 않음으로써 지울 수 있습니다. 누군가가 어떻게 메모리 이미지를 볼 수 있다면, 문자열을 사용하면 일반 텍스트로 암호를 볼 수 있지만, 사용하면 char[]0으로 데이터를 제거한 후 암호는 안전합니다.


답변

어떤 사람들은 더 이상 필요하지 않은 암호를 저장하는 데 사용 된 메모리를 덮어 써야한다고 생각합니다. 이를 통해 공격자가 시스템에서 암호를 읽는 데 걸리는 시간이 단축되고 공격자가 이미이를 수행하기 위해 JVM 메모리를 하이재킹 할 수있는 충분한 액세스가 필요하다는 사실을 완전히 무시합니다. 많은 액세스 권한을 가진 공격자는 주요 이벤트를 포착하여이를 완전히 쓸모 없게 만들 수 있습니다 (AFAIK, 내가 틀렸다면 바로 정정하십시오).

최신 정보

의견 덕분에 답변을 업데이트해야합니다. 암호가 하드 드라이브에 도달 할 수있는 시간을 줄임으로써 약간의 보안 향상을 추가 할 수있는 두 가지 경우가 있습니다. 여전히 대부분의 사용 사례에서는 과잉이라고 생각합니다.

  • 대상 시스템이 잘못 구성되었거나 구성되어 있다고 가정해야하며 코어 덤프에 대해 편집증이 있어야합니다 (관리자가 시스템을 관리하지 않는 경우 유효 할 수 있음).
  • 공격자가 TrueCrypt (단종), VeraCrypt 또는 CipherShed 와 같은 것을 사용하여 하드웨어에 액세스 할 때 데이터 유출을 방지하려면 소프트웨어가 과도하게 편집증 상태 여야 합니다.

가능하면 코어 덤프와 스왑 파일을 비활성화하면 두 가지 문제가 모두 해결됩니다. 그러나 관리자 권한이 필요하고 기능 (사용할 메모리가 적음)이 줄어들고 실행중인 시스템에서 RAM을 가져 오는 것이 여전히 유효한 문제입니다.


답변

나는 이것이 유효한 제안이라고 생각하지 않지만 적어도 그 이유를 추측 할 수 있습니다.

동기 부여는 메모리에서 암호의 모든 흔적을 즉시 사용하고 확실하게 지울 수 있기를 원한다고 생각합니다. 를 사용 char[]하면 배열의 각 요소를 빈 칸으로 덮어 쓸 수 있습니다. String그런 식으로 내부 값을 편집 할 수 없습니다 .

그러나 이것만으로는 좋은 대답이 아닙니다. 왜 char[]또는 String탈출하지 않는지 확인 하지 않습니까? 그런 다음 보안 문제가 없습니다. 그러나 문제는 이론적으로 String객체를 intern()편집하고 일정한 수영장 안에 살 수 있다는 것입니다 . 나는 char[]이것을 사용하는 것이이 가능성 을 금지 한다고 생각 합니다.


답변

답변이 이미 제공되었지만 최근에 Java 표준 라이브러리에서 발견 한 문제를 공유하고 싶습니다. 암호 문자열을 char[]모든 곳 (물론 좋은 것) 으로 바꾸는 데 많은주의를 기울이는 반면 , 메모리에서 지우려면 보안에 중요한 다른 데이터를 간과하는 것 같습니다.

예를 들어 PrivateKey 클래스를 생각하고 있습니다. PKCS # 12 파일에서 개인 RSA 키를 사용하여 일부 작업을 수행하는 시나리오를 고려하십시오. 이제이 경우, 비밀번호 만 스니핑해도 키 파일에 대한 물리적 액세스가 제대로 제한되는 한 도움이되지 않습니다. 공격자는 암호 대신 키를 직접 입수하면 훨씬 나을 것입니다. 원하는 정보가 유출 될 수있는 것은 매니 폴드, 코어 덤프, 디버거 세션 또는 스왑 파일입니다.

결과적으로 PrivateKey해당 정보를 형성하는 바이트를 지우는 API가 없기 때문에 메모리에서 개인 정보를 지울 수있는 것은 없습니다 .

백서 에서는 이러한 상황이 어떻게 악용 될 수 있는지 설명하기 때문에 이는 나쁜 상황 입니다.

예를 들어 OpenSSL 라이브러리는 개인 키가 해제되기 전에 중요한 메모리 섹션을 덮어 씁니다. Java는 가비지 수집되므로 Java 키에 대한 개인 정보를 지우고 무효화하는 명시적인 방법이 필요합니다.이 키는 사용 후 즉시 적용됩니다.