문제

.NET의 SecureString의 목적을 파악하려고 합니다.MSDN에서:

System.String 클래스의 인스턴스는 변경할 수 없으며 더 이상 필요하지 않은 경우 프로그래밍 방식으로 가비지 수집을 예약할 수 없습니다.즉, 인스턴스는 생성된 후 읽기 전용이며 인스턴스가 컴퓨터 메모리에서 언제 삭제될지 예측할 수 없습니다.결과적으로 String 개체에 비밀번호, 신용 카드 번호 또는 개인 데이터와 같은 민감한 정보가 포함되어 있는 경우 응용 프로그램이 컴퓨터 메모리에서 데이터를 삭제할 수 없기 때문에 해당 정보가 사용된 후 노출될 위험이 있습니다.

SecureString 객체는 텍스트 값을 갖는다는 점에서 String 객체와 유사합니다.그러나 SecureString 개체의 값은 자동으로 암호화되고, 응용 프로그램이 읽기 전용으로 표시할 때까지 수정될 수 있으며, 응용 프로그램이나 .NET Framework 가비지 수집기에 의해 컴퓨터 메모리에서 삭제될 수 있습니다.

SecureString 인스턴스의 값은 인스턴스가 초기화되거나 값이 수정될 때 자동으로 암호화됩니다.애플리케이션은 MakeReadOnly 메서드를 호출하여 인스턴스를 변경할 수 없도록 렌더링하고 추가 수정을 방지할 수 있습니다.

자동 암호화가 큰 이득인가요?

그리고 나는 왜 다음과 같이 말할 수 없습니까?

SecureString password = new SecureString("password");

대신에

SecureString pass = new SecureString();
foreach (char c in "password".ToCharArray())
    pass.AppendChar(c);

SecureString의 어떤 측면이 누락되어 있나요?

도움이 되었습니까?

해결책

현재 사용하는 프레임 워크의 일부 SecureString:

주요 목적은 공격 표면을 제거하기보다는 공격 표면을 줄이는 것입니다. SecureStrings RAM에 "고정"되어 있으므로 쓰레기 수집기가 이동하거나 사본을 만들지 않습니다. 또한 일반 텍스트가 스왑 파일 또는 코어 덤프에 기록되지 않도록합니다. 암호화는 난독 화와 비슷하며 결정된 해커를 멈추지 않을 것입니다. 대칭 키 그것을 암호화하고 해독하는 데 사용됩니다.

다른 사람들이 말했듯이 SecureString 캐릭터 별 문자 별은 다른 방법으로 수행하는 첫 번째 명백한 결함 때문입니다.

SecureStringS는 닭고기와 egg 문제를 해결하는 첫 번째 단계이므로 대부분의 최신 시나리오는 일반 문자열로 다시 변환해야하더라도 프레임 워크의 존재는 이제 미래 - 최소한 프로그램이 약한 링크가 될 필요가없는 시점까지.

다른 팁

많은 훌륭한 답변; 다음은 논의 된 내용에 대한 빠른 시놉시스입니다.

Microsoft는 민감한 정보 (신용 카드, 비밀번호 등)를 더 나은 보안을 제공하기 위해 Sicurestring 클래스를 구현했습니다. 자동으로 제공합니다.

  • 암호화 (메모리 덤프 또는 페이지 캐싱의 경우)
  • 메모리에 고정
  • 읽기 전용으로 표시하는 기능 (추가 수정을 방지하기 위해)
  • 상수 문자열을 통과하지 못하면 안전한 구조

현재 Securestring은 사용이 제한되어 있지만 향후 더 나은 채택을 기대합니다.

이 정보를 바탕으로, Securestring의 생성자는 문자열을 가져 와서 문자열이 Securestring의 목적을 물리 치는 것처럼 문자열을 char 배열로 슬라이스하지 않아야합니다.

추가 정보:

  • 게시하다 .NET 보안 블로그에서 여기에서 다루는 것과 거의 동일하게 이야기합니다.
  • 그리고 또 다른 하나그것을 다시 방문하고 증권의 내용을 버릴 수있는 도구를 언급합니다.

