Salvataggio di una sandbox di un linguaggio completo di turing isolato?

4

Gli stati della documentazione sulla solidità di Ethereum:

The Ethereum Virtual Machine or EVM is the runtime environment for smart contracts in Ethereum. It is not only sandboxed but actually completely isolated, which means that code running inside the EVM has no access to network, filesystem or other processes.

È sufficiente limitare l'accesso alla rete, al filesystem e ad altri processi in modo tale da impedire che una lingua completa di Turing venga salvata dalla sandbox?

    
posta Steve Ellis 22.03.2016 - 17:36
fonte

2 risposte

4

La fuga dalle sandbox non viene eseguita nelle lingue ma nelle implementazioni. Ho visto le seguenti implementazioni VM:

Ogni implementazione si basa sulla correttezza del compilatore / interprete e sulla correttezza dell'implementazione stessa. Un utente malintenzionato vorrebbe sfuggire alla VM di Ethereum e per ottenere ciò, dovrà sfruttare una combinazione di errori nelle librerie di compilatore / interprete / standard e nell'implementazione stessa. Pur essendo un compito difficile, non è affatto impossibile (molto probabilmente, coinvolgendo zero giorni). Direi che il libethereum è il più vulnerabile implementato in C ++ ...

Tra qualche anno, con l'accettazione di Ethereum, emergerà un'implementazione dominante che faciliterà il compito dell'aggressore ( webthree- ombrello ha il compilatore canonico di Solidità).

Per fornire una difesa approfondita da tali attacchi, si consiglia di eseguire sandbox Ethereum all'interno di VM generiche. Anche in questo caso, il metodo principale di prevenzione degli attacchi IMHO si baserà sul controllo dei contratti manualmente :

  1. Vai a EtherChain.org , ottieni il codice sorgente del contratto.
  2. Ottieni il bytecode che ti viene nutrito. Smontalo da solo.
  3. Compilare il codice e confrontarlo con il codice byte ricevuto. (Vedi questa domanda su Ethereum SE per dettagli - risulta essere una PITA).
  4. ???
  5. Evita le perdite.
  6. Inizia la tonalità e piangi se vedi un contratto malevolo ...

Nota: l'esistenza di due lingue complete di Turing (Solidità e Serpente) e dozzine di versioni del compilatore (oltre 60 versioni precedenti di Solidità) rende più difficile per il difensore rilevare i contratti malevoli.

    
risposta data 23.03.2016 - 09:31
fonte
2

No, no non lo è ed è piuttosto complesso da prevenire.

In genere, Sandbox associa le API interne e esegue il codice a un livello più basso nell'anello 3. Parliamo dell'API dei file per cominciare. Se conosci i linguaggi di programmazione di livello inferiore come C, C ++ e così via, conoscerai l'API ReadFile . Quindi, esaminiamo ReadFile in un disassemblaggio.

ReadFile si trova come in EAT (Export Address table) in Kernel32.

KERNEL32.ReadFile - FF 25 8803D674        - jmp dword ptr [KERNEL32.PssWalkSnapshot+9588] { ->KERNELBASE.ReadFile }

Quindi, passa a KernelBase.dll su un ReadFile. Non preoccuparti di non comprendere tutti gli opcode ma solo di essere interessati ai CALL.

