TED: un detector de exploits publicados en Twitter que utiliza ML

Hola a todos, aunque no soy un escritor habitual de este blog, me hacía mucha ilusión contaros un mini proyecto que estuve desarrollando en mis vacaciones de semana santa. El proyecto en cuestión se llama TED (Twitter-based Exploit Detector), como bien indica su nombre un detector de exploits en twitter que todavía está en fase PoC.

https://twitter.com/alexfrancow_sec

TED es un bot de Twitter que tiene como objetivo hacer retweet a todo aquel texto que contenga un exploit para un CVE, manteniéndonos así notificados de cuando un exploit es publicado. En su interior incorpora una serie de algoritmos de Machine Learning que le aportan la inteligencia necesaria para discernir entre un tweet que contenga una prueba de concepto a uno que solo aporte información de una vulnerabilidad.

Al utilizar algoritmos supervisados, se ha tenido que crear un dataset en el que se han identificado 629 tweets a mano y se han categorizado con una etiqueta, "Exploit", la cual contiene el valor 1 o 0 siendo 1 exploit y 0 simplemente información. Como se verá más adelante será necesario seguir etiquetando tweets a mano para poder incrementar la precisión del modelo de ML.

Imagen del dataframe etiquetado manualmente

El modelo ha sido entrenado con un algoritmo llamado MultinomialNB, del cual tenéis muchos más detalles técnicos en el enlace de mi blog. Básicamente es un tipo de algoritmo del conjunto de algoritmos "Naive Bayes" una clase especial de algoritmos de clasificación de Machine Learning que se basan en una técnica de clasificación estadística llamada “teorema de Bayes”, como se mencionó anteriormente supervisado. Los clasificadores Naive Bayes se han aplicado con éxito a muchos dominios, particularmente Procesamiento del lenguaje natural (NLP), por lo que encajaría perfectamente con nuestro proyecto. Un funcionamiento un poco más detallado sería:

El primer paso, hacer un pre-procesado de los tweets; sustitución de URLs y nombres de usuario por palabras clave, eliminación de signos de puntuación y la conversión a minúsculas, y la normalización del texto (stemmer, lemmatize).

Imagen del dataframe pre-procesado correctamente

Con el texto bien procesado, nos enfocamos en extraer características del texto. Necesitamos características numéricas como entrada para nuestro clasificador. Entonces, una elección intuitiva sería la frecuencia de las palabras, es decir, contar la aparición de cada palabra en el documento.

Y el último paso sería aplicar los algoritmos de MultinomialNB, que lo haremos muy fácil con la librería de scikit-learn de Python.

```python
# Se crea una canalización con un vectorizador y nuestro clasificador Naive Bayes:
pipe_mnnb = Pipeline(steps = [('tf', TfidfVectorizer()), ('mnnb', MultinomialNB())])

# Parameter grid
pgrid_mnnb = {
    # Max_features is the maximum number of words to include in the vocabulary. We will test max vocab sizes of 1000, 2000, and 3000 words.
    'tf__max_features' : [1000, 2000, 3000],
    
    # Stop_words are common words that can be filtered out when creating the vocabulary- read about them here. We will test removing stopwords against leaving them in.
    'tf__stop_words' : ['english', stop_words_alexfrancow],
    
    # ngram_range allows our model to look at individual words as well as word pairs. For example, the string “I like black cats” would get tokenized into “I”, “I like”, “like”, “like black”, “black”, “black cats”, “cats”. We will test using ngrams of 1 and 2 against just single words.
    'tf__ngram_range' : [(1,1),(1,2)],
    
    # Use_idf is the one we mentioned before. This will test a model that fits a TfidfVectorizer against one that fits a CountVectorizer.
    'tf__use_idf' : [True, False],
    
    'mnnb__alpha' : [0.1, 0.5, 1]
}

gs_mnnb = GridSearchCV(pipe_mnnb, pgrid_mnnb, cv=5, n_jobs=-1)
gs_mnnb.fit(X_train, y_train)

```

Llegados hasta aquí podremos conocer la precisión de casos clasificados correctamente de nuestro modelo, que fue de un 77%, ¿con este porcentaje es suficiente?, lo normal para un modelo existoso es que la precisión sea de un 90%, pero en este caso vemos que no da tan malos resultados para una PoC.

El bot actualmente está en funcionamiento y ya ha dado para varios ejemplos exitosos, uno muy interesante que menciono en el blog fue el acceso a las cámaras personales de seguridad de varias viviendas. En este ejemplo, para hacerlo distinto, veremos un CMS vulnerable.

A las 14 horas de publicarse el CVE-2021-21425 (07/04/2021) que afecta al CMS gravCMS con un riesgo critico ya que permite un RCE unauthenticated contra el servidor, el bot detectó un posible exploit que, tras haberlo comprobado manualmente, dimos por positivo. 

En el link al que hace referencia el tweet, se incluye una explicación muy detallada de la vulnerabilidad en el que explica la función exacta donde se encuentra la vulnerabilidad además de ofrecer el módulo para explotarla en metasploit.

Como vemos en el blog la vulnerabilidad realmente se descubrió el día 18 de Marzo.

 

https://pentest.blog/unexpected-journey-7-gravcms-unauthenticated-arbitrary-yaml-write-update-leads-to-code-execution/

Si nos vamos a shodan.io podremos buscar por la etiqueta meta de html que contiene el valor GravCMS , de esta manera nos saldrán todos los CMS y veremos que hay unas cuantas webs que probablemente están siendo afectadas por la vulnerabilidad.

Filtro utilizado: html:content="GravCMS"


Filtro utilizado: html:content="GravCMS" country:"ES"

Claro ejemplo de que se trata de GravCMS

Cabe destacar que la vulnerabilidad en ningún caso se intento explotar ni llegaron a realizar peticiones maliciosas contra ningún sitio web publicado.

Este bot solo se trata de una PoC de que el modelo de Machine Learning entrenado es funcional, quedaría retocarlo para que sea productivo, ya que todavía tiene un bajo porcentaje de precisión.

Como venía recalcando en varias ocasiones a lo largo de este post, podéis encontrar información más detallada en el post que publiqué en: https://alexfrancow.github.io

Muchas gracias, cualquier duda podéis contactarme por Twitter: @alexfrancow

Comentarios