¿Escape de un lenguaje aislado y completo de la caja de arena?

4

La documentación de Solidaridad de Ethereum dice:

  

La Máquina Virtual Ethereum o EVM es el entorno de ejecución para contratos inteligentes en Ethereum. No solo está aislado, sino que está completamente aislado, lo que significa que el código que se ejecuta dentro del EVM no tiene acceso a la red, al sistema de archivos ni a otros procesos.

¿Limitar el acceso a la red, el sistema de archivos y otros procesos es suficiente para evitar que el lenguaje completo de Turing se escape?

    
pregunta Steve Ellis 22.03.2016 - 17:36
fuente

2 respuestas

4

Escape from sandboxes no se realiza en lenguajes sino en implementaciones. He visto las siguientes implementaciones de VM:

Cada implementación se basa en la corrección del compilador / intérprete y en la corrección de la implementación en sí. Un atacante querría escapar de Ethereum VM y para lograrlo tendría que explotar una combinación de errores en el compilador / intérprete / bibliotecas estándar y en la propia implementación. Si bien es una tarea difícil, de ninguna manera es imposible (lo más probable es que implique cero días). Yo diría que libethereum es el más vulnerable que se está implementando en C ++ ...

En unos pocos años, a medida que Ethereum gane aceptación, surgirá una implementación dominante que facilitará la tarea del atacante ( webthree- umbrella tiene el compilador de Solidaridad canónica).

Para proporcionar defensa en profundidad de tales ataques, uno recomendaría ejecutar sandbox de Ethereum dentro de máquinas virtuales de propósito general. Incluso entonces, el método principal de prevención de ataques dependerá de la verificación de los contratos manualmente :

  1. Vaya a EtherChain.org , obtenga el código fuente del contrato.
  2. Obtenga el bytecode que está siendo alimentado. Desmóntelo usted mismo.
  3. Compile el código y compárelo con el código de bytes recibido. (Consulte esta pregunta en Ethereum SE para detalles - resulta ser una PITA).
  4. ???
  5. Evita pérdidas.
  6. Comience el tono y llore si ve un contrato malicioso ...

Nota: la existencia de dos idiomas completos de Turing (Solidity y Serpent) y docenas de versiones de compilación (más de 60 encarnaciones de Solidity) hace que sea más difícil para el defensor detectar contratos maliciosos.

    
respondido por el Deer Hunter 23.03.2016 - 09:31
fuente
2

No, no lo es y es bastante complejo de evitar.

En general, los Sandbox enganchan las API internas y ejecutan el código en el nivel más bajo en el anillo 3. Hablemos de la API de archivos, para empezar. Si está familiarizado con los lenguajes de programación de nivel inferior como C, C ++, etc., sabrá acerca de ReadFile API. Por lo tanto, echemos un vistazo a ReadFile en un desmontaje.

ReadFile está situado como en la EAT (tabla de direcciones de exportación) en Kernel32.

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

Entonces, salta a KernelBase.dll a un ReadFile. No se preocupe por no entender todos los códigos de operación, solo esté interesado en las LLAMADAS.

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 }

Por lo tanto, la siguiente API de nivel que está más abajo es NtReadFile que se encuentra en 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 

Este es un tipo especial de llamada llamada syscall que luego va a la SSDT (Tabla de Descriptores de Servicio del Sistema) que tiene las API de bajo nivel que se encuentran en el anillo 0, a las que no se puede acceder directamente a través del anillo 3 que no están a la vista.

Por lo tanto, las cajas de arena pueden usar una variedad de métodos de conexión, pero los más comunes son:

  • Desvíos de memoria (JMP, PUSH RET, etc.)
  • Enganchar tablas IAT
  • VEH (improbable, ya que tiene un gran impacto en el rendimiento)

Entonces, solo para saber lo que sucede es que enganchamos el NtReadFile que saltaría a nuestro código y tenemos control completo sobre lo que se ejecuta. Por ejemplo, digamos que va a filtrar cualquier archivo llamado SteveEnix. En nuestra función de trampolín (donde se ha enganchado y saltado el NtReadFile) podemos leer los parámetros y decidir llamarlos o no. Por lo tanto, se verá así:

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

}

Si la aplicación interna tiene acceso al uso de VirtualProtect API o si la región de la memoria se lee y escribe, estos enlaces pueden eliminarse fácilmente.

Sin embargo, si baja un nivel aún más profundo al SSDT, que en x64 tiene PatchGuard para evitar estos ganchos, por lo que generalmente los entornos limitados no tocan el SSDT, entonces necesitará un controlador para cargar en el sistema para poder desemparejar el SSDT o parchelo con su propio gancho.

    
respondido por el Paul 23.03.2016 - 10:34
fuente

Lea otras preguntas en las etiquetas