deja de fuzzear y empieza a amar la teoría computacional
toda mi vida mi vocabulario profesional entero fue BYPASS. bypassea el EDR, bypassea al sanitizer, penkeate al sandbox, encadena primitivos. decía "muh detections" con total seriedad. era, en el sentido clínico, una miegda. vacío con forma de vendorspeak que confundía que saber y poder aplicar técnicas implica entendimiento. y lo trágico es que era BUENO en eso, que es la peor wea que podis ser, porque ser bueno en la abstracción equivocada es justamente cómo te quedai pegado ahí.
con el tiempo caché que casi toda mi pega, casi todo lo que había hecho y dicho alguna vez, estaba mal, era impreciso o demostrablemente incorrecto. dolió. caleta. darme cuenta de que mi visión entera del mundo estaba equivocada, que había estado recetando remedios para síntomas en vez del tratamiento para la enfermedad.
lo bueno es que la evolución pasó más rápido de lo que jamás pensé. nunca me he casado con mis creencias en el mundo de la seguridad, porque todo cambia dos veces por semana, o sale algo nuevo y rompe algo que nadie pensaba que se podía romper.
acto uno: el señorito offsec
usuario de edr. siem enjoyer. fuzzeaba el mundo y encontraba IDORs como si fueran dulces y me sentía como un mago. en realidad memorizaba, aplicaba pattern matching nomás. cada engagement era un mazo de trucos y lo barajaba y lo repartía y si funcionaba lo tiraba al reporte.
acto dos: los meses DICOM
después la imagenología médica me comió vivo. orthanc, dcm4chee, gdcm, dcmtk, cada PACS y cada visor de imágenes que juró haber leído el estándar. me encantó. hackié el zoológico entero. lograba que un objeto malformado aterrizara en un archivo y rebotara en otro, y pensaba que esa diferencia era, obviamente, TRIVIA. una maña. el vendor siendo vendor. un producto siendo mejor que otro.
DICOM fue el comienzo de todo este cambio, de todo este reemplazo de mentalidad. aunque lo odio, tengo que agradecerle por recablearme el cerebro.
acto tres: la realización
acá está la cosa que estaba haciendo y no lograba ver: differential testing. a una escala más pequeña, más gila, sin método. a veces agarraba un payload que rompía la implementación A y lo probaba en la implementación B, y a veces hacía algo chori; nunca lo hice de forma CONSISTENTE porque no tenía ninguna teoría de por qué hacer eso significaría resultados similares o iguales. tenía ene hallazgos ahi guardados y los llamaba "coincidencias", "happy mistakes". redescubría la misma idea y se me olvidaba pa la hora de almuerzo.
así que: la base de mi pega en DICOM era una versión penkera de lo que el differential testing debería ser. igual, ya había juntado caleta de conocimiento sobre los pecados de DICOM y sobre lo que los implementadores (casi siempre) cagaban en sus sistemas y, eventualmente, en lo que leían del estándar mismo.
acto cuatro: langsec y la patada en la wata
y después me enteré de que la wea TENÍA un nombre. toda una dinastía de gente haciendo exactamente lo que yo hacía, pero de forma inteligente mientras yo juntaba dos piedras buscando fuego. language-theoretic security. ese momento me reorganizó el cerebro como si alguien metiera la mano y me hiciera un defrag.
porque de repente el pipeline tenía forma. un mensaje no solo viaja, MUTA en cada salto:
M lo que querías decir
E(TCP(M)) codificado, enmarcado, tirado al cable
D(E(TCP(M))) el receptor decodifica lo que CREE que dijiste
C(D(...)) y algún pobre recognizer tiene que decidir qué significacada una de esas flechas es un lugar donde dos máquinas pueden estar en desacuerdo sobre qué lenguaje siquiera están hablando. empecé a ver reconocedores donde antes veía funciones, gramáticas penkeras donde antes veía "el parser", la interoperabilidad como un MAPA de quién acepta qué. no podía sacarmelo de la cabeza. todavía no puedo. es la mejor droga que he consumido y he consumido varias.
y lo más importante, y lo digo directo porque es más fácil que deducirlo de lo que acabo de decir: cuando dos consumidores del mismo formato admiten strings distintos y la diferencia cruza un trust boundary, no se necesita ningún memory bug pa que sea una vulnerabilidad. el diferencial mismo es la vulnerabilidad.
acto cinco: el toolkit
sin necesariamente querer construir un toolkit, construí DICOMKILLA, o DCMK. era apenas una herramienta para reproducir los mismos payloads, byte a byte, en varias implementaciones de la misma cosa (DICOM, en este caso). era bastante limitado en alcance, pero lo suficientemente general para expandirlo después.
no era tan bueno, la verdad. o sea, los payloads se reproducían bien, como debían, ahí ningún problema; pero el grading era... no necesariamente lo mejor, siendo honesto.
pero fue el comienzo del esfuerzo top-to-bottom de pwnear estándares primero, pa aplicarle pwnage a las implementaciones después. romper prosa suele ser más fácil que irse en contra de una implementación de un estándar que uno no cacha ni en pelea de perros.
acto seis: el paper
y después de un rato y caleta de trabajo en DCMK, se volvió lo suficientemente maduro para poder depender de él para generar data útil de verdad para el paper de DICOM en el que estoy trabajando. payloads spec-anchored, cada uno intentando romper una ambigüedad específica del estándar DICOM. aparecieron hartas cosas, se han pedido vaarios CVEs, y así, la herramienta se probó a sí misma como más que suficiente. se volvió un producto del paper, un artefacto real que estaba produciendo buenos resultados.
así, DCMK fue renombrado, y pasó a llamarse Differential Conformance Matrix Kraftwerk.
acto siete: evolución
el spec-anchoring se volvió un reflejo. cada payload equivocado-a-propósito tenía que citar la cláusula exacta que estaba estresando o no lo salía. el hacha que usas para cortar la piel de un estándar escrito por comité, para encontrar los lugares donde los mismos pelaos no supieron ponerse de acuerdo. todavía no cachaba del todo lo que tenía en las manos. pocas veces uno entiende la magnitud de su propia obra.
el ecosistema, por supuesto, creció mucho más allá del mundo DICOMKILLA, lo que implicó que las dependencias también murieron. DICOM se volvió apenas un plugin dentro de una interfaz por lo demás fácilmente expandible, extensible y muy bonita. MLLP fue el segundo, J2K está ahí pero sin exorcizar (no tengo plata pal estándar J2K lol) y eventualmente apareció FHIR, junto con HL7 CDA XML.
acto ocho: la mentora
después alguien cuyo trabajo fundó este campo entero respondió el correo de un don nadie chileno. no voy a poner su nombre en mi blog (y no le voy a preguntar porque está ocupada con un proyecto precioso) así que van a tener que creerme cuando digo que me pesó en ese momento, y me sigue pesando ahora. me dijo: "you're recovering the boundaries of competence that real implementations actually exhibit, and that's really powerful."
el hacha es la cura. esa sola frase dio vuelta la herramienta completa en mis manos. yo pensaba que había construido una cosa que destruye estándares. ella vió que el mismo hachazo te entrega el subconjunto seguro, la islita decidible en la que todas las implementaciones sí están de acuerdo. la misma matriz. tú decides a la entrada si veniste a romperlo o a sanarlo. mi MUNDO tembló. salí a caminar y no volví siendo el mismo animal.
DCMK dejó de ser un mero harness que probaba que existen distintas clases de lenguaje. le crecieron dos filos. un falsificador empírico que refuta "un estándar, un lenguaje" por contraejemplo, y un probador constructivo que talla un subconjunto lo suficientemente chico como pa probarlo decidible. no solo atacar y destruir, sino remendar y curar.
la falsabilidad va en las dos direcciones al final. un filo: probar que n implementaciones leen el estándar distinto y así lo parten en clases de lenguaje distintas. el otro filo: restringir ese wire language a un subconjunto seguro lo suficientemente chico como para que RECONOCERLO sea decidible, y después probar si una implementación real de verdad se queda adentro. o no. eso es lo que lo hace un falsificador y no un deseo. la cosa que estás volviendo decidible no es "el problema", es la membresía: está este input en el lenguaje seguro, sí o no, demostrablemente, todas las veces.
acto nueve: el patrón bajo el patrón
y acá es donde deja de tratarse de DICOM.
quédate un rato con el halting problem. ¿puede una máquina de Turing recibir otra máquina de Turing como input y decidir si su ejecución termina? no. probado que no, 1936, no y no por siempre. indecidible.
ahora agrégale una palabra. INTENCIÓN.
¿puede un programa recibir otro programa y decidir si es MALICIOSO? es el mismo problema con capucha. es el halting con un motivo apernado encima. y no es una observación ingeniosa mía, es Fred Cohen, 1987, que probó que la detección perfecta de un virus es indecidible reduciéndola directo al halting. el problema de la maliciosidad. cada antivirus, cada EDR, cada sandbox, cada uno de los productos que me pasé años evadiendo con cariño, es una máquina construida pa responder una pregunta que la MATEMÁTICA dice que no tiene respuesta. no son malos en su pega. su pega es imposible. te están vendiendo un halting problem resuelto en una UI bonita con un threat feed.
y vamos un paso más allá: la gente dice que "ningún programa, sitio web, servicio, servidor, etcétera, puede ser completa y 100% seguro o inhackeable". la gente DICE esto. lo RECITA con una certeza que me hace LLORAR.
pero... ¿por qué? ¿por qué no se puede ser 100% seguro, inhackeable?
acto nueve/2: la ciencia de la (in)seguridad
porque es el mismo no, una capa más abajo. "inhackeable" es apenas "¿benigno o malicioso?" preguntado sobre un sistema entero en vez de un solo programa, y ya establecimos que esa pregunta no tiene respuesta.
la world wide web, el mundo en el que vivimos, es una red de composición (encoding) y descomposición (decoding) de mensajes (input), desde mensajes HTTP, paquetes TCP, ruteo BGP...OSPF, descomposición TCP, accession HTTP, chequeo de datos. cada uno de esos pasos es un lugar donde los differentials pueden vivir. sin mencionar la cantidad GIGANTEZZZZCA de protocolos distintos, algunos inocuos (TCP/UDP!!!), algunos basura (DICOM!!!), con estándares y specs tan complejos, tan grandes y tan brígidos que la única respuesta posible a "¿es posible la inhackeabilidad?" es NO y SIEMPRE no.
acto diez: este post
así que acá está lo que realmente me pasó. yo pensaba que la teoría computacional era una wea que unos genios klos hicieron por diversión en los años 30 mientras esperaban que se inventara la penicilina. abstracta. inútil. un rito de pregrados universitarios.
no lo es. es la GENERALIZACIÓN. el halting problem es por qué la detección no puede ganar. la reducción de Cohen es por qué el antivirus es una religión. la jerarquía de Chomsky es por qué tu parser es un intérprete accidental. el teorema de Rice es, calladito, la razón por la que tu vendor de análisis estático entero está corrigiendo una prueba imposible de corregir. cada problema de seguridad al que me enfrenté alguna vez era un problema de decidibilidad con sombrero, y yo andaba discutiendo con el SOMBRERO!!!
me pasé años aprendiendo bypasses. la parte donde todo se cayó y se reconstruyó en algo verdadero tomó como dos meses. esa es la mejor parte. la abstracción equivocada aguantó años y la correcta llegó en un invierno, porque la correcta no es una pila más grande de trucos, es una sola idea que aglomera todos los trucos de una. una vez que cachas que la detección perfecta es INDECIDIBLE, dejas de acumular bypasses. la teoría ya zanjó si existen. sí. siempre. un detector que atrapa todo no se puede construir, así que la evasión está garantizada, no descubierta. "¿existen los bypasses?" nunca fue la pregunta. la única pregunta que queda es "¿puedo encontrarlos?"
REGARDLESS OF THE HARDWARE, SERVICE OR ENCODING, CONNECT IT TO THE INTERNET AND SOMEONE'S GONNA OWN IT!