If you are reading this blog post via a 3rd party source it is very likely that many parts of it will not render correctly (usually, the interactive graphs). Please view the post on dogesec.com for the full interactive viewing experience.

tl;dr

Your handy guide to streamlining upgrades of MITRE ATT&CK by comparing the changes made between releases.

Key Findings

  • ATT&CK Enterprise
    • 70 new objects
    • 378 modified objects
    • 1318 unchanged objects
    • 0 deprecated objects
    • 0 revoked objects
  • ATT&CK Mobile
    • 0 new objects
    • 10 modified objects
    • 287 unchanged objects
    • 1 deprecated objects
    • 0 revoked objects
  • ATT&CK ICS
    • 1 new objects
    • 18 modified objects
    • 275 unchanged objects
    • 0 deprecated objects
    • 0 revoked objects

Overview

The team at MITRE recently announced the launch of ATT&CK v16.0.

We are big users of ATT&CK, using it to add additional context to our intelligence. You might have seen my fanboy post earlier this year describing the structure of the ATT&CK framework.

Whilst the ATT&CK team keep a great change-log in their release notes, I wanted to dive deeper into the changes to better understand the changes.

This post walks you through my analysis.

Follow along

In this post I am going to provide ArangoDB queries you can use to analyse and filter MITRE ATT&CK data.

If you would like to follow along, and keep a searchable copy of ATT&CK locally, you can import the data using stix2arango.

Once you’ve installed stix2arango, you can run the following command to import all versions of the MITRE ATT&CK Enterprise, ICS, and Mobile datasets at the time of writing;

python3 utilities/arango_cti_processor/insert_archive_attack_enterprise.py \
    --database blog_demo \
    --ignore_embedded_relationships True && \
python3 utilities/arango_cti_processor/insert_archive_attack_ics.py \
    --database blog_demo \
    --ignore_embedded_relationships True && \
python3 utilities/arango_cti_processor/insert_archive_attack_mobile.py \
    --database blog_demo \
    --ignore_embedded_relationships True

You can then use the query interface in the ArangoDB UI to run the AQL queries in this post.

Note, in this post I show queries searching the Enterprise domain (mitre_attack_enterprise_vertex_collection), but show results for all matrices. To get the data for each matrix all you need to do is modify enterprise for ics or mobile to get the results for the specified matrix.

ATT&CK through the ages

To begin, here is a query that shows the growth of the ATT&CK matrices over each release;

FOR doc IN mitre_attack_enterprise_vertex_collection
FILTER doc._stix2arango_note != "automatically imported on collection creation"
AND doc.x_mitre_deprecated != true
AND doc.revoked != true
COLLECT version = doc._stix2arango_note WITH COUNT INTO count
RETURN { "version": version, "count": count }

ATT&CK Enterprise Objects by version

ATT&CK Mobile Objects by version

ATT&CK ICS Objects by version

ATT&CK objects changes between version 15.1 and 16.0

This query looks at each object type and shows the count of those that have been changed, added, deprecated, revoked, or have stayed the same between 15.1 and 16.0;

FOR doc IN mitre_attack_enterprise_vertex_collection
FILTER doc._stix2arango_note IN ["v15.1", "v16.0"]
COLLECT id = doc.id, type = doc.type INTO groupedDocs

LET versions = groupedDocs[*].doc
LET createdDates = UNIQUE(versions[*].created)
LET modifiedDates = UNIQUE(versions[*].modified)
LET count_versions = LENGTH(versions)

LET deprecatedInV16 = LENGTH(FOR v IN versions FILTER v._stix2arango_note == "v16.0" AND v.x_mitre_deprecated == true RETURN v) > 0
LET deprecatedInV15 = LENGTH(FOR v IN versions FILTER v._stix2arango_note == "v15.1" AND v.x_mitre_deprecated == true RETURN v) > 0

LET revokedInV16 = LENGTH(FOR v IN versions FILTER v._stix2arango_note == "v16.0" AND v.revoked == true RETURN v) > 0
LET revokedInV15 = LENGTH(FOR v IN versions FILTER v._stix2arango_note == "v15.1" AND v.revoked == true RETURN v) > 0

// Filter out results where x_mitre_deprecated or revoked is true in both versions
FILTER NOT (deprecatedInV15 == true AND deprecatedInV16 == true)
FILTER NOT (revokedInV15 == true AND revokedInV16 == true)

