FlawOpen

flawopen.com/안전하지 않은 역직렬화/.NET BinaryFormatter 보안

.NET BinaryFormatter는 안전한가요?

CWE-502: Deserialization of Untrusted Data참고 페이지
짧은 답: 안전한 설정은 없습니다

Microsoft는 BinaryFormatter가 안전하지 않으며 안전하게 만들 수 없다고 밝힙니다. 데이터가 신뢰 가능하다고 생각하더라도 사용 중단을 권장합니다. .NET 9에는 API 형식이 남아 있지만 기본 구현은 항상 PlatformNotSupportedException을 발생시킵니다. 이전 런타임과 지원되지 않는 호환 패키지에는 기존 위험이 남습니다.

위험
// 신뢰 경계를 넘는 데이터를 역직렬화하지 마세요.
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

public static class LegacyReader
{
    public static object Deserialize(Stream input) =>
        new BinaryFormatter().Deserialize(input);
}

// 제한 없는 다형성 serializer도 제거하세요:
SoapFormatter
NetDataContractSerializer
LosFormatter
ObjectStateFormatter  // ASP.NET ViewState 내부에서 사용

// SerializationBinder도 이 형식을 안전하게 만들지 않습니다.
마이그레이션
// 데이터 구조는 애플리케이션 코드에서 선언합니다.
// Nullable reference types make the DTO contract explicit.
#nullable enable
using System;
using System.IO;
using System.Text.Json;

public sealed record MyDto(int Id, string Name);

public static class DtoReader
{
    public static MyDto Parse(ReadOnlySpan<byte> json)
    {
        // 입력 크기를 제한하고 애플리케이션 규칙을 검증하세요.
        if (json.Length > 65_536)
            throw new InvalidDataException();

        MyDto? value = JsonSerializer.Deserialize<MyDto>(json);
        if (value is null || value.Id <= 0 ||
            string.IsNullOrWhiteSpace(value.Name) ||
            value.Name.Length > 100)
            throw new InvalidDataException();

        return value;
    }
}

// 기존 NRBF 파일은 NrbfDecoder로 레코드를 확인하고
// 허용된 값만 DTO에 매핑하세요.
// 임의 런타임 형식을 재생성하지 마세요.

BinaryFormatter가 위험한 이유

BinaryFormatter.Deserialize는 스트림에서 객체 그래프를 재구성하며 공격자가 제어하는 데이터가 실행 흐름에 영향을 줄 수 있습니다. Microsoft는 서비스 거부, 정보 노출, 원격 코드 실행 위험을 경고합니다. 핵심 문제는 제한 없는 다형성 역직렬화입니다. 직렬화 데이터가 처리될 형식과 객체 상태에 영향을 줄 수 있습니다. 어떤 formatter 설정도 이를 신뢰할 수 없는 바이트를 읽는 안전한 파서로 바꾸지 못합니다.

위험은 공개 HTTP 엔드포인트에만 있지 않습니다. 파일, 캐시, 큐, DB 레코드, 데스크톱 클라이언트 메시지, 클라우드 동기화 상태도 나중에 공격자 영향을 받을 수 있습니다. 바이트가 시스템에 들어와 이동하는 경로를 추적하세요. “우리가 쓴 데이터” 또는 “내부 데이터”는 영구적인 신뢰 표시가 아닙니다.

SerializationBinder만으로 부족한 이유

사용자 지정 SerializationBinder는 formatter가 확인하는 형식을 제한할 수 있지만, Microsoft는 binder나 설정 변경이 DoS를 막지 못하고 다른 공격도 충분히 완화하지 못할 수 있다고 명시합니다. Binder는 마이그레이션 대안이 아닙니다. 제거를 기다리는 동안에도 신뢰할 수 없는 입력을 받지 마세요.

레거시 사용과 관련 경로 찾기

소스, 프로젝트 참조, 런타임 설정에서 BinaryFormatter, IFormatter, SoapFormatter, NetDataContractSerializer, LosFormatter, ObjectStateFormatter를 검색하세요. 세션 provider, 캐시 adapter, 큐 consumer, 파일 입출력, 기존 ASP.NET Web Forms 경로도 확인하세요. ViewState는 보통 메시지 인증 코드(MAC)로 보호됩니다. 보호를 유지하고 machine key를 보호하세요. MAC이 일반 BinaryFormatter 역직렬화를 안전하게 만들지는 않습니다.

데이터 형식과 런타임 버전에 따라 마이그레이션

새 데이터는 형식과 호환성에 맞춰 System.Text.Json, DataContractSerializer, MessagePack, protobuf-net 같은 명시적 계약을 선택하세요. 바로 대체할 제품은 없습니다. 기존 NRBF 파일을 보존해야 한다면 .NET 9의 NrbfDecoder가 인코딩된 애플리케이션 형식을 인스턴스화하지 않고 레코드를 디코딩할 수 있습니다. 구조를 검증하고 예상된 값만 DTO에 매핑하세요. WinForms/WPF의 리소스, 클립보드, 끌어서 놓기 마이그레이션도 별도로 확인하세요.

자주 묻는 질문

직접 기록한 데이터만 역직렬화합니다. 괜찮나요?

Microsoft는 데이터가 신뢰 가능해 보여도 마이그레이션을 권장합니다. 저장소, 캐시, 파일, 동기화, 하위 서비스가 신뢰 경계를 넘을 수 있습니다. 각 데이터 원본에 쓸 수 있는 주체를 확인하고 가정에 기대지 말고 BinaryFormatter 사용을 중단하세요.

.NET 9로 옮기면 어떻게 되나요?

.NET 9에는 API 형식이 남아 있지만 이전 호환 스위치와 관계없이 기본 구현은 항상 PlatformNotSupportedException을 발생시킵니다. 업그레이드 전에 사용처를 찾아 마이그레이션하세요. 지원되지 않는 호환 패키지는 취약한 구현을 복원할 뿐 보안 수정이 아닙니다.

Json.NET은 안전한 대체재인가요?

Json.NET은 기본적으로 TypeNameHandling을 None으로 설정해 payload의 형식 메타데이터가 임의 CLR 형식을 선택하지 않습니다. 신뢰할 수 없는 입력에 다른 설정을 켜지 마세요. 다형성이 필요하면 애플리케이션이 관리하는 엄격한 allowlist와 라이브러리 지침을 따르세요. TypeNameHandling은 안전한가요?를 참조하세요.

출처 및 참고자료

함께 보기 안전하지 않은 역직렬화: 위험과 대응 | flawopen.com Java ObjectInputStream 보안과 안전한 역직렬화 Newtonsoft.Json TypeNameHandling: 안전한 설정 PHP unserialize()와 신뢰할 수 없는 입력 Python pickle.load(): 신뢰할 수 없는 데이터 위험 Ruby YAML.load는 안전한가요? Psych 버전과 safe_load