You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

235 lines
6.9 KiB

# code to prepare datasets and factors goes here
# You need to execute the entire file for a complete dataset pkg
library(tidyverse)
library(stringi)
library(rvest)
# Remove saved JSON -------------------------------------------------------
unlink(
sprintf("%s.xz", here::here(
"data-raw",
c(
"enterprise-attack.json",
"mobile-attack.json",
"pre-attack.json"
)
))
)
# Get new JSON ------------------------------------------------------------
ent_url <- "https://github.com/mitre/cti/raw/master/enterprise-attack/enterprise-attack.json"
mob_url <- "https://github.com/mitre/cti/raw/master/mobile-attack/mobile-attack.json"
pre_url <- "https://github.com/mitre/cti/raw/master/pre-attack/pre-attack.json"
download.file(
url = c(ent_url, mob_url, pre_url),
destfile = c(
here::here(
"data-raw",
c("enterprise-attack.json", "mobile-attack.json", "pre-attack.json")
)
),
method = "libcurl"
)
# Compress new JSON -------------------------------------------------------
walk(
here::here(
"data-raw",
c(
"enterprise-attack.json",
"mobile-attack.json",
"pre-attack.json"
)
),
~system2("xz", args = .x)
)
# Make Enterprise matrix --------------------------------------------------
jsonlite::fromJSON(
here::here("data-raw/enterprise-attack.json.xz")
) -> enterprise_attack
enterprise_attack[["objects"]] <- tibble::as_tibble(enterprise_attack[["objects"]])
# Make Mobile matrix ------------------------------------------------------
jsonlite::fromJSON(
here::here("data-raw/mobile-attack.json.xz")
) -> mobile_attack
mobile_attack[["objects"]] <- tibble::as_tibble(mobile_attack[["objects"]])
# Make Pre matrix ---------------------------------------------------------
jsonlite::fromJSON(
here::here("data-raw/pre-attack.json.xz")
) -> pre_attack
pre_attack[["objects"]] <- tibble::as_tibble(pre_attack[["objects"]])
# Make tidy summary structure ---------------------------------------------
bind_rows(
map_df(1:nrow(enterprise_attack$objects), ~{
if (is.na(enterprise_attack$objects$name[[.x]])) return(NULL)
if (is.null(enterprise_attack$objects$kill_chain_phases[[.x]])) return(NULL)
tibble(
technique = enterprise_attack$objects$name[[.x]],
description = enterprise_attack$objects$description[.x],
id = discard(enterprise_attack$objects$external_references[[.x]]$external_id, is.na) %||% NA_character_,
phs = enterprise_attack$objects$kill_chain_phases[.x]
) %>%
unnest(phs)
}),
map_df(1:nrow(mobile_attack$objects), ~{
if (is.na(mobile_attack$objects$name[[.x]])) return(NULL)
if (is.null(mobile_attack$objects$kill_chain_phases[[.x]])) return(NULL)
tibble(
technique = mobile_attack$objects$name[[.x]],
description = mobile_attack$objects$description[.x],
id = discard(mobile_attack$objects$external_references[[.x]]$external_id, is.na) %||% NA_character_,
phs = mobile_attack$objects$kill_chain_phases[.x]
) %>%
unnest(phs)
}),
map_df(1:nrow(pre_attack$objects), ~{
if (is.na(pre_attack$objects$name[[.x]])) return(NULL)
if (is.null(pre_attack$objects$kill_chain_phases[[.x]])) return(NULL)
tibble(
technique = pre_attack$objects$name[[.x]],
description = pre_attack$objects$description[.x],
id = discard(pre_attack$objects$external_references[[.x]]$external_id, is.na) %||% NA_character_,
phs = pre_attack$objects$kill_chain_phases[.x]
) %>%
unnest(phs)
})
) %>%
rename(tactic = phase_name, matrix = kill_chain_name) %>%
distinct() -> tidy_attack
# Make ordered tactics for factoring --------------------------------------
et_tbl <- read_html("https://attack.mitre.org/tactics/enterprise/") %>% html_nodes("table")
mb_tbl <- read_html("https://attack.mitre.org/tactics/mobile/") %>% html_nodes("table")
pre_tbl <- read_html("https://attack.mitre.org/tactics/pre/") %>% html_nodes("table")
et_tbl %>%
html_table() %>%
.[[1]] %>%
as_tibble() %>%
rename(taid = ID, pretty = Name, description = Description) %>%
mutate(
nl = stri_replace_all_fixed(pretty, " ", "\n"),
id = stri_trans_tolower(pretty) %>% stri_replace_all_fixed(" ", "-")
) %>%
select(taid, id, pretty, nl, description) %>%
mutate(
link = sprintf(
"https://attack.mitre.org%s",
html_attr(html_nodes(et_tbl, xpath = ".//td[1]/a"), "href")
)
) -> ent_tac
mb_tbl %>%
html_table() %>%
.[[1]] %>%
as_tibble() %>%
rename(taid = ID, pretty = Name, description = Description) %>%
mutate(
nl = stri_replace_all_fixed(pretty, " ", "\n"),
id = stri_trans_tolower(pretty) %>% stri_replace_all_fixed(" ", "-")
) %>%
select(taid, id, pretty, nl, description) %>%
mutate(
link = sprintf(
"https://attack.mitre.org%s",
html_attr(html_nodes(mb_tbl, xpath = ".//td[1]/a"), "href")
)
) -> mob_tac
pre_tbl %>%
html_table() %>%
.[[1]] %>%
as_tibble() %>%
rename(taid = ID, pretty = Name, description = Description) %>%
mutate(
nl = stri_replace_all_fixed(pretty, " ", "\n"),
id = stri_trans_tolower(pretty) %>% stri_replace_all_fixed(" ", "-")
) %>%
select(taid, id, pretty, nl, description) %>%
mutate(
link = sprintf(
"https://attack.mitre.org%s",
html_attr(html_nodes(pre_tbl, xpath = ".//td[1]/a"), "href")
)
) -> pre_tac
tactics_f <- list()
tactics_f[["mitre-attack"]] <- ent_tac
tactics_f[["mitre-pre-attack"]] <- pre_tac
tactics_f[["mitre-mobile-attack"]] <- mob_tac
# Mitigations -------------------------------------------------------------
et_tbl <- read_html("https://attack.mitre.org/tactics/enterprise/") %>% html_nodes("table")
# Save it all out ---------------------------------------------------------
usethis::use_data(
enterprise_attack, mobile_attack, pre_attack, tidy_attack, tactics_f,
internal = FALSE,
overwrite = TRUE,
compress = "xz"
)
# Update docs -------------------------------------------------------------
upd <- as.character(Sys.Date())
cat(glue::glue("# This file is autogenerated from tools/update-framework.R
# DO NOT MODIFY BY HAND as all changes will be overwritten
#' @title Enterprise Attack Taxonomy v{enterprise_attack$spec_version}
#' @name enterprise_attack
#' @note Id: `{enterprise_attack$id}`
#' @note Last updated: {upd}
#' @references <{ent_url}>
#' @docType data
NULL
#' @title Mobile Attack Taxonomy v{mobile_attack$spec_version}
#' @name mobile_attack
#' @note Id: `{mobile_attack$id}`
#' @note Last updated: {upd}
#' @references <{mob_url}>
#' @docType data
NULL
#' @title Pre-Attack Taxonomy v{pre_attack$spec_version}
#' @name pre_attack
#' @note Id: `{pre_attack$id}`
#' @note Last updated: {upd}
#' @references <{pre_url}>
#' @docType data
NULL
#' @title Combined ATT&CK Matricies Tactics, Techniques and Technique detail
#' @name tidy_attack
#' @note Last updated: {upd}
#' @docType data
NULL
#' @title Tactics factors (generally for sorting & pretty-printing)
#' @name tactics_f
#' @note Last updated: {upd}
#' @docType data
NULL
"), file = here::here("R/data-docs.R"))