LET status = (
    count_versions == 1 ? "new" :
    (revokedInV16 == true AND revokedInV15 == false ? "revoked" :
    (deprecatedInV16 == true AND deprecatedInV15 == false ? "deprecated" :
    (LENGTH(createdDates) == 1 AND LENGTH(modifiedDates) == 1 ? "unchanged" : "changed")))
)

COLLECT finalStatus = status, finalType = type WITH COUNT INTO count

// Aggregate results by status
COLLECT status = finalStatus INTO typeCounts = {
  "type": finalType,
  "count": count
}

// Construct dynamic columns for each type
RETURN MERGE(
  { "status": status },
  ZIP(
    typeCounts[*].type,
    typeCounts[*].count
  )
)

ATT&CK Enterprise Object type by version

ATT&CK Mobile Object type by version

ATT&CK ICS Object type by version

New ATT&CK objects changes between version v15.1 and v16.0

This query will produce a list of objects that have been added in version 16.0;

FOR doc IN mitre_attack_enterprise_vertex_collection
FILTER doc._stix2arango_note IN ["v15.1", "v16.0"]
COLLECT id = doc.id INTO groupedDocs

LET versions = groupedDocs[*].doc
LET count_versions = LENGTH(versions)

// Only include objects that are classified as "new" (present in only one version)
FILTER count_versions == 1

// Extract external_id where source_name is "mitre-attack"
LET mitre_attack_id = FIRST(
    FOR ref IN versions[0].external_references
    FILTER ref.source_name == "mitre-attack"
    RETURN ref.external_id
)

// Return only the specified fields
RETURN {
    "type": versions[0].type,
    "external_id": mitre_attack_id,
    "name": versions[0].name
}

New objects in ATT&CK Enterprise v16.0

type external_id name
attack-pattern T1666 Modify Cloud Resource Hierarchy
attack-pattern T1485.001 Lifecycle-Triggered Deletion
attack-pattern T1496.003 SMS Pumping
attack-pattern T1071.005 Publish/Subscribe Protocols
attack-pattern T1558.005 Ccache Files
attack-pattern T1098.007 Additional Local or Domain Groups
attack-pattern T1557.004 Evil Twin
attack-pattern T1480.002 Mutual Exclusion
attack-pattern T1496.002 Bandwidth Hijacking
attack-pattern T1496.004 Cloud Service Hijacking
attack-pattern T1496.001 Compute Hijacking
attack-pattern T1059.011 Lua
attack-pattern T1027.014 Polymorphic Code
attack-pattern T1213.004 Customer Relationship Management Software
attack-pattern T1127.002 ClickOnce
attack-pattern T1070.010 Relocate Malware
attack-pattern T1036.010 Masquerade Account Name
attack-pattern T1546.017 Udev Rules
attack-pattern T1213.005 Messaging Applications
campaign C0035 KV Botnet Activity
campaign C0037 Water Curupira Pikabot Distribution
campaign C0038 HomeLand Justice
campaign C0036 Pikabot Distribution February 2024
campaign C0040 APT41 DUST
campaign C0039 Versa Director Zero Day Exploitation
course-of-action M1060 Out-of-Band Communications Channel
intrusion-set G1037 TA577
intrusion-set G1031 Saint Bear
intrusion-set G1035 Winter Vivern
intrusion-set G1039 RedCurl
intrusion-set G1033 Star Blizzard
intrusion-set G1038 TA578
intrusion-set G1030 Agrius
intrusion-set G1032 INC Ransom
intrusion-set G1036 Moonstone Sleet
intrusion-set G1040 Play
intrusion-set G1034 Daggerfly
malware S1145 Pikabot
malware S1154 VersaMem
malware S1162 Playcrypt
malware S1152 IMAPLoader
malware S1159 DUSTTRAP
malware S1158 DUSTPAN
malware S1138 Gootloader
malware S1153 Cuckoo Stealer
malware S1137 Moneybird
malware S1133 Apostle
malware S1130 Raspberry Robin
malware S1147 Nightdoor
malware S1149 CHIMNEYSWEEP
malware S1010 VPNFilter
malware S1143 LunarLoader
malware S1135 MultiLayer Wiper
malware S1160 Latrodectus
malware S1140 Spica
malware S1161 BPFDoor
malware S1151 ZeroCleare
malware S1146 MgBot
malware S1142 LunarMail
malware S1148 Raccoon Stealer
malware S1132 IPsec Helper
malware S1150 ROADSWEEP
malware S1136 BFG Agonizer
malware S1156 Manjusaka
malware S1141 LunarWeb
malware S1139 INC Ransomware
malware S1134 DEADWOOD
tool S1155 Covenant
tool S1131 NPPSPY