편집 : 많은 사람들에게 좋은 정보가 있기 때문에 최고의 답변을 선택하기가 어렵다는 것을 알았습니다. 너무 나쁘게 답변 옵션이 없다.

짧은 답변

왜 난 이렇게 말할 수 없나요:

SecureString password = new SecureString("password");

왜냐하면 지금 당신은 password 기억 속에;닦을 방법이 없습니다. 이것이 바로 요점입니다. SecureString.

긴 답변

이유 SecureString 존재하는 것은 당신이 사용할 수 없기 때문입니다 제로메모리 작업이 끝나면 민감한 데이터를 삭제합니다.존재하는 문제를 해결하기 위해 존재합니다. 왜냐하면 CLR의.

정기적으로 토종의 당신이 호출할 응용 프로그램 SecureZeroMemory:

메모리 블록을 0으로 채웁니다.

메모:SecureZeroMemory는 다음과 동일합니다. ZeroMemory, 컴파일러가 그것을 최적화하지 않는다는 점을 제외하면.

문제는 당신이 캔트 부르다 ZeroMemory 또는 SecureZeroMemory .NET 내부.그리고 .NET 문자열은 변경할 수 없습니다.넌 할 수도 없어 덮어쓰기 다른 언어에서 할 수 있는 것처럼 문자열의 내용:

//Wipe out the password
for (int i=0; i<password.Length; i++)
   password[i] = \0;

그럼 당신은 무엇을 할 수 있나요?.NET에서 작업을 마친 후 메모리에서 암호나 신용 카드 번호를 지우는 기능을 어떻게 제공합니까?

이를 수행할 수 있는 유일한 방법은 문자열을 일부 위치에 배치하는 것입니다. 토종의 메모리 블록, 당신은 어디에 ~할 수 있다 그럼 전화해 ZeroMemory.다음과 같은 기본 메모리 개체:

  • BSTR
  • HGLOBAL
  • CoTaskMem 관리되지 않는 메모리

SecureString은 잃어버린 능력을 되돌려줍니다

.NET에서는 문자열 사용이 끝나면 문자열을 지울 수 없습니다.

  • 그것들은 불변이다;내용을 덮어쓸 수 없습니다
  • 당신은 할 수 없습니다 Dispose 그들의
  • 청소는 가비지 수집가의 손에 달려 있습니다.

SecureString은 문자열 안전을 전달하고 필요할 때 정리를 보장할 수 있는 방법으로 존재합니다.

당신은 질문을했습니다 :

왜 난 이렇게 말할 수 없나요:

SecureString password = new SecureString("password");

왜냐하면 지금 당신은 password 기억 속에;닦을 방법도 없이.CLR이 해당 메모리를 재사용하기로 결정할 때까지 거기에 머물러 있습니다.당신은 우리를 우리가 시작한 곳으로 바로 되돌려 놓았습니다.제거할 수 없는 비밀번호가 있는 실행 중인 애플리케이션과 메모리 덤프(또는 프로세스 모니터)가 비밀번호를 볼 수 있는 곳.

SecureString은 데이터 보호 API를 사용하여 암호화된 문자열을 메모리에 저장합니다.그렇게 하면 스왑 파일, 크래시 덤프, 심지어 동료가 살펴보는 로컬 변수 창에도 문자열이 존재하지 않습니다.

비밀번호는 어떻게 읽나요?

그렇다면 질문은 다음과 같습니다.문자열과 어떻게 상호작용하나요?당신은 절대적으로 ~하지 않다 다음과 같은 방법을 원합니다.

String connectionString = secureConnectionString.ToString()

이제 당신은 시작했던 곳으로 바로 돌아왔기 때문입니다. 제거할 수 없는 비밀번호입니다.당신은 원한다 개발자는 민감한 문자열을 올바르게 처리하기 위해 ~할 수 있다 기억에서 지워집니다.

이것이 바로 .NET이 SecureString을 관리되지 않는 메모리로 마샬링하는 세 가지 편리한 도우미 함수를 제공하는 이유입니다.

문자열을 관리되지 않는 메모리 Blob으로 변환하고 처리한 다음 다시 지웁니다.

