<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    CVE-2021-42287 Windows域內提權漏洞原理分析

    VSole2023-02-17 10:06:21

    本文更多的是根據調試Windows Server 2003,分析漏洞成因。

    閱讀本文需要一定的Kerberos基礎知識、Windows源碼閱讀調試能力。單純的閱讀可能并不能完全理解其中的關鍵點,需要進行調試理解。

    一、背景

    漏洞編號為:CVE-2021-42278 和 CVE-2021-42287

    CVE-2021-42278:通常情況下,機器賬戶應以\$結尾,即DC$。

    但是AD域并沒有對其進行強校驗。通過建立與域控同名卻不以\$結尾的機器賬戶,即DC,對域控進行欺騙。

    • MSRC CVE-2021-42278(https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-42278
    • KB5008102 CVE-2021-42278(https://support.microsoft.com/en-us/topic/kb5008102-active-directory-security-accounts-manager-hardening-changes-cve-2021-42278-5975b463-4c95-45e1-831a-d120004e258e

    CVE-2021-42287:利用上述漏洞進行欺騙,請求到DC的TGT后,修改自身的機器賬號。之后,利用Kerberos的S4U2Self機制,請求對于“自己”(DC)的ST,但是由于此時機器名已經被修改而無法找到DC,域控將會用DC$的Key進行加密,并向其中添加請求的賬戶名的PAC。

    至此便得到了高權限ST。

    • MSRC CVE-2021-42287(https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-42287
    • KB5008102 CVE-2021-42287(https://support.microsoft.com/en-gb/topic/kb5008380-authentication-updates-cve-2021-42287-9dafac11-e0d0-4cb8-959a-143bd0201041

    二、環境配置

    域控:Windows Server 2003 Debug版

    攻擊機:Windows 7 x64 SP1

    武器化工具:https://github.com/cube0x0/noPac

    三、詳細分析

    Active Directory 目錄樹

    使用SysinternalsSuite中的ADExplorer64工具查看域內的所有機器賬戶。

    從上圖中可以很明確的看到域控的機器名為WINSRVSERVER$,之后會使用WINSRVSERVER作為機器賬戶名進行欺騙。

    攻擊準備工作

    相關準備工作不是本文重點,可以在noPac項目中學習。

    //new machine accountNewMachineAccount(argContainer, argDistinguishedName, argDomain, argDomainController, argMachineAccount, argMachinePassword, argVerbose, argRandom, credential);
    //clean spnSetMachineAccountAttribute(argContainer, argDistinguishedName, argDomain, argDomainController, "serviceprincipalname", argMachineAccount, "", false, true, argVerbose, credential);
    //set samaccountnameSetMachineAccountAttribute(argContainer, argDistinguishedName, argDomain, argDomainController, "samaccountname", argMachineAccount, argDomainController.Split('.')[0], false, false, argVerbose, credential);
    

    申請TGT

    申請TGT時是根據修改后的機器賬號WINSRVSERVER進行申請的,域控調用I_GetASTicket處理AS_REQ消息。

    首先會調用KdcNormalize獲得賬戶的相關信息包括UserInfo、ClientTicketInfo等。

    請謹記這個函數,之后的漏洞利用過程會展開分析。

    KerbErr = KdcNormalize(                ClientName,                NULL,                RequestRealm,                NULL,           // no source ticket                NameFlags | KDC_NAME_CLIENT | KDC_NAME_FOLLOW_REFERRALS | KDC_NAME_CHECK_GC,                FALSE,          // do not restrict user accounts (user2user)                &ClientReferral,                ClientRealm,                &ClientTicketInfo,                pExtendedError,                &UserHandle,                WhichFields,                0L,                &UserInfo,                &GroupMembership                );
    

    通過上面獲得的ClientTicketInfo調用BuildTicketAS生成TGT,堆棧如下:

    kd> kc#00 KDCSVC!BuildTicketAS01 KDCSVC!I_GetASTicket02 KDCSVC!KdcGetTicket03 KDCSVC!KdcAtqIoCompletion04 NTDSATQ!ATQ_CONTEXT::IOCompletion05 NTDSATQ!AtqpProcessContext06 NTDSATQ!AtqPoolThread07 kernel32!BaseThreadStart
    

    查看參數ClientTicketInfo和ClientName可以看到此次是以WINSRVSERVER的身份去申請TGT。

    kd> dt ClientTicketInfoLocal var @ 0x332fa00 Type _KDC_TICKET_INFO*0x0332fcb4   +0x000 AccountName      : _UNICODE_STRING "WINSRVSERVER"   +0x008 TrustedForest    : _UNICODE_STRING ""   +0x010 PasswordExpires  : _LARGE_INTEGER 0x7fffffff`ffffffff   +0x018 fTicketOpts      : 0x7b   +0x01c UserAccountControl : 0x80   +0x020 UserId           : 0x472   +0x024 TrustType        : 0   +0x028 TrustAttributes  : 0   +0x02c Passwords        : 0x0015eab8 _KERB_STORED_CREDENTIAL   +0x030 OldPasswords     : 0x001522d0 _KERB_STORED_CREDENTIAL   +0x034 TrustSid         : (null)   +0x038 PasswordVersion  : 1   +0x03c LockoutThreshold : 0kd> dt ClientNameLocal var @ 0x332fa04 Type KERB_PRINCIPAL_NAME*0x00084c44   +0x000 name_type        : 0n1   +0x004 name_string      : 0x000c3360 KERB_PRINCIPAL_NAME_name_string_skd> dx -id 0,0,89c47a68 -r1 ((KDCSVC!KERB_PRINCIPAL_NAME_name_string_s *)0xc3360)((KDCSVC!KERB_PRINCIPAL_NAME_name_string_s *)0xc3360)                 : 0xc3360 [Type: KERB_PRINCIPAL_NAME_name_string_s *]    [+0x000] next             : 0x0 [Type: KERB_PRINCIPAL_NAME_name_string_s *]    [+0x004] value            : 0xb45d8 : "WINSRVSERVER" [Type: char *]
    

    上述函數工作完成后,查看生成的Ticket,即TGT。

    kd> dt KERB_ENCRYPTED_TICKET 0x332fabcKDCSVC!KERB_ENCRYPTED_TICKET   +0x000 bit_mask         : 0xc0   +0x000 o                : [1]  "???"   +0x004 flags            : tagASN1bitstring_t   +0x00c key              : KERB_ENCRYPTION_KEY   +0x018 client_realm     : 0x000c5098  "WINTESTYU03.COM"   +0x01c client_name      : KERB_PRINCIPAL_NAME   +0x024 transited        : KERB_TRANSITED_ENCODING   +0x030 authtime         : tagASN1generalizedtime_t   +0x03e starttime        : tagASN1generalizedtime_t   +0x04c endtime          : tagASN1generalizedtime_t   +0x05a renew_until      : tagASN1generalizedtime_t   +0x068 client_addresses : (null)   +0x06c authorization_data : (null)
    

    此時還沒有向其中添加PAC,會通過之前獲得的UserInfo調用KdcGetPacAuthData生成所需的PAC。

    此時的PAC為WINSRVSERVER的PAC,屬于正常流程。

    kd> dt AuthorizationDataLocal var @ 0x332f9d0 Type PKERB_AUTHORIZATION_DATA_s   +0x000 next             : (null)   +0x004 value            : PKERB_AUTHORIZATION_DATA_Seqkd> dx -id 0,0,89c47a68 -r1 (*((KDCSVC!PKERB_AUTHORIZATION_DATA_Seq *)0x332f9d4))(*((KDCSVC!PKERB_AUTHORIZATION_DATA_Seq *)0x332f9d4))                 [Type: PKERB_AUTHORIZATION_DATA_Seq]    [+0x000] auth_data_type   : 128 [Type: long]    [+0x004] auth_data        [Type: tagASN1octetstring_t]kd> dx -id 0,0,89c47a68 -r1 (*((KDCSVC!tagASN1octetstring_t *)0x332f9d8))(*((KDCSVC!tagASN1octetstring_t *)0x332f9d8))                 [Type: tagASN1octetstring_t]    [+0x000] length           : 0x260 [Type: unsigned long]    [+0x004] value            : 0x16c828 : 0x4 [Type: unsigned char *]kd> db 0x16c828 l 2600016c828  04 00 00 00 00 00 00 00-01 00 00 00 c0 01 00 00  ................0016c838  48 00 00 00 00 00 00 00-0a 00 00 00 22 00 00 00  H..........."...0016c848  08 02 00 00 00 00 00 00-06 00 00 00 14 00 00 00  ................0016c858  30 02 00 00 00 00 00 00-07 00 00 00 14 00 00 00  0...............0016c868  48 02 00 00 00 00 00 00-01 10 08 00 cc cc cc cc  H...............0016c878  b0 01 00 00 00 00 00 00-00 00 02 00 c2 dd c3 d9  ................0016c888  0f f7 d7 01 ff ff ff ff-ff ff ff 7f ff ff ff ff  ................0016c898  ff ff ff 7f 56 b9 d8 d7-0f f7 d7 01 56 79 42 02  ....V.......VyB.0016c8a8  d9 f7 d7 01 ff ff ff ff-ff ff ff 7f 18 00 18 00  ................0016c8b8  04 00 02 00 00 00 00 00-08 00 02 00 00 00 00 00  ................0016c8c8  0c 00 02 00 00 00 00 00-10 00 02 00 00 00 00 00  ................0016c8d8  14 00 02 00 00 00 00 00-18 00 02 00 01 00 00 00  ................0016c8e8  72 04 00 00 03 02 00 00-01 00 00 00 1c 00 02 00  r...............0016c8f8  20 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ...............0016c908  00 00 00 00 18 00 1a 00-20 00 02 00 16 00 18 00  ........ .......0016c918  24 00 02 00 28 00 02 00-00 00 00 00 00 00 00 00  $...(...........0016c928  80 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................0016c938  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................0016c948  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................0016c958  00 00 00 00 0c 00 00 00-00 00 00 00 0c 00 00 00  ................0016c968  57 00 49 00 4e 00 53 00-52 00 56 00 53 00 45 00  W.I.N.S.R.V.S.E.0016c978  52 00 56 00 45 00 52 00-00 00 00 00 00 00 00 00  R.V.E.R.........0016c988  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................0016c998  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................0016c9a8  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................0016c9b8  00 00 00 00 01 00 00 00-03 02 00 00 07 00 00 00  ................0016c9c8  0d 00 00 00 00 00 00 00-0c 00 00 00 57 00 49 00  ............W.I.0016c9d8  4e 00 53 00 52 00 56 00-53 00 45 00 52 00 56 00  N.S.R.V.S.E.R.V.0016c9e8  45 00 52 00 0c 00 00 00-00 00 00 00 0b 00 00 00  E.R.............0016c9f8  52 00 45 00 4e 00 50 00-45 00 4e 00 47 00 59 00  W.I.N.T.E.S.T.Y.0016ca08  55 00 30 00 33 00 00 00-04 00 00 00 01 04 00 00  U.0.3...........0016ca18  00 00 00 05 15 00 00 00-db ac e2 f8 a5 b2 f3 d1  ................0016ca28  a1 c4 3e 10 00 00 00 00-00 b4 a3 e5 0f f7 d7 01  ..>.............0016ca38  18 00 57 00 49 00 4e 00-53 00 52 00 56 00 53 00  ..W.I.N.S.R.V.S.0016ca48  45 00 52 00 56 00 45 00-52 00 00 00 00 00 00 00  E.R.V.E.R.......0016ca58  76 ff ff ff c1 fc e6 ad-46 30 3f 05 5e ed 74 c0  v.......F0?.^.t.0016ca68  20 7d c9 54 00 00 00 00-76 ff ff ff 42 e1 22 e3   }.T....v...B.".0016ca78  3b 44 cd ee b7 d7 50 5f-2d f9 44 ab 00 00 00 00  ;D....P_-.D.....
    

    之后便是將PAC放入TGT中,將其打包并使用krbtgt密鑰進行加密,通過AS_REP消息傳遞回Client。

    關鍵代碼如下,不再展開分析。

    KerbErr = BuildReply(            &ClientTicketInfo,            (Nonce != 0) ? Nonce : RequestBody->nonce,            &Ticket.server_name,            Ticket.realm,            ((RequestBody->bit_mask & addresses_present) != 0) ? RequestBody->addresses : NULL,            &Ticket,            &ReplyBody            );... KerbErr = KerbPackTicket(            &Ticket,            ServerKey,            ServiceTicketInfo.PasswordVersion,            &Reply.ticket            );...KerbErr = KerbPackKdcReplyBody(        &ReplyBody,        (EncryptionKey.keyvalue.value != NULL) ? &EncryptionKey : ClientKey,        (EncryptionKey.keyvalue.value != NULL) ? KERB_NO_KEY_VERSION : ClientTicketInfo.PasswordVersion,        KERB_TGS_REP_SALT,        KERB_ENCRYPTED_AS_REPLY_PDU,        &Reply.encrypted_part        );
    

    還原機器賬戶名

    還原機器賬戶名的目的是使得域控處理TGS_REQ請求的時候,找不到賬戶從而是用自己的Key加密。

    //undo samaccountname changeSetMachineAccountAttribute(argContainer, argDistinguishedName, argDomain, argDomainController, "samaccountname", argMachineAccount, argMachineAccount, false, false, argVerbose, credential);
    

    申請ST

    Client向域控申請WINSRVSERVER的服務票據,域控在HandleTGSRequest函數中處理TGS_REQ請求。

    首先通過KerbFindPreAuthDataEntry獲取TGS_REQ中包含的ApRequest。

    ApRequest = KerbFindPreAuthDataEntry(                KRB5_PADATA_TGS_REQ,                RequestMessage->KERB_KDC_REQUEST_preauth_data                );
    

    之后便是解析獲得的APRequest獲得解密后的TGT。

    //驗證請求。這包括對AP請求進行解碼,找到合適的密鑰來解密票據,并檢查票據。KerbErr = KdcVerifyKdcRequest(            ApRequest->preauth_data.value,            ApRequest->preauth_data.length,            ClientAddress,            TRUE,                           // this is a kdc request            &UnmarshalledApRequest,            &UnmarshalledAuthenticator,            &SourceEncryptPart,            &ReplyKey,            &SourceTicketKey,            &ServerTicketInfo,            &UseSubKey,            pExtendedError            );
    

    KdcVerifyKdcRequest做了以下幾件事情:

    KdcVerifyKdcRequest

    解包ApRequest ---- KerbUnpackApRequest

    根據其中的服務名(kbrtgt)獲取服務的相關信息 ---- KdcNormalize

    通過相關信息找到服務的Hash ---- KerbGetKeyFromList

    解密TGT --- KerbCheckTicket

    獲得解密后的TGT --- KerbVerifyTicket

    用TGT中的Key(key為Client與KDC通信所需要的LogonSessionKey)解密獲得Authenticator --- KerbUnpackAuthenticator

    ……(校驗檢查之類的)

    查看這個函數的結果,獲得了傳過來的明文TGT和krbtgt的相關服務信息。

    kd> dt ServerTicketInfoLocal var @ 0x327fc48 Type _KDC_TICKET_INFO   +0x000 AccountName      : _UNICODE_STRING "krbtgt"   +0x008 TrustedForest    : _UNICODE_STRING ""   +0x010 PasswordExpires  : _LARGE_INTEGER 0x7fffffff`ffffffff   +0x018 fTicketOpts      : 0x7b   +0x01c UserAccountControl : 0x11   +0x020 UserId           : 0x1f6   +0x024 TrustType        : 0   +0x028 TrustAttributes  : 0   +0x02c Passwords        : 0x00084bf0 _KERB_STORED_CREDENTIAL   +0x030 OldPasswords     : 0x000c4010 _KERB_STORED_CREDENTIAL   +0x034 TrustSid         : (null)   +0x038 PasswordVersion  : 2   +0x03c LockoutThreshold : 0
    kd> dt SourceEncryptPartLocal var @ 0x327fdd0 Type KERB_ENCRYPTED_TICKET*0x000fcf90   +0x000 bit_mask         : 0xd0   +0x000 o                : [1]  "???"   +0x004 flags            : tagASN1bitstring_t   +0x00c key              : KERB_ENCRYPTION_KEY   +0x018 client_realm     : 0x00106a18  "WINTESTYU03.COM"   +0x01c client_name      : KERB_PRINCIPAL_NAME   +0x024 transited        : KERB_TRANSITED_ENCODING   +0x030 authtime         : tagASN1generalizedtime_t   +0x03e starttime        : tagASN1generalizedtime_t   +0x04c endtime          : tagASN1generalizedtime_t   +0x05a renew_until      : tagASN1generalizedtime_t   +0x068 client_addresses : (null)   +0x06c authorization_data : 0x000c3370 PKERB_AUTHORIZATION_DATA_s
    kd> db authorization_data l 2760017f168  30 82 02 72 30 82 02 6e-a0 04 02 02 00 80 a1 82  0..r0..n........0017f178  02 64 04 82 02 60 04 00-00 00 00 00 00 00 01 00  .d...`..........0017f188  00 00 c0 01 00 00 48 00-00 00 00 00 00 00 0a 00  ......H.........0017f198  00 00 22 00 00 00 08 02-00 00 00 00 00 00 06 00  ..".............0017f1a8  00 00 14 00 00 00 30 02-00 00 00 00 00 00 07 00  ......0.........0017f1b8  00 00 14 00 00 00 48 02-00 00 00 00 00 00 01 10  ......H.........0017f1c8  08 00 cc cc cc cc b0 01-00 00 00 00 00 00 00 00  ................0017f1d8  02 00 02 4e 81 c8 1c f7-d7 01 ff ff ff ff ff ff  ...N............0017f1e8  ff 7f ff ff ff ff ff ff-ff 7f 56 b9 d8 d7 0f f7  ..........V.....0017f1f8  d7 01 56 79 42 02 d9 f7-d7 01 ff ff ff ff ff ff  ..VyB...........0017f208  ff 7f 18 00 18 00 04 00-02 00 00 00 00 00 08 00  ................0017f218  02 00 00 00 00 00 0c 00-02 00 00 00 00 00 10 00  ................0017f228  02 00 00 00 00 00 14 00-02 00 00 00 00 00 18 00  ................0017f238  02 00 08 00 00 00 72 04-00 00 03 02 00 00 01 00  ......r.........0017f248  00 00 1c 00 02 00 20 00-00 00 00 00 00 00 00 00  ...... .........0017f258  00 00 00 00 00 00 00 00-00 00 18 00 1a 00 20 00  .............. .0017f268  02 00 16 00 18 00 24 00-02 00 28 00 02 00 00 00  ......$...(.....0017f278  00 00 00 00 00 00 80 00-00 00 00 00 00 00 00 00  ................0017f288  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................0017f298  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................0017f2a8  00 00 00 00 00 00 00 00-00 00 0c 00 00 00 00 00  ................0017f2b8  00 00 0c 00 00 00 57 00-49 00 4e 00 53 00 52 00  ......W.I.N.S.R.0017f2c8  56 00 53 00 45 00 52 00-56 00 45 00 52 00 00 00  V.S.E.R.V.E.R...0017f2d8  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................0017f2e8  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................0017f2f8  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................0017f308  00 00 00 00 00 00 00 00-00 00 01 00 00 00 03 02  ................0017f318  00 00 07 00 00 00 0d 00-00 00 00 00 00 00 0c 00  ................0017f328  00 00 57 00 49 00 4e 00-53 00 52 00 56 00 53 00  ..W.I.N.S.R.V.S.0017f338  45 00 52 00 56 00 45 00-52 00 0c 00 00 00 00 00  E.R.V.E.R.......0017f348  00 00 0b 00 00 00 52 00-45 00 4e 00 50 00 45 00  ......W.I.N.T.E.0017f358  4e 00 47 00 59 00 55 00-30 00 33 00 00 00 04 00  S.T.Y.U.0.3.....0017f368  00 00 01 04 00 00 00 00-00 05 15 00 00 00 db ac  ................0017f378  e2 f8 a5 b2 f3 d1 a1 c4-3e 10 00 00 00 00 00 06  ........>.......0017f388  7d ec a5 f7 d7 01 18 00-57 00 49 00 4e 00 53 00  }.......W.I.N.S.0017f398  52 00 56 00 53 00 45 00-52 00 56 00 45 00 52 00  R.V.S.E.R.V.E.R.0017f3a8  00 00 00 00 00 00 76 ff-ff ff 51 30 b4 c6 f1 8c  ......v...Q0....0017f3b8  bf 3d 01 2f 7c 3d 75 9b-9d 8d 00 00 00 00 76 ff  .=./|=u.......v.0017f3c8  ff ff 5a 8c df 90 88 38-ec 5d 6c 61 b8 46 bd bf  ..Z....8.]la.F..0017f3d8  99 5c 00 00 00 00                                .\....
    

    之后會獲取請求的相關信息:

    • 在REQUEST_BODY中獲得ServerName
    • 在TGT中獲得cname和crealm
    KerbErr = KerbConvertPrincipalNameToKdcName(            &ServerName,            &RequestBody->KERB_KDC_REQUEST_BODY_server_name            );
    KerbErr = KerbConvertPrincipalNameToKdcName(               &SourceClientName,               &SourceEncryptPart->client_name               );
    KerbErr = KerbConvertRealmToUnicodeString(               &SourceClientRealm,               &SourceEncryptPart->client_realm               );
    

    內容分別如下:

    kd> dt ServerNameLocal var @ 0x327fdd8 Type _KERB_INTERNAL_NAME*0x00117610   +0x000 NameType         : 0n1   +0x002 NameCount        : 1   +0x004 Names            : [1] _UNICODE_STRING "WINSRVSERVER"
    kd> dt SourceClientNameLocal var @ 0x327fdd4 Type _KERB_INTERNAL_NAME*0x0017f3e8   +0x000 NameType         : 0n1   +0x002 NameCount        : 1   +0x004 Names            : [1] _UNICODE_STRING "WINSRVSERVER"
    kd> dt SourceClientRealmLocal var @ 0x327fdc4 Type _UNICODE_STRING "WINTESTYU03.COM"   +0x000 Length           : 0x1e   +0x002 MaximumLength    : 0x20   +0x004 Buffer           : 0x00153578  "WINTESTYU03.COM"
    

    之后會調用KdcFindS4UClientAndRealm來獲取PA_DATA_FOR_USER這個結構中的內容。

    KdcFindS4UClientAndRealm函數會解析PaList并將其轉換成KERB_PA_FOR_USER結構,目前需要注意的便是其中的userName是我們要請求的高權限用戶的用戶名Administrator。

    kd> dt S4URequestLocal var @ 0x327f9b0 Type KERB_PA_FOR_USER*0x0012aaa8   +0x000 bit_mask         : 0   +0x000 o                : [1]  ""   +0x004 userName         : KERB_PRINCIPAL_NAME   +0x00c userRealm        : 0x0012abf0  "WINTESTYU03.COM"   +0x010 cksum            : KERB_CHECKSUM   +0x01c authentication_package : 0x000fca30  "Kerberos"   +0x020 authorization_data : tagASN1octetstring_tkd> dx -id 0,0,89de1678 -r1 (*((KDCSVC!KERB_PRINCIPAL_NAME *)0x12aaac))(*((KDCSVC!KERB_PRINCIPAL_NAME *)0x12aaac))                 [Type: KERB_PRINCIPAL_NAME]    [+0x000] name_type        : 10 [Type: long]    [+0x004] name_string      : 0x82c98 [Type: KERB_PRINCIPAL_NAME_name_string_s *]kd> dx -id 0,0,89de1678 -r1 ((KDCSVC!KERB_PRINCIPAL_NAME_name_string_s *)0x82c98)((KDCSVC!KERB_PRINCIPAL_NAME_name_string_s *)0x82c98)                 : 0x82c98 [Type: KERB_PRINCIPAL_NAME_name_string_s *]    [+0x000] next             : 0x0 [Type: KERB_PRINCIPAL_NAME_name_string_s *]    [+0x004] value            : 0x159c88 : "wintestServer" [Type: char *]
    

    之后會通過KdcNormalize獲取我們自身WINSRVSERVER的相關信息。

    其中的關鍵調用如下:

    KdcNormalize

    • KdcGetTicketInfo
    • SamIGetUserLogonInformation2 (WINSRVSERVER)
    • SamIGetUserLogonInformation2 (WINSRVSERVER$)

    對于漏洞的利用便發生在這個函數中,并且利用了兩次。

    第一次實現了將申請的用戶轉換為域控上的Administrator。

    第二次實現了將申請的服務轉換成WINSRVSERVER$。

    下面將詳細分析漏洞點。

    KERBERRKdcNormalize(    IN PKERB_INTERNAL_NAME PrincipalName,    IN OPTIONAL PUNICODE_STRING PrincipalRealm,    IN OPTIONAL PUNICODE_STRING RequestRealm,    IN OPTIONAL PUNICODE_STRING  TgtClientRealm,    IN ULONG NameFlags,    IN BOOLEAN bRestrictUserAccounts,    OUT PBOOLEAN Referral,    OUT PUNICODE_STRING RealmName,    OUT PKDC_TICKET_INFO TicketInfo,    OUT PKERB_EXT_ERROR  pExtendedError,    OUT OPTIONAL SAMPR_HANDLE * UserHandle,    IN OPTIONAL ULONG WhichFields,    IN OPTIONAL ULONG ExtendedFields,    OUT OPTIONAL PUSER_INTERNAL6_INFORMATION * UserInfo,    OUT OPTIONAL PSID_AND_ATTRIBUTES_LIST GroupMembership    )
    

    調用KdcNormalize時的相關參數中最重要的就是SourceCName。

    因為我們是在利用S4U2Self協議請求自身的ST,所以SourceCName也就是自身的名字WINSRVSERVER。

    kd> dt SourceCNameLocal var @ 0x327f9e0 Type _KERB_INTERNAL_NAME*0x0016e920   +0x000 NameType         : 0n1   +0x002 NameCount        : 1   +0x004 Names            : [1] _UNICODE_STRING "WINSRVSERVER"
    

    之后在CheckSam條件中會調用到KdcGetTicketInfo來獲取用戶WINSRVSERVER的相關信息。

    KerbErr = KdcGetTicketInfo(            &OutputPrincipal,            0,                  // no lookup flags means sam name            bRestrictUserAccounts,            NULL,               // no principal name            NULL,               // no realm name,            TicketInfo,            pExtendedError,            UserHandle,            WhichFields,            ExtendedFields,            UserInfo,            GroupMembership            );
    

    此時OutputPrincipal的值為WINSRVSERVER,即我們自己的機器名DC,目前仍一切正常。

    kd> dt OutputPrincipalLocal var @ 0x327f928 Type _UNICODE_STRING "WINSRVSERVER"   +0x000 Length           : 0x18   +0x002 MaximumLength    : 0x1a   +0x004 Buffer           : 0x0016e92c  "WINSRVSERVER"
    

    之后會調用SamIGetUserLogonInformation2在SAM中查找對應的賬戶信息,但由于此時已經將創建的機器賬號還原,所以并不能找到對應的賬號,該函數會返回錯誤。

    但是系統并不會直接提示找不到賬號,而是會在其后面添加'$'符號,將其作為機器賬號再次查找。

    Status = SamIGetUserLogonInformation2(            GlobalAccountDomainHandle,            LookupFlags,            UserName,            WhichFields,            ExtendedFields,            &UserInfo,            &LocalMembership,            &LocalUserHandle            );
    //// WASBUG: For now, if we couldn't find the account try again// with a '$' at the end (if there wasn't one already)//
    if (((Status == STATUS_NOT_FOUND) ||   (Status == STATUS_NO_SUCH_USER)) &&   (!IsValidGuid) &&   ((LookupFlags & ~SAM_NO_MEMBERSHIPS) == 0) &&   (UserName->Length >= sizeof(WCHAR)) &&   (UserName->Buffer[UserName->Length/sizeof(WCHAR)-1] != L'$')){   Status = KerbDuplicateString(               &TempString,               UserName               );   if (!NT_SUCCESS(Status))   {         KerbErr = KRB_ERR_GENERIC;         goto Cleanup;   }   DsysAssert(TempString.MaximumLength >= TempString.Length + sizeof(WCHAR));   TempString.Buffer[TempString.Length/sizeof(WCHAR)] = L'$';   TempString.Length += sizeof(WCHAR);
       D_DebugLog((DEB_TRACE, "Account not found ,trying machine account %wZ",         &TempString ));
       Status = SamIGetUserLogonInformation2(               GlobalAccountDomainHandle,               LookupFlags,               &TempString,               WhichFields,               ExtendedFields,               &UserInfo,               &LocalMembership,               &LocalUserHandle               );}
    

    通過調試信息可以清晰的看到查找到的用戶信息不再是WINSRVSERVER而是變成了WINSRVSERVER$也就是域控對應的機器賬號UserId = 0x3ed。

    至此便完成了對于域控的欺騙,之后就是頒發ST的過程。

    kd> dt UserInfoLocal var @ 0x327f684 Type _USER_INTERNAL6_INFORMATION*0x001602e0   +0x000 I1               : _USER_ALL_INFORMATION   +0x0c8 LastBadPasswordTime : _LARGE_INTEGER 0x0   +0x0d0 ExtendedFields   : 0x18   +0x0d4 UPNDefaulted     : 0 ''   +0x0d8 UPN              : _UNICODE_STRING ""   +0x0e0 A2D2List         : (null)   +0x0e4 RegisteredSPNs   : (null)   +0x0e8 KeyVersionNumber : 5   +0x0ec LockoutThreshold : 0kd> dx -id 0,0,89de1678 -r1 (*((KDCSVC!_USER_ALL_INFORMATION *)0x1602e0))(*((KDCSVC!_USER_ALL_INFORMATION *)0x1602e0))                 [Type: _USER_ALL_INFORMATION]    [+0x000] LastLogon        : {0} [Type: _LARGE_INTEGER]    [+0x008] LastLogoff       : {0} [Type: _LARGE_INTEGER]    [+0x010] PasswordLastSet  : {0} [Type: _LARGE_INTEGER]    [+0x018] AccountExpires   : {0} [Type: _LARGE_INTEGER]    [+0x020] PasswordCanChange : {0} [Type: _LARGE_INTEGER]    [+0x028] PasswordMustChange : {9223372036854775807} [Type: _LARGE_INTEGER]    [+0x030] UserName         : "WINSRVSERVER$" [Type: _UNICODE_STRING]    [+0x038] FullName         : "" [Type: _UNICODE_STRING]    [+0x040] HomeDirectory    : "" [Type: _UNICODE_STRING]    [+0x048] HomeDirectoryDrive : "" [Type: _UNICODE_STRING]    [+0x050] ScriptPath       : "" [Type: _UNICODE_STRING]    [+0x058] ProfilePath      : "" [Type: _UNICODE_STRING]    [+0x060] AdminComment     : "" [Type: _UNICODE_STRING]    [+0x068] WorkStations     : "" [Type: _UNICODE_STRING]    [+0x070] UserComment      : "" [Type: _UNICODE_STRING]    [+0x078] Parameters       : "" [Type: _UNICODE_STRING]    [+0x080] LmPassword       : "" [Type: _UNICODE_STRING]    [+0x088] NtPassword       : ".?廢??樾??" [Type: _UNICODE_STRING]    [+0x090] PrivateData      : "." [Type: _UNICODE_STRING]    [+0x098] SecurityDescriptor [Type: _SR_SECURITY_DESCRIPTOR]    [+0x0a0] UserId           : 0x3ed [Type: unsigned long]    [+0x0a4] PrimaryGroupId   : 0x0 [Type: unsigned long]    [+0x0a8] UserAccountControl : 0x2100 [Type: unsigned long]    [+0x0ac] WhichFields      : 0x27120005 [Type: unsigned long]    [+0x0b0] LogonHours       [Type: _LOGON_HOURS]    [+0x0b8] BadPasswordCount : 0x0 [Type: unsigned short]    [+0x0ba] LogonCount       : 0x0 [Type: unsigned short]    [+0x0bc] CountryCode      : 0x0 [Type: unsigned short]    [+0x0be] CodePage         : 0x0 [Type: unsigned short]    [+0x0c0] LmPasswordPresent : 0x0 [Type: unsigned char]    [+0x0c1] NtPasswordPresent : 0x1 [Type: unsigned char]    [+0x0c2] PasswordExpired  : 0x0 [Type: unsigned char]    [+0x0c3] PrivateDataSensitive : 0x1 [Type: unsigned char]
    

    至此,我們成功的請求的用戶WINSRVSERVER偽裝成了域控自身WINSRVSERVER$。

    之后再I_GetTGSTicket中,為了獲得WINSRVSERVER這個服務的相關信息,又再次調用KdcNormalize,其中的流程與上述基本相同,這也就是漏洞的第二次利用。成功的將請求的服務從WINSRVSERVER偽裝成WINSRVSERVER$。

    完成上述的兩次利用后,其他過程都顯得不再重要,但有一點仍然需要留意,便是關于PAC的問題。

    之前TGT中的PAC主體為WINSRVSERVER,又是如何切換為申請的Administrator的,對于之前的PAC又是如何處理的。

    下面將對這兩點進行分析。

    S4U2self協議的意義是 服務器模擬用戶向域控申請針對自身的ST,即給予用戶訪問服務的權限,所以返回的ST中應該插入的是用戶的PAC,即下圖中的(2)(3)兩個過程。

    而上一步中我們申請的TGT中的PAC,是 不在下圖中的Service1向KDC認證的過程 中頒發的PAC。

    明白了這點也就明白了為什么PAC會被替換。

    以下堆棧及函數完成了生成ST并向其中添加了用戶PAC。

    kd> kb # ChildEBP RetAddr      Args to Child             00 0327f9ac 61ba4b9b     0327fb48 0327fea8 0327fea0 KDCSVC!I_GetTGSTicket+0x313  01 0327fe44 61ba1901     00160958 000c5020 0327feb8 KDCSVC!HandleTGSRequest+0x77f  02 0327fee0 61bae51e     0327ff30 00160958 00160968 KDCSVC!KdcGetTicket+0x25e   03 0327ff34 70d173e6     00160940 00000562 00000000 KDCSVC!KdcAtqIoCompletion+0x15f 04 0327ff58 70d18808     00000562 00000000 00084df4 NTDSATQ!ATQ_CONTEXT::IOCompletion+0x5305 0327ff84 70d189f2     00000000 00000562 00084df4 NTDSATQ!AtqpProcessContext+0x3c2 06 0327ffb8 77e41be7     abcdef01 00000000 00000000 NTDSATQ!AtqPoolThread+0xbd   07 0327ffec 00000000     70d18935 abcdef01 00000000 kernel32!BaseThreadStart+0x34
    KerbErr = KdcGetS4UTicketInfo(                  S4UTicketInfo,                  &OldServiceTicketInfo, // tgt's account info.                  &S4UClientUserInfo,                  &S4UClientGroupMembership,                  pExtendedError                  );...KerbErr = BuildTicketTGS(            ServiceTicketInfo,            RequestBody,            SourceTicket,            Referral,            S4UTicketInfo,            CommonEType,            &NewTicket,            pExtendedError            ); ...        KerbErr = KdcInsertInitialS4UAuthorizationData(               &EncryptedTicket,               pExtendedError,               S4UTicketInfo,               S4UClientUserInfo,               &S4UClientGroupMembership,               ((ServiceTicketInfo->UserId != DOMAIN_USER_RID_KRBTGT) &&                     ((ServiceTicketInfo->UserAccountControl & USER_INTERDOMAIN_TRUST_ACCOUNT) == 0)),               pKeyToUse               );
    

    對于原本的TGT中的PAC并沒有做任何處理,直接將其丟棄了。

    string
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    如果你不是 Java8 的釘子戶,你應該早就發現了:String 類的源碼已經由 char[] 優化為了 byte[] 來存儲字符串內容,為什么要這樣做呢? 開門見山地說,從 char[] 到 byte[],最主要的目的是為了節省字符串占用的內存 。內存占用減少帶來的另外一個好處,就是 GC 次數也會減少。
    Adobe已經發布了一個名為Stringlifier的開源工具,該工具允許用戶識別任何純文本中隨機生成的字符串,該工具可用于清理日志。Stringlifier工具是用Python編寫的,它使用機器學習來識別插入普通文本中的隨機字符序列。開源工具可用于出于多種目的分析日志,例如研究意外暴露的憑證。Stringlifier能夠在源代碼或配置文件中查找API密鑰,哈希,隨機生成的字符串,包括密碼,日志。Adobe在Github上發布的描述中寫道。
    介紹Runtime 是一系列采用 C++ 語言編寫的功能方法,它實現了大量 JavaScript 運行期間需要的 native 功能。本文分析 Runtime_StringToArray 方法的源碼和重要數據結構,講解 Runtime_StringToArray 方法的觸發條件。
    介紹Runtime 是一系列采用 C++ 語言編寫的功能方法,它實現了大量 JavaScript 運行期間需要的 native 功能。
    通過common-collection相關gadget,想辦法調用org.mozilla.classfile.DefiningClassLoader這個類去加載字節碼。然后通過T3協議的反序列化漏洞發送給待攻擊weblogic服務器。
    舉個例子:但是對于64位的來說 ROPgadget預設的長度是不夠的。所以,我們可以使用ROPgadget --binary ./b --depth 100來加深他的搜索深度。2利用_libc_csu_init制造ROP常規方法我們前面說的利用ROPgadget來尋找,大多都是找到直接設置某個寄存器的rop,當然也可以使用--ropchain這個參數。
    一般情況下類與類之間是相互獨立的,內部類的意思就是打破這種獨立思想,讓一個類成為另一個類的內部信息,和成員變量、成員方法同等級別。「內部類的好處:」把一個類寫在外面和寫在里面最終達到的結果都一樣,那我們為什么還要使用內部類,豈不是多此一舉嗎?
    當被問及網絡間諜是否成功時,愛德華·斯金格表示,他非常有信心地確信,除了國防學院本身,沒有任何其他危害行為。斯金格接受采訪時透露,本次攻擊看起來不像是一次暴力攻擊,但有代價。國防學院立即意識到它可能已成為敵對國家在灰色地帶式網絡攻擊中的目標的可能性。官方迅速采取了行動,對更廣泛的國防部IT網絡沒有影響。
    java安全-02RMI
    2022-03-25 15:35:13
    基礎知識動態代理反射攻擊方式注冊端攻擊服務端java -cp .\ysoserial-master-8eb5
    MISC中常用python腳本
    2021-09-20 20:26:46
    MISC中常用python腳本總結
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类