홈으로 돌아가기

개발자를 위한 Kerberos: 프로토콜 및 SSPI

이 기사는 AD용 Kerberos 프로토콜을 분석: 가장 및 TGT부터 위임 및 C++ 코드까지. 한 대의 머신에서 테스트할 SSPI, PKINIT, U2U 예제. 시니어 개발자 적합.

Kerberos: TGT, 위임 및 SSPI용 C++ 코드
Advertisement 728x90

Kerberos 프로토콜: 개발자를 위한 깊이 있는 분석

Kerberos는 사칭 문제를 해결합니다: A 머신의 서비스가 원격 클라이언트로부터 요청을 받고 해당 클라이언트 대신 로컬 리소스 접근을 포함한 작업을 수행해야 합니다. 이를 위해 제공된 자격 증명을 기반으로 새로운 액세스 토큰이 생성됩니다. Kerberos가 없으면 서비스는 자신의 토큰을 사용하므로 상승된 권한이 필요한 파일 접근이 차단됩니다.

연쇄 요청 시나리오에서 서비스 A가 서비스 B를 요청합니다. 위임을 통해 자신의 계정으로 사칭할지 원래 클라이언트로 할지 선택할 수 있습니다. Kerberos는 사용자의 SID, 그룹, PAC(특권 속성 인증서)를 포함한 암호화된 티켓을 전달합니다.

주요 구성 요소:

Google AdInline article slot
  • Principal: 비밀번호를 가진 엔티티(사용자, 컴퓨터, 서비스).
  • KDC (키 배포 센터): 비밀번호를 저장하고 TGT(티켓 부여 티켓)와 서비스 티켓을 발급합니다.
  • SPN (서비스 주체 이름): 서비스 식별자. 종종 서비스가 실행되는 계정을 가리킵니다.

Kerberos는 인증과 권한 부여를 구분합니다: 티켓 복호화로 신원을 확인하고 토큰으로 권한을 결정합니다.

메시지 구조와 전송

Kerberos 메시지는 ASN.1(PER/DER 인코딩, RFC 4120 기준)을 사용합니다. UDP/TCP 포트 88을 통해 전송됩니다. UDP는 짧은 패킷(TGT ~1-2 KB)에, TCP는 PAC가 포함된 큰 패킷에 적합합니다.

Active Directory의 KDC는 AS(인증 서비스)와 TGS(티켓 부여 서비스)를 결합합니다. SRV 레코드(_kerberos._tcp.<domain>)가 도메인 컨트롤러를 가리킵니다.

Google AdInline article slot

AS-Exchange 프로세스 (TGT 획득):

  • Client → KDC: KRB_KDC_REQ (타임스탬프 포함 사전 인증, 비밀번호 또는 PKINIT으로 암호화).
  • KDC → Client: KRB_KDC_REP (클라이언트 장기 키로 암호화된 TGT; 사전 인증에 세션 키 포함).
  • Client가 LSA(로컬 보안 권한)에 TGT를 저장합니다.

TGS-Exchange (서비스 티켓):

  • Client → KDC: KRB_TGS_REQ (TGT + 인증자 + 서비스 이름/SPN).
  • KDC → Client: KRB_TGS_REP (서비스 티켓, 서비스 세션 키).

AP-REQ(서비스 티켓 포함)는 LDAP, HTTP Negotiate, SMB, RPC에 캡슐화됩니다. Wireshark에서 GSS-WRAP에 NTLM/Kerberos 토큰이 표시됩니다.

Google AdInline article slot

암호화와 키

비밀번호는 장기 키(AES-256-CTs, Windows용)로 해싱됩니다. 세션 키는 메시지 보호를 위한 임시 키입니다.

CNG(Cryptography API: Next Generation)를 사용한 Kerberos AES 암호화의 C++ 예제 코드:

#include <windows.h>
#include <ncrypt.h>
#include <ntstatus.h>

NTSTATUS EncryptKerberosAES(
    PUCHAR key, ULONG keyLen,
    PUCHAR plaintext, ULONG ptLen,
    PUCHAR* ciphertext, ULONG* ctLen) {
    NCRYPT_ALG_HANDLE hAlg = NULL;
    BCRYPT_KEY_HANDLE hKey = NULL;
    NTSTATUS status;

    status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_AES_ALGORITHM, NULL, 0);
    if (!NT_SUCCESS(status)) return status;

    status = BCryptSetProperty(hAlg, BCRYPT_CHAINING_MODE, (PUCHAR)BCRYPT_CHAIN_MODE_CTS, sizeof(BCRYPT_CHAIN_MODE_CTS), 0);
    // Kerberos uses AES-CTS

    status = BCryptGenerateSymmetricKey(hAlg, &hKey, NULL, 0, key, keyLen);
    // ... encrypt logic with IV from Kerberos spec
    // Full code omitted for brevity

    BCryptCloseAlgorithmProvider(hAlg, 0);
    return status;
}

이 코드는 Kerberos에 특화된 CTS(Cipher Text Stealing) 모드의 AES 설정을 보여줍니다.

위임 유형과 테스트

Kerberos는 제약 위임과 비제약 위임을 지원합니다.

위임 옵션:

  • 단순: 위임 없음(서비스가 자격 증명을 더 전달하지 않음).
  • 비제약: 전체 TGT 전달(위험, 사용 중단됨).
  • 제약: S4U2Proxy — 지정된 SPN에 대한 서비스 티켓만.
  • 리소스 기반 제약: 서비스 측(Windows Server 2012+).

단일 머신 테스트: klist, SSPI의 AcquireCredentialsHandle 사용. U2U(User-to-User) 예제:

CredHandle cred;
TimeStamp expiry;
AcquireCredentialsHandle(NULL, L"Kerberos", SECPKG_CRED_OUTBOUND, NULL, NULL, NULL, NULL, &cred, &expiry);
// U2U: impersonate without KDC, direct exchange

PKINIT의 경우 AcquireCredentialsHandle에 X.509 인증서를 SECPKG_CRED_CERTIFICATE와 함께 전달합니다. Windows에서 GSS-API는 SSPI 래퍼입니다.

도메인 간 인증과 SPN

신뢰 계정(name = domain)은 도메인 간 인증을 가능하게 합니다. 도메인 A의 클라이언트가 도메인 B의 신뢰 principal에 대한 TGT를 요청합니다.

SPN에는 비밀번호가 없으며 호스트/사용자를 식별합니다. 중복 SPN은 단일 principal을 가리킵니다. 시스템은 형식으로 타입을 판단합니다: host/<fqdn>, HTTP/<fqdn>.

다중 자격 증명 관리:

  • logon과 함께 ImpersonateHandleExplicit.
  • 다중 사용자 SPN을 위한 LSA 정책.
  • 여러 키 확인을 위한 사용자 정의 GSS 수락자.

핵심 요점

  • Kerberos는 AD의 단일 사인온을 위한 GSS-API 계층입니다; 티켓은 SIDs/그룹이 포함된 PAC를 포함합니다.
  • 백엔드 간 위임에 필수적입니다; 제약 위임으로 위험 최소화.
  • SSPI 테스트: 보일러플레이트 대신 AcquireCredentialsHandle에 3-5줄만.
  • PKINIT과 U2U가 비밀번호 없는 시나리오를 확장합니다.
  • ASN.1 + AES-CTs가 프로토콜 핵심; 포트 88에서 Wireshark로 모니터링.

— Editorial Team

Advertisement 728x90

다음 읽기