일부 API는 허용 SecureString.예를 들어 ADO.net 4.5에서는 SqlConnection.Credential 세트를 가져간다 Sql자격 증명:

SqlCredential cred = new SqlCredential(userid, password); //password is SecureString
SqlConnection conn = new SqlConnection(connectionString);
conn.Credential = cred;
conn.Open();

연결 문자열 내에서 비밀번호를 변경할 수도 있습니다.

SqlConnection.ChangePassword(connectionString, cred, newPassword);

그리고 .NET 내부에는 호환성 목적으로 일반 문자열을 계속 허용한 다음 신속하게 이를 SecureString에 넣는 곳이 많이 있습니다.

SecureString에 텍스트를 넣는 방법은 무엇입니까?

여전히 문제가 남아 있습니다.

처음에 SecureString에 대한 비밀번호를 어떻게 얻나요?

이것이 어려운 일이지만 중요한 점은 보안에 대해 생각하게 만드는 것입니다.

때로는 해당 기능이 이미 제공되는 경우도 있습니다.예를 들어, WPF 비밀번호 상자 제어 장치는 입력한 비밀번호를 다음과 같이 반환할 수 있습니다. SecureString 곧장:

PasswordBox.SecurePassword 속성

현재 보유하고 있는 비밀번호를 가져옵니다. 비밀번호 상자 로서 SecureString.

원시 문자열을 전달했던 모든 곳에서 이제 SecureString이 String과 호환되지 않는다고 불평하는 유형 시스템이 있기 때문에 이는 도움이 됩니다.SecureString을 일반 문자열로 다시 변환하기 전에 가능한 한 오래 가고 싶습니다.

SecureString 변환은 매우 쉽습니다.

  • SecureStringToBSTR
  • PtrToStringBSTR

다음과 같이:

private static string CreateString(SecureString secureString)
{
    IntPtr intPtr = IntPtr.Zero;
    if (secureString == null || secureString.Length == 0)
    {
        return string.Empty;
    }
    string result;
    try
    {
        intPtr = Marshal.SecureStringToBSTR(secureString);
        result = Marshal.PtrToStringBSTR(intPtr);
    }
    finally
    {
        if (intPtr != IntPtr.Zero)
        {
            Marshal.ZeroFreeBSTR(intPtr);
        }
    }
    return result;
}

그들은 당신이 그렇게 하는 것을 정말로 원하지 않습니다.

하지만 SecureString에 문자열을 어떻게 추가하나요?그럼 당신이 해야 할 일은 더 이상 비밀번호를 사용하지 않는 것입니다. 우선.넌 그걸 꼭 넣어야 했어 무엇 또 다른.심지어 Char[] 배열이 도움이 될 것입니다.

그러면 각 문자를 추가할 수 있습니다. 그리고 완료되면 일반 텍스트를 지우십시오.

for (int i=0; i < PasswordArray.Length; i++)
{
   password.AppendChar(PasswordArray[i]);
   PasswordArray[i] = (Char)0;
}

비밀번호가 저장되어 있어야 합니다. 일부 지울 수 있는 기억.거기에서 SecureString으로 로드하세요.


tl;dr: SecureString 동등한 것을 제공하기 위해 존재합니다. 제로메모리.

어떤 사람들은 요점을 보지 못한다. 기기가 잠겨 있을 때 메모리에서 사용자 비밀번호 삭제, 또는 닦아내기 인증된 키 입력을 메모리에서 지우기.그 사람들은 SecureString을 사용하지 않습니다.

프레임 워크의 현재 버전에서 Securestring을 현명하게 사용할 수있는 시나리오는 거의 없습니다. 관리되지 않는 API와 상호 작용하는 데만 유용합니다. Marshal.securestringtoglobalallocunicode를 사용하여 마샬링 할 수 있습니다.

System.String에서/로 변환하자마자 목적을 물리 쳤습니다.

MSDN 견본 콘솔 입력에서 한 번에 한 번에 특성을 생성하고 보안 문자열을 관리되지 않는 API로 전달합니다. 다소 복잡하고 비현실적입니다.

