Curso: Data Science aplicado a la Ciberseguridad Alumnos: Cesar Burgos, Pablo Medina, Christian Ravichagua, Miguel Zavaleta Fecha: Noviembre 2021 Repositorio de código: GitHub
El presente trabajo se basa en el análisis de la información de urls maliciosas a través del uso de RStudio basado en lenguaje R; el cuál, resulta un recurso idóneo para el análisis estadístico de datos.
La fuente de la información consultada es el “Dataset of Malicious and Benign Webpages” facilitado por Amit Kumar Singh del año 2020 publicado en MENDELEY en el link: Mendeley dataset; el documento contiene 1.2 millones de registros especialmente trabajados para efectos de análisis.
Los datos cuentan con los siguiente atributos:
url La URL de la página web
ip_add La dirección IP de la página web
geo_loc La ubicacuipon geografica donde la pagina se encuentra hospedada
url_len El tamaño de la URL
js_len Tamaño del código JavaScript en la página web
js_obf_len Tamaño del código JavaScript ofuscado
tld El Top Level Domain de la página web
who_is Si el dominio ha consignado información completa en who is o no
https Whether the site uses https or http
content The raw webpage content including JavaScript code
label The class label for benign or malicious webpage
Adicionalmente se agregaron contadores de caracteres especiales para analizar rápidamente si se detectaba algún patrón interesante
Se plantearon preguntas exploratorias para identificar tendencias y patrones que nos ayuden a tomar precaución ante intentos de fraude u otros tipos de ataque.
3.1) Para la manipulación, análisis y presentación de datos, Se trabajó con las siguientes librerías:
library(dplyr)
library(skimr)
library(lubridate)
library(tidyr)
library(ggplot2)
library(hrbrthemes)
library(vtable)
library(e1071)
library(RColorBrewer)
library(leaflet)
library(rgdal)
library(caret)
library(tidyverse)
library(plotrix)
3.2) Se cargaron los datos (que se encuentran en formato SVC y con separador “;” en la variable dataframe “df”
df <- read.csv('dataset-sincontenido.csv',sep=';')
3.3) Una vez cargados los datos, se realizaron trabajos de depuración, transformación y análisis preliminar
Para ello, se buscó convertir en variables tipo “factor” a aquellas que se debían tratar como elementos de clasificación; también se aprovechó para analizar y eliminar valores estadísticamente no representativos como en el siguiente caso:
# Analizando diagrama de cajas para encontrar valores no representativos
ggplot(df,x=1) + geom_boxplot(aes(y=url_len))
El gráfico representa mediante una diagrama de cajas los valores del atributo url_len que representa el tamaño en caracteres de la url. Se identifican valores atípicos (no representativos) mayores a 60 (aproximadamente). Esos valores serán depurados.
#Revisndo nuevamente como queda el dataset
ggplot(df,x=1) + geom_boxplot(aes(y=url_len))
3.4) Una vez tratados los datos, se realiza un ploteo veloz para graficar los datos del tipo entero y del tipo factor.
En este primer análisis se encuentra una curva url_len interesante que representa la distribución respecto al tamaño de caracteres de la url. Que predominan unos pocos paises (geo_loc) como los sitios en donde se encuentran la mayor cantidad de url analizadas. La mayoría de recursos usan https y se encoentran correctamente registrados en who is. Por último, el dataset tiene un gran volumen de urls benignas y muy pocas maliciosas.
Esta aproximación inicial ayuda a entender rápidamente la naturaleza de los datos y permite, a partir de este punto, realizar análisis mas detallados.
El resultado entrega un 97.74% de urls buenas frenta a un 2.26% de url maliciosas.
ggplot(data = df, aes(x = url_len, fill = label, colour = label)) + geom_freqpoly(binwidth=1) + labs(title ="Comparación de páginas url por número de caracteres y clasificación", x = "Número de caracteres", y = "Cantidad")
Las curvas tanto de páginas maliciosas como de páginas normales, tienen su pico cerca de los 25 caracteres; sin embargo, la diferencia en la cantidad de muestrar buenas y muestras maliciosas, no permite apreciar una comparación en la relación del tamaño de las url maliciosas vs las url benignas. Para hacer una comparación mas sencilla de este aspecto, se trabajará con la densidad en el eje y en el gráfico a continuación.
ggplot(data = df, aes(x = url_len, after_stat(density), colour = label)) + geom_freqpoly(binwidth=1)
Las URL maliciosas tienen tamaños similares a las URL buenas; en parte, podría explicarse por el uso de mecanismos de clonación de dominios en los cuales, la página maliciosa emplea nombres muy similares a los originales para evitar que el usuario detecte la diferencia.
WHOIS es un directorio público mediante el cual puede saber «quién es» («who is» en inglés) el propietario de un dominio o dirección IP. Antes podía utilizar WHOIS para conocer algunos datos del propietario, como su nombre, dirección, número de teléfono y dirección de correo electrónico.
# Creación de variables
Who_is_pct <- as.numeric(round(((prop.table(table(df$who_is)))*100),2))
etiquetas_w <- c("Completo", "Incompleto")
etiquetas_w <- paste (etiquetas_w,Who_is_pct)
etiquetas_w <- paste (etiquetas_w,"%", sep = "")
# Grafico Circular 3D
sectores <- pie3D(Who_is_pct, main = " Porcentaje de URL Registradas en Who_Is", explode = 0.2, col = 5:3, border = "white", radius = 1.4)
pie3D.labels(sectores, labels=etiquetas_w, radius=1.4,height=0.5,theta=pi/7, labelcex=1,labelrad=1.3)
Al analizar la data y llevarla a un lienzo podemos apreciar que tanto las paginas web válidas como maliciosas utilizan JavaScript. En el gráfico apreciaremos la relación existente entre la Longitud de URL y Longitud de JavaScript.
ggplot(df) +
aes(x = url_len, y = js_len, colour = label) +
geom_point(shape = "circle",
size = 1) +
scale_color_hue(direction = 1) +
labs(x = "Longitud de URL", y = "Longitud de JavaScript",
title = "Relación Longitud de URL y Longitud de JavaScript") +
theme_gray()
La ofuscación de código es utilizada en la mayoría de casos por páginas web maliciosas para ocultar código y mostrar redireccionamientos a otros sitios o descargas de malware, etc. En el gráfico apreciaremos la relación existente entre la Longitud de URL y Longitud de JavaScript Ofuscado tanto para páginas web válidas y maliciosas donde se apreciará que en su mayoría está presente en web maliciosas.
ggplot(df) +
aes(x = url_len, y = js_obf_len, colour = label) +
geom_point(shape = "circle",
size = 1.5) +
scale_color_hue(direction = 1) +
labs(x = "Longitud de URL", y = "Longitud de JavaScript Ofuscado",
title = "Relación Longitud de URL y Longitud de JavaScript Ofuscado") +
theme_gray()
Al analizar la data y llevarla a un lienzo podemos apreciar la Relación Longitud de URL y Longitud de JavaScript Ofuscado solo para las páginas web maliciosas y nos daremos cuenta que que tiene una alta presencia en páginas web maliciosas.
df %>%
filter(label %in% "bad") %>%
ggplot() +
aes(x = url_len, y = js_obf_len, colour = label) +
geom_point(shape = "circle",
size = 1.5) +
scale_color_hue(direction = 1) +
labs(x = "Longitud de URL", y = "Longitud de JavaScript Ofuscado",
title = "Relación Longitud de URL y Longitud de JavaScript Ofuscado | Bad") +
theme_gray()
A continuación, a un histograma las páginas web maliciosas que utilizan código de JavaScript Ofuscado, podemos visualizar que la longitud de uso de código ofuscado bordea cerca a los 800 carácteres y que esta presente en casi 2500 páginas web maliciosas.
df %>%
filter(label %in% "bad") %>%
ggplot() +
aes(x = js_obf_len, colour = label) +
geom_histogram(bins = 20L, fill = "#4682B4") +
scale_color_brewer(palette = "OrRd", direction = 1) +
labs(x = "Longitud de JavaScript Ofuscado",
title = "Histograma JavaScript Ofuscado - BAD") +
theme_gray()
Al realizar el análisis de paginas maliciosas por el país de origen, creando una escala de la muestra de 1.2 millones de paginas se muestran desde un color mas oscuro a claro, donde los países generan una mayor cantidad paginas son, United States, China, Japan, Germany, United Kingdom, Brazil, en el orden especifico, cabe destacar que China, United States y Brazil, son los países que están entre los 6 países con mayor cantidad de habitantes del mundo. Además en segunda instancia vemos a Rusia y Japón, que están entre los 10 países con mayor habitantes del mundo.
#download.file("http://thematicmapping.org/downloads/TM_WORLD_BORDERS_SIMPL-0.3.zip" , destfile="world_shape_file.zip")
# Unzip del archivo de mapas
#system("unzip world_shape_file.zip")
world_spdf <- readOGR(
dsn= paste0(getwd(),"/world_shape_file") ,
layer="TM_WORLD_BORDERS_SIMPL-0.3",
verbose=FALSE
)
densi <-data.frame(table((filter(df, label=="bad"))$geo_loc))
names(densi) <- c("NAME", "Var1")
densi <-as.data.frame(densi)
densi2 <- world_spdf@data %>% inner_join( world_spdf@data,densi, by = "NAME")
densi2 <- full_join( densi2,densi, by = "NAME")
densi2 <- filter(densi2,!is.na(ISO2.x))
mybins <- c(0,5,20,50,100,500,Inf)
mypalette <- colorBin( palette="YlOrBr", domain=densi2$Var1, na.color="transparent", bins=mybins)
# Prepare the text for tooltips:
mytext <- paste(
"Pais origen: ", world_spdf@data$NAME,"<br/>",
"N° de paginas maliciosas: ", densi2$Var1,
sep="") %>%
lapply(htmltools::HTML)
# Final Map
m <- leaflet(world_spdf) %>%
addTiles() %>%
setView( lat=10, lng=0 , zoom=2) %>%
addPolygons(
fillColor = ~mypalette(densi2$Var1),
stroke=TRUE,
fillOpacity = 0.9,
color="white",
weight=0.3,
label = mytext,
labelOptions = labelOptions(
style = list("font-weight" = "normal", padding = "3px 8px"),
textsize = "13px",
direction = "auto"
)
) %>%
addLegend( pal=mypalette, values=~densi2$Var1, opacity=0.9, title = "Ataques", position = "bottomleft" )
m
Cuando se consolida la cantidad de páginas maliciosas por regiones mundiales de acuerdo con la muestra, existe una gran cantidad de páginas maliciosas en America el cual duplica la paginas realizadas desde el resto del mundo, lo que indica una gran disponibilidad de recursos.
# Grafico circular por regiones
densi3 <- aggregate((filter(densi2, !is.na(densi2$Var1)))$Var1, by=list(Region=(filter(densi2, !is.na(densi2$Var1)))$REGION.x), FUN=sum)
densi3 <- cbind(densi3,NAMEREG= c("otros", "Africa", "Oceania", "America", "Asia", "Europa" ) )
empty_bar <- 0
to_add <- matrix(NA, empty_bar, ncol(densi3))
colnames(to_add) <- colnames(densi3)
densi3 <- rbind(densi3, to_add)
densi3$id <- seq(1, nrow(densi3))
names(densi3) <- c("Región" ,"Var1", "NAMEREG","id")
label_data <- densi3
number_of_bar <- nrow(label_data)
angle <- 90 - 360 * (label_data$id-0.5) /number_of_bar
label_data$hjust <- ifelse( angle < -90, 1, 0)
label_data$angle <- ifelse(angle < -90, angle+180, angle)
p <- ggplot(densi3, aes(x=as.factor(id), y=Var1)) +
geom_bar(stat="identity", fill=alpha("Blue", 0.3)) +
ylim(-1000,12000) +
theme_minimal() +
theme(
axis.text.x = element_blank(),
axis.title = element_blank(),
plot.margin = unit(rep(-1,4), "cm")
) +
coord_polar(start =0) +
geom_text(data=label_data, aes(x=id, y=Var1+10, label= NAMEREG, hjust=hjust), color="black", fontface="bold",alpha=0.6, size=5, angle= label_data$angle, inherit.aes = FALSE )
p
densi3
## Región Var1 NAMEREG id
## 1 0 212 otros 1
## 2 2 626 Africa 2
## 3 9 352 Oceania 3
## 4 19 11042 America 4
## 5 142 4473 Asia 5
## 6 150 4453 Europa 6
En resumen el análisis realizado por geografía indica que los países con mayor origen de población, son los candidatos a generar mas paginas maliciosas, además de ser países con alto crecimiento tecnológico en el mundo.
Las técnicas de análisis de datos avanzadas permiten crear modelos predictivos; surgen preguntas exploratorias respecto a la viabilidad de crear modelos que permitan evitar la conexión a una url maliciosa que no se encuentre listada en ninguna base de datos de reputación; para ello, el primer paso es definir el tipo de modelo de análisis de datos que debe ser empleado que gracias a la siguiente imagen nos permite centrarnos en la pregunta que queremos hacernos. ¿Esta url es maliciosa?
image: … Fuente: https://scientistcafe.com/2017/07/11/datasciencequestion
La pregunta es del tipo: ¿Este correo es spam?, lo que se ajusta a un caso de clasificación. Ya en el ámbito de clasificación tenemos una colección de algoritmos que pueden ser utilizados para clasificar un elemento en función a determinadas condiciones y atributos.
image2: … Fuente:https://blog.hackbrightacademy.com/blog/pycon-2014-melanie-warrick-machine-learning-talk/
Se desarrolla, a continuación, un modelo sencillo basado en Naive Bayes; una técnica bastante simple pero efectiva que realiza clasificaciones en bae a la propbabilidad hallada en los modelos de entrenamiento; esta técnica asume que no existen dependencias entre las variables analizadas.
Para el trabajo, se desarrolla el modelo a partir del 75% de los datos que servirán como participon de entrenamiento y el 25% restante sirve como datos de prueba para ratificar el modelo.
# Eliminando las variables que quedarán fuera del modelo
df <- df[,-(12:22)]
df <- df[,-(9:10)]
df <- df[,-4]
df <- df[,-(1:2)]
#str(df)
set.seed(2021)
entrenamiento <- createDataPartition(df$label, p = 0.75, list = FALSE)
#prop.table(table(entrenamiento$label))*100
modelo <- naiveBayes(label~.,data= df[entrenamiento,])
prediccion <- predict(modelo, df[-entrenamiento,])
tabla <- table(df[-entrenamiento,]$label, prediccion, dnn = c("Actual","Predicha"))
confusionMatrix(tabla)
## Confusion Matrix and Statistics
##
## Predicha
## Actual bad good
## bad 653 4874
## good 711 238693
##
## Accuracy : 0.9772
## 95% CI : (0.9766, 0.9778)
## No Information Rate : 0.9944
## P-Value [Acc > NIR] : 1
##
## Kappa : 0.1822
##
## Mcnemar's Test P-Value : <2e-16
##
## Sensitivity : 0.478739
## Specificity : 0.979989
## Pos Pred Value : 0.118147
## Neg Pred Value : 0.997030
## Prevalence : 0.005569
## Detection Rate : 0.002666
## Detection Prevalence : 0.022566
## Balanced Accuracy : 0.729364
##
## 'Positive' Class : bad
##
El modelo entrega una presición del 97.7% para la muestra utilizada.
Asemejan a los sitios confiables en cuanto a número de caracteres en la URL. En su mayoría, están alojadas en paises de América
Identificación WhoIs Uso de https Registro completo en Who Is Geolocalización o Pool de direcciones IP Uso de javaScript obfuscado
Se puede trabajar desarrollando modelos de clasificación a través de, por ejemplo:
NaiveBayes
K-Nearest Neighbor
Support Vector Machines
Árboles de desición
En este caso, se hizo un ejercicio para construir un modelo de clasificación en base a Naive Bayes utilizando las variables más importantes encontradas al analizar el dataset. Los resultados permiten iniciar en el camino del análisis de datos con modelos clasificatorios que deben ser comparados con diferentes conjuntos de datos y cuya efectividad puede mejorar en función a la calidad y proporción de los mismos junto con un correcto modelado y uso de las técnicas adecuada.