New objects in ATT&CK Mobile v16.0

None.

New objects in ATT&CK ICS v16.0

type external_id name
malware S1157 Fuxnet

ATT&CK changes

To get a similar list of changed objects between versions, you can run the query;

FOR doc IN mitre_attack_enterprise_vertex_collection
FILTER doc._stix2arango_note IN ["v15.1", "v16.0"]
COLLECT id = doc.id INTO groupedDocs

LET versions = groupedDocs[*].doc
LET createdDates = UNIQUE(versions[*].created)
LET modifiedDates = UNIQUE(versions[*].modified)
LET count_versions = LENGTH(versions)

LET deprecatedInV16 = LENGTH(FOR v IN versions FILTER v._stix2arango_note == "v16.0" AND v.x_mitre_deprecated == true RETURN v) > 0
LET deprecatedInV15 = LENGTH(FOR v IN versions FILTER v._stix2arango_note == "v15.1" AND v.x_mitre_deprecated == true RETURN v) > 0

LET revokedInV16 = LENGTH(FOR v IN versions FILTER v._stix2arango_note == "v16.0" AND v.revoked == true RETURN v) > 0
LET revokedInV15 = LENGTH(FOR v IN versions FILTER v._stix2arango_note == "v15.1" AND v.revoked == true RETURN v) > 0

// Filter out results where x_mitre_deprecated or revoked is true in both versions
FILTER NOT (deprecatedInV15 == true AND deprecatedInV16 == true)
FILTER NOT (revokedInV15 == true AND revokedInV16 == true)

// Only include objects that are classified as "changed" (present in both versions with differences in created or modified dates)
LET status = (
    count_versions == 1 ? "new" :
    (revokedInV16 == true AND revokedInV15 == false ? "revoked" :
    (deprecatedInV16 == true AND deprecatedInV15 == false ? "deprecated" :
    (LENGTH(createdDates) == 1 AND LENGTH(modifiedDates) == 1 ? "unchanged" : "changed")))
)

FILTER status == "changed"

// Safely extract external_id where source_name is "mitre-attack", handling missing external_references
LET mitre_attack_id = FIRST(
    FOR ref IN versions[0].external_references || []
    FILTER ref.source_name == "mitre-attack"
    RETURN ref.external_id
)

// Return only the specified fields
RETURN {
    "type": versions[0].type,
    "external_id": mitre_attack_id,
    "name": versions[0].name
}

Once you have a list of IDs returned by the above query, you can use the following query to identify the properties changed. For example, here I am comparing T1053.005 (Scheduled Task/Job: Scheduled Task) between version 15.1 and 16.0.

// Specify the ID of the object to compare
LET target_id = "T1053.005"

// Gather both versions
LET docs = (
    FOR doc IN mitre_attack_enterprise_vertex_collection
    FILTER doc._stix2arango_note IN ["v15.1", "v16.0"]
    AND "mitre-attack" IN doc.external_references[*].source_name
    AND target_id IN doc.external_references[*].external_id
    RETURN { "version": doc._stix2arango_note, "doc": doc }
)

// Extract the documents for v15.1 and v16.0
LET v15_1 = FIRST(FOR d IN docs FILTER d.version == "v15.1" RETURN d.doc) || null
LET v16_0 = FIRST(FOR d IN docs FILTER d.version == "v16.0" RETURN d.doc) || null

