Ciberseguridad
Advent of Cyber día 7
Prácticas / TryHackMe
CloudWatch y CloudTrail aportan piezas distintas. Para reconstruir la actividad hay que respetar tiempos, regiones y tipo de evento; juntar nombres de servicios no completa automáticamente la historia.
Contexto histórico: recorrido de Advent of Cyber 2024. Las capturas y respuestas corresponden al ejercicio original.
Conocimientos:
- AWS
- Cloudwatch
- Cloudtrail
- JQ
En este ejercicio vamos a revisar logs en AWS, a través de CloudWatch, para investigar qué sucedió con los dineros del servicio.
Cloudwatch
Es una plataforma de monitoreo y observabilidad que nos ayuda a investigar el entorno AWS. Monitorea métricas, configura alarmas, etc. EC2 publica métricas básicas de CloudWatch sin instalar el agente. El agente añade, entre otras cosas, métricas internas del sistema operativo y recolección de logs según su configuración. AWS: agente de CloudWatch.
Tres términos importantes:
- Log event:
- una entrada o evento. tiene estampa de tiempo y el mensaje + metadata
- Log streams:
- una colección de logs de una sola fuente
- Log groups:
- colección de log streams. Lo realiza cuando tiene lógica hacerlo, como el mismo servicio en varios hosts.
CloudTrail
CloudWatch puede hacerle un seguimiento a la infraestructura y el performance de aplicaciones. Pero para monitorear acciones en el entorno AWS, utilizamos CloudTrail. La cobertura depende del servicio, categoría de evento y configuración. No significa que cada acción posible quede registrada en todo contexto.
- El historial de eventos de CloudTrail permite consultar los eventos de administración de los últimos 90 días por región; no incluye por defecto todos los eventos de datos. AWS: historial de eventos.
- Formato JSON
- Historial de eventos (90 días)
- Trails
- se pueden definir trails propios para capturar acciones específicas para monitorear escenarios y guardarlos por más de 90 días, por ejemplo
- Enviable
- Se permite configurar los logs de cloudtrail para que lleguen a cloudwatch
Todo esto podemos aplicarlo a servicios como S3 o IAM.
JQ
JQ es un procesador de linea de comandos que se puede usar con JSON de manera similar a sed, awky grep.
jq aplica un filtro a entradas JSON, desde archivos o entrada estándar.
Comenzamos el filtro JQ con un ., que le dice a JQ que vamos a acceder la entrada actual. De ahí, queremos acceder a los valores JSON guardados en array [], osea, tendriamos algo así:
jq '.[]' book_list.json
o podriamos profundizar, agregando una llave del json:
jq '.[] | .book_title' book_list.json
A grandes rasgos, nos ayuda a hacer más fácil la lectura, filtrado y acceso de archivos json.
Investigación
La narrativa del desafío nos cuenta a grandes rasgos:
- Care4wares levantó una caridad
- 28 de noviembre se mandó un enlace con un folleto que tenía detalles de la caridad.
- detalles como el número de cuenta
- primer día recibieron donaciones
- segundo día no recibieron
- preguntando a la gente, si se habían hecho donaciones pero no se recibieron.
- el número de transacción estaba incorrecto.
- El link es el mismo, pero tiene otro número de cuenta.
- el folleto,
wareville-bank-account-qr.pngse guardó un bucket S3 llamadowareville-care4wares
Un log usualmente se ve así:
{
"eventVersion": "1.10",
"userIdentity": {
"type": "IAMUser",
"principalId": "AIDAXRMKYT5O5Y2GLD4ZG",
"arn": "arn:aws:iam::518371450717:user/wareville_collector",
"accountId": "518371450717",
"accessKeyId": "AKIAXRMKYT5OZCZPGNZ7",
"userName": "wareville_collector"
},
"eventTime": "2024-10-21T22:13:24Z",
"eventSource": "s3.amazonaws.com",
"eventName": "ListObjects",
"awsRegion": "ap-southeast-1",
"sourceIPAddress": "34.247.218.56",
"userAgent": "[aws-sdk-go/0.24.0 (go1.22.6; linux; amd64)]",
"requestParameters": {
"bucketName": "aoc-cloudtrail-wareville",
"Host": "aoc-cloudtrail-wareville.s3.ap-southeast-1.amazonaws.com",
"prefix": ""
},
"responseElements": null,
"additionalEventData": {
"SignatureVersion": "SigV4",
"CipherSuite": "TLS_AES_128_GCM_SHA256",
"bytesTransferredIn": 0,
"AuthenticationMethod": "AuthHeader",
"x-amz-id-2": "yqniVtqBrL0jNyGlvnYeR3BvJJPlXdgxvjAwwWhTt9dLMbhgZugkhlH8H21Oo5kNLiq8vg5vLoj3BNl9LPEAqN5iHpKpZ1hVynQi7qrIDk0=",
"bytesTransferredOut": 236375
},
"requestID": "YKEKJP7QX32B4NZB",
"eventID": "fd80529f-d0af-4f44-8034-743d8d92bdcf",
"readOnly": true,
"resources": [
{
"type": "AWS::S3::Object",
"ARNPrefix": "arn:aws:s3:::aoc-cloudtrail-wareville/"
},
{
"accountId": "518371450717",
"type": "AWS::S3::Bucket",
"ARN": "arn:aws:s3:::aoc-cloudtrail-wareville"
}
],
"eventType": "AwsApiCall",
"managementEvent": false,
"recipientAccountId": "518371450717",
"eventCategory": "Data",
"tlsDetails": {
"tlsVersion": "TLSv1.3",
"cipherSuite": "TLS_AES_128_GCM_SHA256",
"clientProvidedHostHeader": "aoc-cloudtrail-wareville.s3.ap-southeast-1.amazonaws.com"
}
}
Puede ser un poco intenso de primera vista pero es todo descriptivo. En lo que nos podemos enfocar ahora mismo:
| Campo | Descripción |
|---|---|
| userIdentity | Detalles de la cuenta de usuario que actuó sobre un objeto |
| eventTime | Cuándo ocurrio |
| eventType | Qué tipo de evento ocurrió (AwsApiCall ? AwsConsoleSignIn ?) |
| eventSource | Desde dónde se logeo este evento |
| eventName | Qué acción específica ocurrió (ListObjects ? GetBucketObject ?) |
| sourceIPAddress | Desde dónde vino la acción |
| userAgent | Que agente de usuario lo realizó (Firefox ? AWS CLI ?) |
| requestParameters | Qué parámetros estuvieron involucrados (BucketName ?) |
| Osea, en nuestro log podemos ver: |
- el usuario IAM,
wareville_collector, listó los objetos (ListObjects event) del S3 llamadoaoc-cloudtrail-wareville 34.247.218.56o la IP desde dónde se originó- El user agent que usó
AWS SDK tool for Go
Usemos JQ para filtrar logs de eventos relacionados con el objeto S3 wareville-bank-account-qr.png
A través de la consola navegamos a wareville_logs y utilizamos el siguiente comando:
jq -r '.Records[] | select(.eventSource == "s3.amazonaws.com" and .requestParameters.bucketName=="wareville-care4wares") | [.eventTime, .eventName, .userIdentity.userName // "N/A",.requestParameters.bucketName // "N/A", .requestParameters.key // "N/A", .sourceIPAddress // "N/A"]' cloudtrail_log.json
Se ve complejo pero no lo es, la estructura sigue siendo la misma:
-rescribe las salidas que sean strings sin comillas JSON; no convierte cualquier resultado a «JSON crudo»- el resto es simplemente pedirle parámetros específicos, filtros, etc
// "N/A"usa la alternativa cuando el resultado de la izquierda esnullofalse- El comando mostrado devuelve arrays. Para obtener TSV habría que añadir
| @tsvdentro del filtro; un formateo concolumnsería un paso adicional que aquí no está incluido.
Con esto obtenemos el siguiente resultado:

Básicamente nos dice que tenemos 5 eventos relacionados con el bucket wareville-care4wares, todos relacionados al usuario glitch. Listó los objetos del bucket pero también subió un archivo: wareville-bank-account-qr.png que coincide con la fecha. Es un usuario anómalo.
Ahora, podríamos investigar todos los eventos relacionados con este usuario:
Lo más relevante es que ingresó a la consola (ConsoleLogin), lo que nos dice que se usó la cuenta para acceder a la consola de AWS en un navegador.
La cadena User-Agent declara macOS y Chrome. Es una pista, no prueba del equipo o navegador real.
Ahora, podríamos buscar quién creo la cuenta. Filtremos los eventos relacionados a IAM.

Con esto ya podemos ir entendiendo para donde va el asunto. Básicamente a través de filtrados de logs vamos encontrando quién creo esa cuenta anómala pero deberiamos verificar los eventos relacionados a esa IP maliciosa y si esta IP ha accedido otras cuentas.
Lo que encontramos es lo siguiente:
- el incidente tuvo un acceso anómalo con el usuario
mcskidydesde la IP53.94.201.69 - se creó una cuenta,
glitch - a
glitchse le asignaron permisos de admin glitchaccedió al S3wareville-care4wares, reemplazó el archivo del folleto. La IP usada para acceder a las cuentas y al User-Agent, es la misma en todos los casos- sin embargo, el User-Agent string y la IP de donde recurrentemente se accede a la cuenta de
mcskidyes distinta a la usada ahora.
Lo que ahora podriamos hacer es buscar en los logs de RDS.
Con el comando grep filtramos el query INSERT INTO:
grep "INSERT INTO" rds.log

Y nos encontramos con lo que necesitabamos.
Preguntas
Para responder las preguntas simplemente debemos utilizar los comandos de filtro para jq. Las dos preguntas sobre IP las podemos deducir a través de los mismos logs. La última pregunta la respondemos con el comando grep!
Con eso concluimos el día 7

Procedamos al Advent of Cyber día 8
Véase también
- Logs — Fundamentos de recopilación y análisis de registros.
Referencias: AWS, contenido de eventos CloudTrail, historial y jq, manual.
+----------------------------------------+
| Floure & |
| Tachibana's guild |
| [Hikari · Nozomi · Rin] |
| SEAL: sha256/12: 81c90696be29 |
| STATUS: LITURGY_IN_PROGRESS |
+----------------------------------------+