미래 버전의 .NET이 더 유용 할 수 있도록 보안을 더 많이 지원할 것으로 기대할 수 있습니다.

  • SECURESTRING CONSOLE.READLINECURE () 또는 샘플의 모든 복잡한 코드없이 SECURESTRING에 콘솔 입력을 읽는 것과 유사합니다.

  • Winforms textbox 교체를 텍스트 box.text 속성을 보안 문자열로 저장하여 비밀번호를 안전하게 입력 할 수 있습니다.

  • 보안 관련 API 로의 확장 장치가 암호를 증권으로 전달할 수 있도록합니다.

위의 것이 없으면 증권은 값이 제한적입니다.

하나의 평평한 인스턴스화 대신 캐릭터가 부여 해야하는 이유는 Securestring의 생성자에게 "비밀번호"를 전달하는 백그라운드에서 보안 문자열의 목적을 물리 치는 "비밀번호"문자열을 메모리에 넣기 때문입니다.

추가함으로써 당신은 한 번에 캐릭터를 기억에 넣는 것만으로, 서로 인접 해지지 않는 likley는 원래 문자열을 재구성하기가 훨씬 어렵습니다. 나는 여기서 틀릴 수 있지만 그것이 나에게 설명 된 방법입니다.

클래스의 목적은 메모리 덤프 또는 유사한 도구를 통해 보안 데이터가 노출되는 것을 방지하는 것입니다.

MS는 서버 (데스크탑 등)를 유발하는 특정 인스턴스에서 런타임 환경이 메모리의 내용을 노출시키는 메모리 덤프를 수행 할 때가 있었음을 발견했습니다. 보안 문자열은 메모리에서 암호화하여 공격자가 문자열의 내용을 검색하지 못하게합니다.

Securestring의 큰 이점 중 하나는 페이지 캐싱으로 인해 데이터가 디스크에 저장 될 가능성을 피할 수 있다는 것입니다. 메모리에 비밀번호가 있고 큰 프로그램이나 데이터 세트를로드하면 프로그램이 메모리에서 벗어나면서 비밀번호가 스왑 파일에 기록 될 수 있습니다. 증시 스트링을 사용하면 최소한 데이터가 명확한 텍스트로 디스크에 무기한 주위에 앉아 있지 않습니다.

문자열이 안전해야하기 때문이라고 생각합니다. 즉, 해커는 그것을 읽을 수 없어야합니다. 문자열로 초기화하면 해커는 원래 문자열을 읽을 수 있습니다.

글쎄, 설명에 따르면, 값은 암호화 된 저장되며, 프로세스의 메모리 덤프는 문자열의 값을 드러내지 않음을 의미합니다 (상당히 심각한 작업이 없음).

일정한 문자열에서 증서를 구축 할 수없는 이유는 당신이 때문입니다. ~일 것이다 암호화되지 않은 버전의 문자열이 메모리에 있습니다. 조각으로 문자열을 생성하도록 제한하면 전체 문자열을 메모리에 한 번에 가질 위험이 줄어 듭니다.

Securestring 사용을 중단 할 것입니다. PG Guys가 지원하는 것처럼 보입니다. 아마도 미래에 그것을 당기는 것도 - https://github.com/dotnet/apireviews/tree/master/2015-07-14-securestring .

.NET Core의 모든 플랫폼에서 Securestring에서 암호화를 제거해야합니다. Securestring을 사용하지 않아야합니다. 아마도 .NET Core에서 Securestring을 노출해서는 안됩니다.

또 다른 사용 사례 불변의 데이터 구조를 사용할 수 없습니다 신중한 개발자이기 때문에 민감한 데이터를 저장하기 위해. 예를 들어 : 민감한 카드 데이터 또는 인증 메타 데이터를 불변의 문자열에 저장하면이 데이터가 폐기 된 후 상당한 시간 동안 메모리에서 사용할 수있는 경우가 항상있을 것입니다. 나는 단순히 그것을 덮어 쓸 수 없습니다. 이러한 민감한 데이터가 메모리에 유지되는 또 다른 큰 장점.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top