~hrbrmstr/attckr

ab8cfb1c06666c2afde7a3cc71b36165319ff2c4 — hrbrmstr 11 months ago 8463f83
update to 2.0
M NAMESPACE => NAMESPACE +0 -1
@@ 2,7 2,6 @@

export(fct_tactic)
export(read_events)
export(tactics_f)
export(validate_tactics)
export(validate_technique_ids)
export(validate_techniques)

M R/data-docs.R => R/data-docs.R +22 -3
@@ 1,19 1,38 @@
#' @title Enterprise Attack Taxonomy
# This file is autogenerated from tools/update-framework.R
# DO NOT MODIFY BY HAND as all changes will be overwritten

#' @title Enterprise Attack Taxonomy v2.0
#' @name enterprise_attack
#' @note Id: `bundle--24c77e72-f42e-48e5-9f6c-5ddfc02e8399`
#' @note Last updated: 2019-07-31
#' @references <https://github.com/mitre/cti/raw/master/enterprise-attack/enterprise-attack.json>
#' @docType data
NULL

#' @title Mobile Attack Taxonomy
#' @title Mobile Attack Taxonomy v2.0
#' @name mobile_attack
#' @note Id: `bundle--eeb1ff74-2747-4602-96fb-e7b220361101`
#' @note Last updated: 2019-07-31
#' @references <https://github.com/mitre/cti/raw/master/mobile-attack/mobile-attack.json>
#' @docType data
NULL

#' @title Pre-Attack Taxonomy
#' @title Pre-Attack Taxonomy v2.0
#' @name pre_attack
#' @note Id: `bundle--0bf62d3b-a5a3-4dae-996d-e990ca6e2f4d`
#' @note Last updated: 2019-07-31
#' @references <https://github.com/mitre/cti/raw/master/pre-attack/pre-attack.json>
#' @docType data
NULL

#' @title Combined ATT&CK Matricies Tactics, Techniques and Technique detail
#' @name tidy_attack
#' @note Last updated: 2019-07-31
#' @docType data
NULL

#' @title Tactics factors (generally for sorting & pretty-printing)
#' @name tactics_f
#' @note Last updated: 2019-07-31
#' @docType data
NULL
\ No newline at end of file