// Only proceed if both versions are available
RETURN (v15_1 != null AND v16_0 != null) ? {
    "id": target_id,
    "differences": (
        FOR key IN ATTRIBUTES(v15_1)
        FILTER v15_1[key] != v16_0[key]
        AND !STARTS_WITH(key, "_")  // Exclude keys starting with an underscore
        RETURN {
            "field": key,
            "v15.1": v15_1[key],
            "v16.0": v16_0[key]
        }
    )
} : {
    "id": target_id,
    "error": "One or both versions are missing for comparison."
}
[
  {
    "id": "T1053.005",
    "differences": [
      {
        "field": "modified",
        "v15.1": "2023-11-15T14:33:53.354Z",
        "v16.0": "2024-10-13T16:13:47.770Z"
      },
      {
        "field": "external_references",
        "v15.1": [
          {
            "source_name": "mitre-attack",
            "url": "https://attack.mitre.org/techniques/T1053/005",
            "external_id": "T1053.005"
          },
          {
            "source_name": "ProofPoint Serpent",
            "description": "Campbell, B. et al. (2022, March 21). Serpent, No Swiping! New Backdoor Targets French Entities with Unique Attack Chain. Retrieved April 11, 2022.",
            "url": "https://www.proofpoint.com/us/blog/threat-insight/serpent-no-swiping-new-backdoor-targets-french-entities-unique-attack-chain"
          },
          {
            "source_name": "Defending Against Scheduled Task Attacks in Windows Environments",
            "description": "Harshal Tupsamudre. (2022, June 20). Defending Against Scheduled Tasks. Retrieved July 5, 2022.",
            "url": "https://blog.qualys.com/vulnerabilities-threat-research/2022/06/20/defending-against-scheduled-task-attacks-in-windows-environments"
          },
          {
            "source_name": "Twitter Leoloobeek Scheduled Task",
            "description": "Loobeek, L. (2017, December 8). leoloobeek Status. Retrieved December 12, 2017.",
            "url": "https://twitter.com/leoloobeek/status/939248813465853953"
          },
          {
            "source_name": "Tarrask scheduled task",
            "description": "Microsoft Threat Intelligence Team & Detection and Response Team . (2022, April 12). Tarrask malware uses scheduled tasks for defense evasion. Retrieved June 1, 2022.",
            "url": "https://www.microsoft.com/security/blog/2022/04/12/tarrask-malware-uses-scheduled-tasks-for-defense-evasion/"
          },
          {
            "source_name": "Microsoft Scheduled Task Events Win10",
            "description": "Microsoft. (2017, May 28). Audit Other Object Access Events. Retrieved June 27, 2019.",
            "url": "https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/audit-other-object-access-events"
          },
          {
            "source_name": "TechNet Scheduled Task Events",
            "description": "Microsoft. (n.d.). General Task Registration. Retrieved December 12, 2017.",
            "url": "https://technet.microsoft.com/library/dd315590.aspx"
          },
          {
            "source_name": "TechNet Autoruns",
            "description": "Russinovich, M. (2016, January 4). Autoruns for Windows v13.51. Retrieved June 6, 2016.",
            "url": "https://technet.microsoft.com/en-us/sysinternals/bb963902"
          },
          {
            "source_name": "TechNet Forum Scheduled Task Operational Setting",
            "description": "Satyajit321. (2015, November 3). Scheduled Tasks History Retention settings. Retrieved December 12, 2017.",
            "url": "https://social.technet.microsoft.com/Forums/en-US/e5bca729-52e7-4fcb-ba12-3225c564674c/scheduled-tasks-history-retention-settings?forum=winserver8gen"
          },
          {
            "source_name": "SigmaHQ",
            "description": "Sittikorn S. (2022, April 15). Removal Of SD Value to Hide Schedule Task - Registry. Retrieved June 1, 2022.",
            "url": "https://github.com/SigmaHQ/sigma/blob/master/rules/windows/registry/registry_delete/registry_delete_schtasks_hide_task_via_sd_value_removal.yml"
          }
        ],
        "v16.0": [
          {
            "source_name": "mitre-attack",
            "url": "https://attack.mitre.org/techniques/T1053/005",
            "external_id": "T1053.005"
          },
          {
            "source_name": "ProofPoint Serpent",
            "description": "Campbell, B. et al. (2022, March 21). Serpent, No Swiping! New Backdoor Targets French Entities with Unique Attack Chain. Retrieved April 11, 2022.",
            "url": "https://www.proofpoint.com/us/blog/threat-insight/serpent-no-swiping-new-backdoor-targets-french-entities-unique-attack-chain"
          },
          {
            "source_name": "Defending Against Scheduled Task Attacks in Windows Environments",
            "description": "Harshal Tupsamudre. (2022, June 20). Defending Against Scheduled Tasks. Retrieved July 5, 2022.",
            "url": "https://blog.qualys.com/vulnerabilities-threat-research/2022/06/20/defending-against-scheduled-task-attacks-in-windows-environments"
          },
          {
            "source_name": "Twitter Leoloobeek Scheduled Task",
            "description": "Loobeek, L. (2017, December 8). leoloobeek Status. Retrieved September 12, 2024.",
            "url": "https://x.com/leoloobeek/status/939248813465853953"
          },
          {
            "source_name": "Tarrask scheduled task",
            "description": "Microsoft Threat Intelligence Team & Detection and Response Team . (2022, April 12). Tarrask malware uses scheduled tasks for defense evasion. Retrieved June 1, 2022.",
            "url": "https://www.microsoft.com/security/blog/2022/04/12/tarrask-malware-uses-scheduled-tasks-for-defense-evasion/"
          },
          {
            "source_name": "Microsoft Scheduled Task Events Win10",
            "description": "Microsoft. (2017, May 28). Audit Other Object Access Events. Retrieved June 27, 2019.",
            "url": "https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/audit-other-object-access-events"
          },
          {
            "source_name": "TechNet Scheduled Task Events",
            "description": "Microsoft. (n.d.). General Task Registration. Retrieved December 12, 2017.",
            "url": "https://technet.microsoft.com/library/dd315590.aspx"
          },
          {
            "source_name": "Red Canary - Atomic Red Team",
            "description": "Red Canary - Atomic Red Team. (n.d.). T1053.005 - Scheduled Task/Job: Scheduled Task. Retrieved June 19, 2024.",
            "url": "https://github.com/redcanaryco/atomic-red-team/blob/master/atomics/T1053.005/T1053.005.md"
          },
          {
            "source_name": "TechNet Autoruns",
            "description": "Russinovich, M. (2016, January 4). Autoruns for Windows v13.51. Retrieved June 6, 2016.",
            "url": "https://technet.microsoft.com/en-us/sysinternals/bb963902"
          },
          {
            "source_name": "TechNet Forum Scheduled Task Operational Setting",
            "description": "Satyajit321. (2015, November 3). Scheduled Tasks History Retention settings. Retrieved December 12, 2017.",
            "url": "https://social.technet.microsoft.com/Forums/en-US/e5bca729-52e7-4fcb-ba12-3225c564674c/scheduled-tasks-history-retention-settings?forum=winserver8gen"
          },
          {
            "source_name": "SigmaHQ",
            "description": "Sittikorn S. (2022, April 15). Removal Of SD Value to Hide Schedule Task - Registry. Retrieved June 1, 2022.",
            "url": "https://github.com/SigmaHQ/sigma/blob/master/rules/windows/registry/registry_delete/registry_delete_schtasks_hide_task_via_sd_value_removal.yml"
          },
          {
            "source_name": "Stack Overflow",
            "description": "Stack Overflow. (n.d.). How to find the location of the Scheduled Tasks folder. Retrieved June 19, 2024.",
            "url": "https://stackoverflow.com/questions/2913816/how-to-find-the-location-of-the-scheduled-tasks-folder"
          }
        ]
      },
      {
        "field": "x_mitre_version",
        "v15.1": "1.5",
        "v16.0": "1.6"
      },
      {
        "field": "description",
        "v15.1": "Adversaries may abuse the Windows Task Scheduler to perform task scheduling for initial or recurring execution of malicious code. There are multiple ways to access the Task Scheduler in Windows. The [schtasks](https://attack.mitre.org/software/S0111) utility can be run directly on the command line, or the Task Scheduler can be opened through the GUI within the Administrator Tools section of the Control Panel. In some cases, adversaries have used a .NET wrapper for the Windows Task Scheduler, and alternatively, adversaries have used the Windows netapi32 library to create a scheduled task.\n\nThe deprecated [at](https://attack.mitre.org/software/S0110) utility could also be abused by adversaries (ex: [At](https://attack.mitre.org/techniques/T1053/002)), though <code>at.exe</code> can not access tasks created with <code>schtasks</code> or the Control Panel.\n\nAn adversary may use Windows Task Scheduler to execute programs at system startup or on a scheduled basis for persistence. The Windows Task Scheduler can also be abused to conduct remote Execution as part of Lateral Movement and/or to run a process under the context of a specified account (such as SYSTEM). Similar to [System Binary Proxy Execution](https://attack.mitre.org/techniques/T1218), adversaries have also abused the Windows Task Scheduler to potentially mask one-time execution under signed/trusted system processes.(Citation: ProofPoint Serpent)\n\nAdversaries may also create \"hidden\" scheduled tasks (i.e. [Hide Artifacts](https://attack.mitre.org/techniques/T1564)) that may not be visible to defender tools and manual queries used to enumerate tasks. Specifically, an adversary may hide a task from `schtasks /query` and the Task Scheduler by deleting the associated Security Descriptor (SD) registry value (where deletion of this value must be completed using SYSTEM permissions).(Citation: SigmaHQ)(Citation: Tarrask scheduled task) Adversaries may also employ alternate methods to hide tasks, such as altering the metadata (e.g., `Index` value) within associated registry keys.(Citation: Defending Against Scheduled Task Attacks in Windows Environments) ",
        "v16.0": "Adversaries may abuse the Windows Task Scheduler to perform task scheduling for initial or recurring execution of malicious code. There are multiple ways to access the Task Scheduler in Windows. The [schtasks](https://attack.mitre.org/software/S0111) utility can be run directly on the command line, or the Task Scheduler can be opened through the GUI within the Administrator Tools section of the Control Panel.(Citation: Stack Overflow) In some cases, adversaries have used a .NET wrapper for the Windows Task Scheduler, and alternatively, adversaries have used the Windows netapi32 library and [Windows Management Instrumentation](https://attack.mitre.org/techniques/T1047) (WMI) to create a scheduled task. Adversaries may also utilize the Powershell Cmdlet `Invoke-CimMethod`, which leverages WMI class `PS_ScheduledTask` to create a scheduled task via an XML path.(Citation: Red Canary - Atomic Red Team)\n\nAn adversary may use Windows Task Scheduler to execute programs at system startup or on a scheduled basis for persistence. The Windows Task Scheduler can also be abused to conduct remote Execution as part of Lateral Movement and/or to run a process under the context of a specified account (such as SYSTEM). Similar to [System Binary Proxy Execution](https://attack.mitre.org/techniques/T1218), adversaries have also abused the Windows Task Scheduler to potentially mask one-time execution under signed/trusted system processes.(Citation: ProofPoint Serpent)\n\nAdversaries may also create \"hidden\" scheduled tasks (i.e. [Hide Artifacts](https://attack.mitre.org/techniques/T1564)) that may not be visible to defender tools and manual queries used to enumerate tasks. Specifically, an adversary may hide a task from `schtasks /query` and the Task Scheduler by deleting the associated Security Descriptor (SD) registry value (where deletion of this value must be completed using SYSTEM permissions).(Citation: SigmaHQ)(Citation: Tarrask scheduled task) Adversaries may also employ alternate methods to hide tasks, such as altering the metadata (e.g., `Index` value) within associated registry keys.(Citation: Defending Against Scheduled Task Attacks in Windows Environments) "
      }
    ]
  }
]

A shout out to ATT&CK Sync

Having the objects in a database makes them easy to query however you choose.

Though many of you reading this will just want the review changes in a more simple manner. That’s where a nicely crafted web interface on top of these queries helps.

Enter ATT&CK Sync…

The ATT&CK Sync project streamlines upgrades to new versions of MITRE ATT&CK® by providing tools and resources to migrate existing projects to current ATT&CK versions in a timely and efficient manner.

Source: MITRE Engenuity

ATT&CK Sync T1053.005

Take the T1053.005 example I showed earlier. Whilst it only shows changes to the description, ATT&CK Sync makes it much easier to compare what was actually changed.

In fact, ATT&CK Sync was a big inspiration for the ATT&CK part of CTI Butler (which contains this feature for many popular CTI frameworks, not only ATT&CK).


CTI Butler

One API. Much CTI. CTI Butler is the API used by the world's leading cyber-security companies.

CTI Butler

Discuss this post

Head on over to the DOGESEC community to discuss this post.

DOGESEC community

Posted by:

David Greenwood

David Greenwood, Do Only Good Everyday



Never miss an update


Sign up to receive new articles in your inbox as they published.

Your subscription could not be saved. Please try again.
Your subscription has been successful.