La función de la consulta RDP Logins from External IPs.sql es bastante autoexplicativa, basándonos en el nombre. En este post, la utilizaremos para buscar conexiones RDP satisfactorias que hayan tenido lugar desde direcciones IP externas, es decir, cualquiera que no sea RFC 1918. Para esta demostración, haremos el trabajo de construir y ejecutar la consulta en sí a través de nuestro propio servicio Sophos Central, pero lo básico es válido independientemente de la herramienta de investigación. Como alternativa, el vídeo “Ejecutar la consulta RDP externa” enlazado a continuación muestra los pasos relevantes, en lugar de describirlos como hacemos aquí.
Crear y ejecutar la consulta
El primer paso es crear la consulta, para eso en Sophos Central ve a:
Centro de Análisis de Amenazas > Live Discover > Modo Diseñador
haciendo clic en el botón Crear nueva consulta, como se muestra en la Figura 1.
Al hacer clic en el botón se abre una pantalla con un cuadro SQL, en el que pegarás la siguiente consulta (también disponible en nuestro Github):
SELECT strftime('%Y-%m-%dT%H:%M:%SZ',datetime) AS date_time, eventid, CASE eventid WHEN 21 THEN eventid || ' - Session logon succeeded' WHEN 22 THEN eventid || ' - Shell start notification received' WHEN 25 THEN eventid || ' - Session reconnection successful' ELSE NULL END AS description, JSON_EXTRACT(data, '$.UserData.User') AS username, SUBSTR(JSON_EXTRACT(data, '$.UserData.User'), 1, INSTR(JSON_EXTRACT(data, '$.UserData.User'), '\') - 1) AS domain, JSON_EXTRACT(data, '$.UserData.Address') AS source_IP, JSON_EXTRACT(data, '$.UserData.SessionID') AS session_ID, CASE WHEN JSON_EXTRACT(data, '$.UserData.Address') GLOB '*[a-zA-Z]*' THEN 'private_IP' WHEN INSTR(JSON_EXTRACT(data, '$.UserData.Address'), '192.168.') = 1 THEN 'private_IP' WHEN INSTR(JSON_EXTRACT(data, '$.UserData.Address'), '172.') = 1 AND CAST(SUBSTR(JSON_EXTRACT(data, '$.UserData.Address'), 5, 2) AS INTEGER) BETWEEN 16 AND 31 THEN 'private_IP' WHEN INSTR(JSON_EXTRACT(data, '$.UserData.Address'), '10.') = 1 THEN 'private_IP' WHEN INSTR(JSON_EXTRACT(data, '$.UserData.Address'), '127.') = 1 THEN 'private_IP' WHEN JSON_EXTRACT(data, '$.UserData.Address') = '0.0.0.0' THEN 'private_IP' WHEN JSON_EXTRACT(data, '$.UserData.Address') LIKE '%::%' THEN 'unknown' WHEN JSON_EXTRACT(data, '$.UserData.Address') = '' THEN 'private_IP' ELSE 'external_IP' END AS status, 'TS LocalSession EVTX' AS data_source, 'Logins.01.4' AS query FROM sophos_windows_events WHERE source = 'Microsoft-Windows-TerminalServices-LocalSessionManager/Operational' AND eventid IN (21,22,25) AND (status = 'external_IP' OR status = 'unknown') UNION ALL SELECT strftime('%Y-%m-%dT%H:%M:%SZ',datetime) AS date_time, eventid, CASE eventid WHEN 1149 THEN eventid || ' - User authentication succeeded' ELSE NULL END AS description, JSON_EXTRACT(data, '$.UserData.Param1') AS username, JSON_EXTRACT(data, '$.UserData.Param2') AS domain, JSON_EXTRACT(data, '$.UserData.Param3') AS source_IP, NULL AS Session_ID, CASE WHEN INSTR(JSON_EXTRACT(data, '$.UserData.Param3'), '192.168.') = 1 THEN 'private_IP' WHEN INSTR(JSON_EXTRACT(data, '$.UserData.Param3'), '172.') = 1 AND CAST(SUBSTR(JSON_EXTRACT(data, '$.UserData.Param3'), 5, 2) AS INTEGER) BETWEEN 16 AND 31 THEN 'private_IP' WHEN INSTR(JSON_EXTRACT(data, '$.UserData.Param3'), '10.') = 1 THEN 'private_IP' WHEN INSTR(JSON_EXTRACT(data, '$.UserData.Param3'), '127.') = 1 THEN 'private_IP' WHEN JSON_EXTRACT(data, '$.UserData.Param3') = '0.0.0.0' THEN 'private_IP' WHEN JSON_EXTRACT(data, '$.UserData.Param3') LIKE '%::%' THEN 'unknown' WHEN JSON_EXTRACT(data, '$.UserData.Param3') = '' THEN 'private_IP' ELSE 'external_IP' END AS status, 'TS RemoteConnection EVTX' AS data_source, 'Logins.01.4' AS query FROM sophos_windows_events WHERE source = 'Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational' AND eventid = 1149 AND (status = 'external_IP' OR status = 'unknown')
Una vez pegado esto, seleccionarás las máquinas contra las que debe ejecutarse esta consulta. La consulta es específica de Windows; si se ejecuta en máquinas macOS o Linux no se obtendrán resultados, por lo que deseleccionarlas (en la opción Filtros -> Sistema operativo) es un buen primer paso. Más allá de eso, las necesidades de cada empresa son únicas. Sin embargo, hay razones de peso para ejecutar la consulta en todos los equipos Windows de tu red, incluso en los endpoints, por si alguno está incorrectamente expuesto a Internet. Por desgracia, nuestros investigadores de Respuesta a Incidentes se encuentran con esto mucho más a menudo de lo que cabría esperar.
Haz clic en Actualizar Dispositivos Seleccionados para confirmar tus selecciones y selecciona Ejecutar Consulta en la parte inferior derecha para ejecutarla. El sistema te pedirá que confirmes que deseas ejecutar esta consulta no probada: lo haces. La consulta comienza a ejecutarse; la velocidad a la que se devuelven los resultados depende de cuántos dispositivos se consulten y de sus conexiones de red. Cuando termine, la columna Estado te avisará de la finalización de la consulta (o, si algo ha ido mal, del fallo de la consulta). Desplázate hacia arriba; hay una sección llamada Resultados de la consulta que muestra los resultados. Si no aparece nada, ¡enhorabuena! No se han encontrado inicios de sesión RDP desde direcciones IP externas. Si, por el contrario, se muestran resultados…
Entender los resultados
Si tu consulta devuelve resultados, el primer campo a tener en cuenta en esos resultados es el nombre del endpoint. En el ejemplo que se muestra a continuación (tomado del banco de pruebas que montamos para hacer nuestro vídeo), dos máquinas informaron de que tienen conexiones RDP externas.
Al ampliar los resultados vemos la fecha y hora en que se produjo la conexión, el ID de evento devuelto por la consulta (con una breve descripción de lo que significa ese ID de evento), el nombre de usuario de la cuenta que se conectó y la dirección IP de origen desde la que se conectaron. Las direcciones no RFC 1918 demuestran que estas conexiones no procedían del espacio de direcciones privado de la red.
Cabe señalar que, como con cualquier consulta de este tipo, es necesario investigar más para descartar falsos positivos. Sin embargo, un “falso” positivo (una conexión externa peculiar que en realidad no era más que un administrador abriendo RDP en un servidor temporalmente) sigue mereciendo la pena comprobarlo. Como hemos señalado anteriormente en esta serie de artículos, los atacantes son impresionantemente rápidos para saltar a una conexión RDP abierta. Si el administrador pudo conectarse, son muchas las probabilidades de que un atacante también pudo encontrar el puerto abierto. Si fuéramos muy precavidos podríamos aislar el dispositivo y examinarlo más a fondo en busca de un posible compromiso.
Protocolo de escritorio remoto: la serie
Parte 1: protocolo de escritorio remoto: introducción (post, vídeo)
Parte 2: RDP expuesto (es peligroso) (post, vídeo)
Parte 3: consultas para la investigación (post, vídeo)
Parte 4: factor zona horaria RDP (post, vídeo)
Parte 5: ejecución de la consulta RDP externa (estás aquí, vídeo)
Parte 6: ejecución de la consulta de inicio de sesión 4624_4625 (post, vídeo)
Repositorio de consultas en GitHub: SophosRapidResponse/OSQuery
Repositorio de transcripciones: sophoslabs/video-transcripts
Lista de reproducción de YouTube: Protocolo de escritorio remoto: la serie