M R/fct-tactic.R => R/fct-tactic.R +18 -7
@@ 1,18 1,29 @@
#' Make an ordered Tactics factor with optional better labelling
#'
#' Uses the metadat in [tactics_f] to make it easier to build ordered factors.
#'
#' You may receive Tatics encoded in one of many forms, including:
#'
#' - `taid` (Tactic ID) the official MITRE ATT&CK tactic id (e.g. "`TA0001`")
#' - `id` (Tactic text id) lowercase-dashed name (e.g. "`initial-access`")
#' - `pretty` (Tactic text) Upper/lowercase name suitable for display (e.g. "`Initial Access`")
#' - `nl` (Tactic text) same as ^ but w/newlines for space constrained display (e.g. "`Initial\\nAccess`")
#'
#' @param tactics a character vector
#' @param input what is in `tactics`?
#' @param output what do you want the factor label to be?
#' @param matrix which matrix?
#' @param input what is in `tactics`? (See Details)
#' @param output what do you want the factor label to be? (See Details)
#' @param matrix which matrix? ("`enterprise`", "`mobile`", "`pre`")
#' @seealso [tactics_f] for direct access to the ordered Tactics
#' @export
#' @examples
#' fct_tactic(c("initial-access", "persistence"), "id", "nl")
fct_tactic <- function(tactics,
                       input = c("id", "pretty", "nl"),
                       output = c("pretty", "nl", "id"),
                       input = c("id", "pretty", "nl", "taid"),
                       output = c("pretty", "nl", "id", "taid"),
                       matrix = c("enterprise", "mobile", "pre")) {

  input <- match.arg(input[1], c("id", "pretty", "nl"))
  output <- match.arg(output[1], c("id", "pretty", "nl"))
  input <- match.arg(input[1], c("id", "pretty", "nl", "taid"))
  output <- match.arg(output[1], c("id", "pretty", "nl", "taid"))
  matrix <- match.arg(matrix[1], c("enterprise", "mobile", "pre"))

  switch(

D R/tactics-factors.R => R/tactics-factors.R +0 -76
@@ 1,76 0,0 @@
tactics_f <- list()

tactics_f[["mitre-attack"]] <- tibble(
  id = c(
    "initial-access", "execution", "persistence", "privilege-escalation",
    "defense-evasion", "credential-access", "discovery", "lateral-movement",
    "collection", "command-and-control", "exfiltration", "impact"
  ),
  pretty = c(
    "Initial Access", "Execution", "Persistence", "Privilege Escalation",
    "Defense Evasion", "Credential Access", "Discovery", "Lateral Movement",
    "Collection", "Command & Control", "Exfiltration", "Impact"
  ),
  nl = c(
    "Initial\nAccess", "Execution", "Persistence", "Privilege\nEscalation",
    "Defense\nEvasion", "Credential\nAccess", "Discovery", "Lateral\nMovement",
    "Collection", "Command\n&\nControl", "Exfiltration", "Impact"
  )
)

tactics_f[["mitre-pre-attack"]] <- tibble(
  id = c(
    "priority-definition-planning", "priority-definition-direction",
    "target-selection", "technical-information-gathering",
    "people-information-gathering", "organizational-information-gathering",
    "technical-weakness-identification", "people-weakness-identification",
    "organizational-weakness-identification", "adversary-opsec",
    "establish-&-maintain-infrastructure", "persona-development",
    "build-capabilities", "test-capabilities", "stage-capabilities",
    "launch", "compromise"
  ),
  pretty = c(
    "Priority Definition Planning", "Priority Definition Direction",
    "Target Selection", "Technical Information Gathering", "People Information Gathering",
    "Organizational Information Gathering", "Technical Weakness Identification",
    "People Weakness Identification", "Organizational Weakness Identification",
    "Adversary Opsec", "Establish & Maintain Infrastructure", "Persona Development",
    "Build Capabilities", "Test Capabilities", "Stage Capabilities",
    "Launch", "Compromise"
  ),
  nl = c(
    "Priority\nDefinition\nPlanning", "Priority\nDefinition\nDirection",
    "Target\nSelection", "Technical\nInformation\nGathering", "People\nInformation\nGathering",
    "Organizational\nInformation\nGathering", "Technical\nWeakness\nIdentification",
    "People\nWeakness\nIdentification", "Organizational\nWeakness\nIdentification",
    "Adversary\nOpsec", "Establish\n&\nMaintain\nInfrastructure",
    "Persona\nDevelopment", "Build\nCapabilities", "Test\nCapabilities",
    "Stage\nCapabilities", "Launch", "Compromise"
  )
)

tactics_f[["mitre-mobile-attack"]] <- tibble(
  id = c(
    "initial-access", "persistence", "privilege-escalation", "defense-evasion",
    "credential-access", "discovery", "lateral-movement", "effects", "network-effects",
    "remote-service-effects", "collection", "exfiltration", "command-and-control"
  ),
  pretty = c(
    "Initial Access", "Persistence", "Privilege Escalation", "Defense Evasion",
    "Credential Access", "Discovery", "Lateral Movement", "Effects",
    "Network Effects", "Remote Service Effects", "Collection", "Exfiltration",
    "Command & Control"
  ),
  nl = c(
    "Initial\nAccess", "Persistence", "Privilege\nEscalation",
    "Defense\nEvasion", "Credential\nAccess", "Discovery", "Lateral\nMovement",
    "Effects", "Network\nEffects", "Remote\nService\nEffects", "Collection",
    "Exfiltration", "Command\n&\nControl"
  )
)

#' @title Tactics factors (generally for sorting & pretty-printing)
#' @name tactics_f
#' @docType data
#' @export
NULL

M README.Rmd => README.Rmd +10 -0
@@ 1,5 1,7 @@
---
output: rmarkdown::github_document
editor_options: 
  chunk_output_type: console
---
```{r pkg-knitr-opts, include=FALSE}
hrbrpkghelpr::global_opts()


@@ 21,6 23,14 @@ The following functions are implemented:
hrbrpkghelpr::describe_ingredients()
```

The following datasets are included:

```{r datasets, echo=FALSE, results="asis"}
d <- as.data.frame(data(package = "attckr")$results[,c("Item", "Title")], stringsAsFactors=FALSE)
d$Item <- sprintf("`%s`", d$Item)
cat(sprintf("- %s: %s", d$Item, d$Title), sep="\n")
```

## Installation

```{r install-ex, results='asis', echo=FALSE, cache=FALSE}

M README.md => README.md +17 -7
@@ 32,11 32,11 @@ CTI Corpus.

The following functions are implemented:

  - `enterprise_attack`: Enterprise Attack Taxonomy
  - `enterprise_attack`: Enterprise Attack Taxonomy v2.0
  - `fct_tactic`: Make an ordered Tactics factor with optional better
    labelling
  - `mobile_attack`: Mobile Attack Taxonomy
  - `pre_attack`: Pre-Attack Taxonomy
  - `mobile_attack`: Mobile Attack Taxonomy v2.0
  - `pre_attack`: Pre-Attack Taxonomy v2.0
  - `read_events`: Read in ATT\&CK events from a file
  - `tactics_f`: Tactics factors (generally for sorting &
    pretty-printing)


@@ 48,6 48,16 @@ The following functions are implemented:
  - `validate_techniques`: Validate Techniques strings against MITRE
    authoritative source

The following datasets are included:

  - `enterprise_attack`: Enterprise Attack Taxonomy v2.0
  - `mobile_attack`: Mobile Attack Taxonomy v2.0
  - `pre_attack`: Pre-Attack Taxonomy v2.0
  - `tactics_f`: Tactics factors (generally for sorting &
    pretty-printing)
  - `tidy_attack`: Combined ATT\&CK Matricies Tactics, Techniques and
    Technique detail

## Installation

``` r


@@ 137,10 147,10 @@ count(head(events, 30), tactic, technique) %>%

## attckr Metrics

| Lang | \# Files |  (%) | LoC | (%) | Blank lines |  (%) | \# Lines |  (%) |
| :--- | -------: | ---: | --: | --: | ----------: | ---: | -------: | ---: |
| R    |       11 | 0.92 | 270 | 0.9 |          59 | 0.77 |      121 | 0.81 |
| Rmd  |        1 | 0.08 |  29 | 0.1 |          18 | 0.23 |       29 | 0.19 |
| Lang | \# Files |  (%) | LoC |  (%) | Blank lines |  (%) | \# Lines |  (%) |
| :--- | -------: | ---: | --: | ---: | ----------: | ---: | -------: | ---: |
| R    |       10 | 0.91 | 203 | 0.86 |          57 | 0.74 |      144 | 0.81 |
| Rmd  |        1 | 0.09 |  32 | 0.14 |          20 | 0.26 |       34 | 0.19 |

## Code of Conduct


M data-raw/enterprise-attack.json.xz => data-raw/enterprise-attack.json.xz +0 -0

M data-raw/mobile-attack.json.xz => data-raw/mobile-attack.json.xz +0 -0

M data-raw/pre-attack.json.xz => data-raw/pre-attack.json.xz +0 -0

M data/enterprise_attack.rda => data/enterprise_attack.rda +0 -0

M data/mobile_attack.rda => data/mobile_attack.rda +0 -0

M data/pre_attack.rda => data/pre_attack.rda +0 -0

A data/tactics_f.rda => data/tactics_f.rda +0 -0

M data/tidy_attack.rda => data/tidy_attack.rda +0 -0

M man/enterprise_attack.Rd => man/enterprise_attack.Rd +10 -2
@@ 3,7 3,15 @@
\docType{data}
\name{enterprise_attack}
\alias{enterprise_attack}
\title{Enterprise Attack Taxonomy}
\title{Enterprise Attack Taxonomy v2.0}
\description{
Enterprise Attack Taxonomy
Enterprise Attack Taxonomy v2.0
}
\note{
Id: \code{bundle--24c77e72-f42e-48e5-9f6c-5ddfc02e8399}

Last updated: 2019-07-31
}
\references{
\url{https://github.com/mitre/cti/raw/master/enterprise-attack/enterprise-attack.json}
}

M man/fct_tactic.Rd => man/fct_tactic.Rd +19 -7
@@ 4,21 4,33 @@
\alias{fct_tactic}
\title{Make an ordered Tactics factor with optional better labelling}
\usage{
fct_tactic(tactics, input = c("id", "pretty", "nl"),
  output = c("pretty", "nl", "id"), matrix = c("enterprise", "mobile",
  "pre"))
fct_tactic(tactics, input = c("id", "pretty", "nl", "taid"),
  output = c("pretty", "nl", "id", "taid"), matrix = c("enterprise",
  "mobile", "pre"))
}
\arguments{
\item{tactics}{a character vector}

\item{input}{what is in \code{tactics}?}
\item{input}{what is in \code{tactics}? (See Details)}

\item{output}{what do you want the factor label to be?}
\item{output}{what do you want the factor label to be? (See Details)}

\item{matrix}{which matrix?}
\item{matrix}{which matrix? ("\code{enterprise}", "\code{mobile}", "\code{pre}")}
}
\description{
Make an ordered Tactics factor with optional better labelling
Uses the metadat in \link{tactics_f} to make it easier to build ordered factors.
}
\details{
You may receive Tatics encoded in one of many forms, including:
\itemize{
\item \code{taid} (Tactic ID) the official MITRE ATT&CK tactic id (e.g. "\code{TA0001}")
\item \code{id} (Tactic text id) lowercase-dashed name (e.g. "\code{initial-access}")
\item \code{pretty} (Tactic text) Upper/lowercase name suitable for display (e.g. "\code{Initial Access}")
\item \code{nl} (Tactic text) same as ^ but w/newlines for space constrained display (e.g. "\code{Initial\\nAccess}")
}
}
\examples{
fct_tactic(c("initial-access", "persistence"), "id", "nl")
}
\seealso{
\link{tactics_f} for direct access to the ordered Tactics

M man/figures/README-events-1.png => man/figures/README-events-1.png +0 -0

M man/mobile_attack.Rd => man/mobile_attack.Rd +10 -2
@@ 3,7 3,15 @@
\docType{data}
\name{mobile_attack}
\alias{mobile_attack}
\title{Mobile Attack Taxonomy}
\title{Mobile Attack Taxonomy v2.0}
\description{
Mobile Attack Taxonomy
Mobile Attack Taxonomy v2.0
}
\note{
Id: \code{bundle--eeb1ff74-2747-4602-96fb-e7b220361101}

Last updated: 2019-07-31
}
\references{
\url{https://github.com/mitre/cti/raw/master/mobile-attack/mobile-attack.json}
}

M man/pre_attack.Rd => man/pre_attack.Rd +10 -2
@@ 3,7 3,15 @@
\docType{data}
\name{pre_attack}
\alias{pre_attack}
\title{Pre-Attack Taxonomy}
\title{Pre-Attack Taxonomy v2.0}
\description{
Pre-Attack Taxonomy
Pre-Attack Taxonomy v2.0
}
\note{
Id: \code{bundle--0bf62d3b-a5a3-4dae-996d-e990ca6e2f4d}

Last updated: 2019-07-31
}
\references{
\url{https://github.com/mitre/cti/raw/master/pre-attack/pre-attack.json}
}

M man/tactics_f.Rd => man/tactics_f.Rd +4 -1
@@ 1,5 1,5 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/tactics-factors.R
% Please edit documentation in R/data-docs.R
\docType{data}
\name{tactics_f}
\alias{tactics_f}


@@ 7,3 7,6 @@
\description{
Tactics factors (generally for sorting & pretty-printing)
}
\note{
Last updated: 2019-07-31
}

M man/tidy_attack.Rd => man/tidy_attack.Rd +3 -0
@@ 7,3 7,6 @@
\description{
Combined ATT&CK Matricies Tactics, Techniques and Technique detail
}
\note{
Last updated: 2019-07-31
}

M tools/update-framework.R => tools/update-framework.R +133 -31
@@ 1,6 1,11 @@
## code to prepare `enterprise_attack` dataset goes here
# 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(


@@ 13,25 18,25 @@ unlink(
  ))
)

# 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(
    "https://github.com/mitre/cti/raw/master/enterprise-attack/enterprise-attack.json",
    "https://github.com/mitre/cti/raw/master/mobile-attack/mobile-attack.json",
    "https://github.com/mitre/cti/raw/master/pre-attack/pre-attack.json"
  ),
  url = c(ent_url, mob_url, pre_url),
  destfile = c(
    here::here(
      "data-raw",
      c(
        "enterprise-attack.json",
        "mobile-attack.json",
        "pre-attack.json"
      )
      c("enterprise-attack.json", "mobile-attack.json", "pre-attack.json")
    )
  ),
  method = "libcurl"
)

# Compress new JSON -------------------------------------------------------

walk(
  here::here(
    "data-raw",


@@ 44,24 49,33 @@ walk(
  ~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)


@@ 100,30 114,118 @@ bind_rows(
  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

# Save it all out ---------------------------------------------------------

usethis::use_data(
  enterprise_attack, mobile_attack, pre_attack, tidy_attack,
  enterprise_attack, mobile_attack, pre_attack, tidy_attack, tactics_f,
  internal = FALSE,
  overwrite = TRUE,
  compress = "xz"
)

bind_rows(enterprise_attack$objects$kill_chain_phases) %>%
  distinct(phase_name)

















# 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"))