KERNELBASE.ReadFile - 8B FF                 - mov edi,edi
KERNELBASE.ReadFile+2- 55                    - push ebp
KERNELBASE.ReadFile+3- 8B EC                 - mov ebp,esp
KERNELBASE.ReadFile+5- 6A FE                 - push -02 { 254 }
KERNELBASE.ReadFile+7- 68 A806D576           - push KERNELBASE.ReadFile+B8 { [FFFFFFFE] }
KERNELBASE.ReadFile+C- 68 5098D576           - push KERNELBASE.OutputDebugStringA+C0 { [8B55FF8B] }
KERNELBASE.ReadFile+11- 64 A1 00000000        - mov eax,fs:[00000000] { 0 }
KERNELBASE.ReadFile+17- 50                    - push eax
KERNELBASE.ReadFile+18- 83 EC 18              - sub esp,18 { 24 }
KERNELBASE.ReadFile+1B- 53                    - push ebx
KERNELBASE.ReadFile+1C- 56                    - push esi
KERNELBASE.ReadFile+1D- 57                    - push edi
KERNELBASE.ReadFile+1E- A1 683BE076           - mov eax,[KERNELBASE.dll+C3B68] { [1EB677D9] }
KERNELBASE.ReadFile+23- 31 45 F8              - xor [ebp-08],eax
KERNELBASE.ReadFile+26- 33 C5                 - xor eax,ebp
KERNELBASE.ReadFile+28- 50                    - push eax
KERNELBASE.ReadFile+29- 8D 45 F0              - lea eax,[ebp-10]
KERNELBASE.ReadFile+2C- 64 A3 00000000        - mov fs:[00000000],eax { 0 }
KERNELBASE.ReadFile+32- 89 65 E8              - mov [ebp-18],esp
KERNELBASE.ReadFile+35- C7 45 E0 00000000     - mov [ebp-20],00000000 { 0 }
KERNELBASE.ReadFile+3C- C7 45 E4 00000000     - mov [ebp-1C],00000000 { 0 }
KERNELBASE.ReadFile+43- 8B 75 14              - mov esi,[ebp+14]
KERNELBASE.ReadFile+46- 85 F6                 - test esi,esi
KERNELBASE.ReadFile+48- 74 06                 - je KERNELBASE.ReadFile+50
KERNELBASE.ReadFile+4A- C7 06 00000000        - mov [esi],00000000 { 0 }
KERNELBASE.ReadFile+50- 8B 5D 08              - mov ebx,[ebp+08]
KERNELBASE.ReadFile+53- 83 FB F4              - cmp ebx,-0C { 244 }
KERNELBASE.ReadFile+56- 0F83 60D30400         - jae KERNELBASE.InterlockedExchangeAdd+528C
KERNELBASE.ReadFile+5C- 8B 7D 18              - mov edi,[ebp+18]
KERNELBASE.ReadFile+5F- 85 FF                 - test edi,edi
KERNELBASE.ReadFile+61- 75 71                 - jne KERNELBASE.ReadFile+D4
KERNELBASE.ReadFile+63- 57                    - push edi
KERNELBASE.ReadFile+64- 57                    - push edi
KERNELBASE.ReadFile+65- FF 75 10              - push [ebp+10]
KERNELBASE.ReadFile+68- FF 75 0C              - push [ebp+0C]
KERNELBASE.ReadFile+6B- 8D 45 E0              - lea eax,[ebp-20]
KERNELBASE.ReadFile+6E- 50                    - push eax
KERNELBASE.ReadFile+6F- 57                    - push edi
KERNELBASE.ReadFile+70- 57                    - push edi
KERNELBASE.ReadFile+71- 57                    - push edi
KERNELBASE.ReadFile+72- 53                    - push ebx
KERNELBASE.ReadFile+73- FF 15 5C66E076        - call dword ptr [KERNELBASE.dll+C665C] { ->ntdll.NtReadFile }
KERNELBASE.ReadFile+79- 8B C8                 - mov ecx,eax
KERNELBASE.ReadFile+7B- 81 F9 03010000        - cmp ecx,00000103 { 259 }
KERNELBASE.ReadFile+81- 0F84 B9D30400         - je KERNELBASE.InterlockedExchangeAdd+5310
KERNELBASE.ReadFile+87- 85 C9                 - test ecx,ecx
KERNELBASE.ReadFile+89- 0F88 380A0000         - js KERNELBASE.GetModuleHandleExW+277
KERNELBASE.ReadFile+8F- 85 F6                 - test esi,esi
KERNELBASE.ReadFile+91- 74 05                 - je KERNELBASE.ReadFile+98
KERNELBASE.ReadFile+93- 8B 45 E4              - mov eax,[ebp-1C]
KERNELBASE.ReadFile+96- 89 06                 - mov [esi],eax
KERNELBASE.ReadFile+98- B8 01000000           - mov eax,00000001 { 1 }
KERNELBASE.ReadFile+9D- 8B 4D F0              - mov ecx,[ebp-10]
KERNELBASE.ReadFile+A0- 64 89 0D 00000000     - mov fs:[00000000],ecx { 0 }
KERNELBASE.ReadFile+A7- 59                    - pop ecx
KERNELBASE.ReadFile+A8- 5F                    - pop edi
KERNELBASE.ReadFile+A9- 5E                    - pop esi
KERNELBASE.ReadFile+AA- 5B                    - pop ebx
KERNELBASE.ReadFile+AB- 8B E5                 - mov esp,ebp
KERNELBASE.ReadFile+AD- 5D                    - pop ebp
KERNELBASE.ReadFile+AE- C2 1400               - ret 0014 { 20 }

Quindi, l'API di livello successivo che è più in basso è NtReadFile che si trova in ntdll.dll.

ntdll.NtReadFile - B8 05001A00           - mov eax,001A0005 { [0] }
ntdll.ZwReadFile+5- 64 FF 15 C0000000     - call fs:[000000C0]
ntdll.ZwReadFile+C- C2 2400               - ret 0024 { 36 }
ntdll.ZwReadFile+F- 90                    - nop 

Questo è un tipo speciale di chiamata di syscall che va quindi a SSDT (System Descriptor Table) che ha le API di basso livello che si trovano nell'anello 0 che non è accessibile direttamente tramite l'anello 3 diverso da syscall che sono esposte.

Quindi, le sandbox possono utilizzare una gamma di metodi di aggancio ma i più comuni sono:

  • Deviazioni di memoria (JMP, PUSH RET e così via)
  • Agganciare tabelle IAT
  • VEH (Improbabile, dal momento che ha un strong impatto sulle prestazioni)

Quindi, solo per sapere cosa sta succedendo vorremmo agganciare il NtReadFile che salverebbe al nostro codice e avremo il controllo completo su ciò che viene eseguito. Ad esempio, supponiamo che filtrerai qualsiasi file chiamato SteveEnix. Nella nostra funzione trampolino (dove NtReadFile è stato agganciato e saltato) possiamo leggere i parametri e decidere se chiamarlo o meno. Quindi, assomiglierà a questo:

NTSYSAPI NTSTATUS NTAPI t_NtReadFile(
                  IN HANDLE               FileHandle,
                  IN HANDLE               Event OPTIONAL,
                  IN PIO_APC_ROUTINE      ApcRoutine OPTIONAL,
                  IN PVOID                ApcContext OPTIONAL,
                  OUT PIO_STATUS_BLOCK    IoStatusBlock,
                  OUT PVOID               Buffer,
                  IN ULONG                Length,
                  IN PLARGE_INTEGER       ByteOffset OPTIONAL,
                  IN PULONG               Key OPTIONAL )
{

// Your check on buffer to filter files or whatever you want and return an error or call the original function

}

Se l'applicazione interna ha accesso all'utilizzo di VirtualProtect API o l'area di memoria viene letta e scritta, questi hook possono essere facilmente rimossi.

Tuttavia, se si abbassa un livello ancora più profondo per l'SSDT che su x64 ha PatchGuard per prevenire questi hook, quindi in genere le sandbox non toccano SSDT, allora è necessario caricare un driver nel sistema per poterlo sbloccare. SSDT o patch con il proprio gancio.

    
risposta data 23.03.2016 - 10:34
fonte

Leggi altre domande sui tag