diff --git a/detection/initial_access/sketchy-mounted-diskimage.sql b/detection/initial_access/sketchy-mounted-diskimage.sql index d91c0fb..160238e 100644 --- a/detection/initial_access/sketchy-mounted-diskimage.sql +++ b/detection/initial_access/sketchy-mounted-diskimage.sql @@ -44,6 +44,7 @@ WHERE OR file.directory LIKE mounts.path || "/%.app/Contents/MacOS/" OR file.directory LIKE mounts.path || "/%.app/Contents/Resources/" OR file.directory LIKE mounts.path || "/%/%.app/Contents/MacOS/" + OR file.directory LIKE mounts.path || "/%/%.app/Contents/Library/LaunchServices" OR file.directory LIKE mounts.path || "/%/%.app/Contents/Resources/" WHERE model = 'Disk Image' @@ -99,6 +100,7 @@ WHERE -- The rest are synced with sketchy-download-names OR vol_name LIKE "%.app%" + OR vol_name LIKE "%AnyDesk%" OR vol_name LIKE "%Advertising%" OR vol_name LIKE "%agreement%" OR vol_name LIKE "%animated%" diff --git a/detection/initial_access/yara-mounted-stealer.sql b/detection/initial_access/yara-mounted-stealer.sql new file mode 100644 index 0000000..a642a74 --- /dev/null +++ b/detection/initial_access/yara-mounted-stealer.sql @@ -0,0 +1,81 @@ +-- Look for sketchy mounted disk images, inspired by Shlayer +-- +-- references: +-- * https://attack.mitre.org/techniques/T1566/001/ (Phishing: Spearphishing Attachment) +-- * https://attack.mitre.org/techniques/T1204/002/ (User Execution: Malicious File) +-- * https://www.crowdstrike.com/blog/how-crowdstrike-uncovered-a-new-macos-browser-hijacking-campaign/ +-- +-- tags: volume filesystem +-- platform: darwin +SELECT + RTRIM(file.path, '/') AS f, + file.bsd_flags AS f_flags, + file.gid AS f_gid, + file.mode AS f_mode, + file.size AS f_size, + file.type AS f_type, + REGEX_MATCH (file.filename, '.*\.(.*?)$', 1) AS f_ext, + file.uid AS f_uid, + hash.sha256 AS f_sha256, + magic.data AS f_data, + mdfind.path AS probable_source, + mdhash.sha256 AS probable_source_sha256, + ea.value AS probable_url, + REGEX_MATCH (file.path, '/Volumes/(.*?)/', 1) AS vol_name, + signature.authority AS s_auth, + signature.identifier AS s_id, + yara.* +FROM + file + JOIN yara ON file.path = yara.path + LEFT JOIN mdfind ON mdfind.query = "kMDItemFSName == '*" || REGEX_MATCH (file.path, '/Volumes/(\w+)', 1) || "*.dmg'" + LEFT JOIN extended_attributes ea ON mdfind.path = ea.path + AND ea.key = 'where_from' + LEFT JOIN hash on file.path = hash.path + LEFT JOIN hash mdhash ON mdfind.path = mdhash.path + LEFT JOIN magic ON file.path = magic.path + LEFT JOIN signature ON file.path = signature.path +WHERE + file.path IN ( + SELECT + file.path + FROM + block_devices + JOIN mounts ON mounts.device = block_devices.name + JOIN file ON file.directory = mounts.path + OR file.directory LIKE mounts.path || "/%.app/Contents/MacOS/" + OR file.directory LIKE mounts.path || "/%.app/Contents/Resources/" + OR file.directory LIKE mounts.path || "/%/%.app/Contents/MacOS/" + OR file.directory LIKE mounts.path || "/%/%.app/Contents/Library/LaunchServices" + OR file.directory LIKE mounts.path || "/%/%.app/Contents/Resources/" + WHERE + model = 'Disk Image' + AND parent != "" + AND mounts.path LIKE "/Volumes/%" + -- osquery will traverse symlinks, this prevents following symlinks to /Applications (poorly) + AND file.path NOT LIKE "/Volumes/%/Applications/%" + AND ( + file.mode LIKE "%7%" + OR file.mode LIKE "%5%" + OR file.mode LIKE "%1%" + ) + AND file.type = "regular" + ) + AND magic.data LIKE "%Executable%" + AND yara.sigrule = ' + rule stealer { + strings: + $ds = "data_stealers" ascii + $lk = "/Library/Keychains" ascii + $cs = "cookies.sqlite" ascii + $mc = "moz_cookies" ascii + $og = "OperaGX" ascii + $bs = "BraveSoftware" ascii + $os = "osascript" ascii + $fgp = "find-generic-password" ascii + + condition: + 2 of them +}' + AND yara.count > 0 +GROUP BY file.path \ No newline at end of file diff --git a/detection/initial_access/yara-recently-downloaded-go-crypt-exec.sql b/detection/initial_access/yara-recently-downloaded-go-crypt-exec.sql new file mode 100644 index 0000000..8a9ed8a --- /dev/null +++ b/detection/initial_access/yara-recently-downloaded-go-crypt-exec.sql @@ -0,0 +1,42 @@ +-- Recently downloaded cryptexec program +SELECT + file.path, + file.size, + file.btime, + file.ctime, + file.mtime, + magic.data, + hash.sha256, + yara.* +FROM + file + JOIN yara ON file.path = yara.path + LEFT JOIN magic ON file.path = magic.path + LEFT JOIN hash ON file.path = hash.path +WHERE + -- Only scan recent downloads + ( + file.path LIKE '/home/%/Downloads/%' + OR file.path LIKE '/home/%/Downloads/%/%' + OR file.path LIKE '/Users/%/Downloads/%' + OR file.path LIKE '/Users/%/Downloads/%/%' + OR file.path LIKE '/Volumes/%' + OR file.path LIKE '/tmp/%' + OR file.path LIKE '/var/tmp/%' + ) + AND ( + file.btime > (strftime('%s', 'now') -432000) + OR file.ctime > (strftime('%s', 'now') -432000) + OR file.mtime > (strftime('%s', 'now') -432000) + ) + AND yara.sigrule = ' + rule cryptexec { + strings: + $cbc = "crypto/cipher.newCBC" ascii + $aes = "crypto/aes.newCipher" + $run = "os/exec.(*Cmd).Run" ascii + $exec = "os/exec.Command" ascii + condition: + 3 of them +}' + AND yara.count > 0 \ No newline at end of file diff --git a/detection/initial_access/yara-recently-downloaded-miner.sql b/detection/initial_access/yara-recently-downloaded-miner.sql new file mode 100644 index 0000000..5f1969f --- /dev/null +++ b/detection/initial_access/yara-recently-downloaded-miner.sql @@ -0,0 +1,39 @@ +-- Recently downloaded UPX file +SELECT + file.path, + file.size, + file.btime, + file.ctime, + file.mtime, + magic.data, + hash.sha256 +FROM + file + JOIN yara ON file.path = yara.path + LEFT JOIN magic ON file.path = magic.path + LEFT JOIN hash ON file.path = hash.path +WHERE + -- Only scan recent downloads + ( + file.path LIKE '/home/%/Downloads/%' + OR file.path LIKE '/Users/%/Downloads/%' + OR file.path LIKE '/tmp/%' + OR file.path LIKE '/var/tmp/%' + ) + AND ( + file.btime > (strftime('%s', 'now') -432000) + OR file.ctime > (strftime('%s', 'now') -432000) + OR file.mtime > (strftime('%s', 'now') -432000) + ) + AND yara.sigrule = ' + rule miner { + strings: + $tcp = "stratum+tcp://" ascii + $tls = "stratum+tls://" ascii + $ssl = "stratum+ssl://" ascii + $stratum = "stratum://" ascii + $normalhash = "\"normalHashing\": true," + condition: + filesize < 10MB and 1 of them +}' + AND yara.count > 0 \ No newline at end of file diff --git a/detection/initial_access/yara-recently-downloaded-ransom.sql b/detection/initial_access/yara-recently-downloaded-ransom.sql new file mode 100644 index 0000000..097c56e --- /dev/null +++ b/detection/initial_access/yara-recently-downloaded-ransom.sql @@ -0,0 +1,47 @@ +-- Recently downloaded UPX file +SELECT + file.path, + file.size, + file.btime, + file.ctime, + file.mtime, + magic.data, + hash.sha256, + yara.* +FROM + file + JOIN yara ON file.path = yara.path + LEFT JOIN magic ON file.path = magic.path + LEFT JOIN hash ON file.path = hash.path +WHERE + -- Only scan recent downloads + ( + file.path LIKE '/home/%/Downloads/%' + OR file.path LIKE '/home/%/Downloads/%/%' + OR file.path LIKE '/Users/%/Downloads/%' + OR file.path LIKE '/tmp/%' + OR file.path LIKE '/var/tmp/%' + ) + AND ( + file.btime > (strftime('%s', 'now') -432000) + OR file.ctime > (strftime('%s', 'now') -432000) + OR file.mtime > (strftime('%s', 'now') -432000) + ) + AND yara.sigrule = ' + rule ransomware { + strings: + $unfortunately = "unfortunately" ascii + $crypted = "crypted" ascii + $leaked = "leaked" ascii + $recover = "recover your" ascii + $leaks = "of leaks" ascii + $decrypt = "will decrypt" ascii + + $onion = ".onion/" ascii + $tor = "TOR Browser" ascii + + $esxcli = "esxcli" ascii + condition: + filesize < 10MB and 2 of them +}' + AND yara.count > 0 \ No newline at end of file diff --git a/detection/initial_access/yara-recently-downloaded-rust-http-exec.sql b/detection/initial_access/yara-recently-downloaded-rust-http-exec.sql new file mode 100644 index 0000000..160352c --- /dev/null +++ b/detection/initial_access/yara-recently-downloaded-rust-http-exec.sql @@ -0,0 +1,40 @@ +-- Recently downloaded cryptexec program +SELECT + file.path, + file.size, + file.btime, + file.ctime, + file.mtime, + magic.data, + hash.sha256, + yara.* +FROM + file + JOIN yara ON file.path = yara.path + LEFT JOIN magic ON file.path = magic.path + LEFT JOIN hash ON file.path = hash.path +WHERE + -- Only scan recent downloads + ( + file.path LIKE '/home/%/Downloads/%' + OR file.path LIKE '/home/%/Downloads/%/%' + OR file.path LIKE '/Users/%/Downloads/%' + OR file.path LIKE '/Users/%/Downloads/%/%' + OR file.path LIKE '/Volumes/%' + OR file.path LIKE '/tmp/%' + OR file.path LIKE '/var/tmp/%' + ) + AND ( + file.btime > (strftime('%s', 'now') -432000) + OR file.ctime > (strftime('%s', 'now') -432000) + OR file.mtime > (strftime('%s', 'now') -432000) + ) + AND yara.sigrule = ' +rule http_exec { + strings: + $http_proxy = "HTTP_PROXY" ascii + $process_unix = "process_unix.rs" ascii + condition: + all of them +}' + AND yara.count > 0 \ No newline at end of file diff --git a/detection/initial_access/yara-recently-downloaded-stealer.sql b/detection/initial_access/yara-recently-downloaded-stealer.sql new file mode 100644 index 0000000..0b06a84 --- /dev/null +++ b/detection/initial_access/yara-recently-downloaded-stealer.sql @@ -0,0 +1,46 @@ +-- Recently downloaded Stealer +SELECT + file.path, + file.size, + file.btime, + file.ctime, + file.mtime, + magic.data, + hash.sha256, + yara.* +FROM + file + JOIN yara ON file.path = yara.path + LEFT JOIN magic ON file.path = magic.path + LEFT JOIN hash ON file.path = hash.path +WHERE + -- Only scan recent downloads + ( + file.path LIKE '/home/%/Downloads/%' + OR file.path LIKE '/home/%/Downloads/%/%' + OR file.path LIKE '/Users/%/Downloads/%' + OR file.path LIKE '/Users/%/Downloads/%/%' + OR file.path LIKE '/tmp/%' + OR file.path LIKE '/var/tmp/%' + ) + AND ( + file.btime > (strftime('%s', 'now') -432000) + OR file.ctime > (strftime('%s', 'now') -432000) + OR file.mtime > (strftime('%s', 'now') -432000) + ) + AND yara.sigrule = ' + rule stealer { + strings: + $ds = "data_stealers" ascii + $lk = "/Library/Keychains" ascii + $cs = "cookies.sqlite" ascii + $mc = "moz_cookies" ascii + $og = "OperaGX" ascii + $bs = "BraveSoftware" ascii + $os = "osascript" ascii + $fgp = "find-generic-password" ascii + + condition: + 2 of them +}' + AND yara.count > 0 \ No newline at end of file diff --git a/detection/initial_access/yara-recently-downloaded-upx.sql b/detection/initial_access/yara-recently-downloaded-upx.sql new file mode 100644 index 0000000..64329a3 --- /dev/null +++ b/detection/initial_access/yara-recently-downloaded-upx.sql @@ -0,0 +1,37 @@ +-- Recently downloaded UPX file +SELECT + file.path, + file.size, + file.btime, + file.ctime, + file.mtime, + magic.data, + hash.sha256 +FROM + file + JOIN yara ON file.path = yara.path + LEFT JOIN magic ON file.path = magic.path + LEFT JOIN hash ON file.path = hash.path +WHERE + -- Only scan recent downloads + ( + file.path LIKE '/home/%/Downloads/%' + OR file.path LIKE '/Users/%/Downloads/%' + OR file.path LIKE '/Volumes/%' + OR file.path LIKE '/tmp/%' + OR file.path LIKE '/var/tmp/%' + ) + AND ( + file.btime > (strftime('%s', 'now') -432000) + OR file.ctime > (strftime('%s', 'now') -432000) + OR file.mtime > (strftime('%s', 'now') -432000) + ) + AND yara.sigrule = ' + rule upx { + strings: + $upx_sig = "UPX!" + + condition: + $upx_sig in (0..1024) + }' + AND yara.count > 0 \ No newline at end of file diff --git a/detection/persistence/yara-exec-connect-process-linux.sql b/detection/persistence/yara-exec-connect-process-linux.sql new file mode 100644 index 0000000..0c23c82 --- /dev/null +++ b/detection/persistence/yara-exec-connect-process-linux.sql @@ -0,0 +1,62 @@ +-- Currently running program with Linux red flags +-- +-- reference: +-- * bpfdoor (old) +-- +-- tags: persistent +-- interval: 7200 +-- platform: linux +SELECT + yara.strings, + -- Child + p0.pid AS p0_pid, + p0.path AS p0_path, + p0.name AS p0_name, + p0.start_time AS p0_start, + p0.cmdline AS p0_cmd, + p0.cwd AS p0_cwd, + p0.cgroup_path AS p0_cgroup, + p0.euid AS p0_euid, + p0_hash.sha256 AS p0_sha256, + -- Parent + p0.parent AS p1_pid, + p1.path AS p1_path, + p1.name AS p1_name, + p1.start_time AS p1_start, + p1.euid AS p1_euid, + p1.cmdline AS p1_cmd, + p1_hash.sha256 AS p1_sha256, + -- Grandparent + p1.parent AS p2_pid, + p2.name AS p2_name, + p2.start_time AS p2_start, + p2.path AS p2_path, + p2.cmdline AS p2_cmd, + p2_hash.sha256 AS p2_sha256 +FROM + processes p0 + JOIN yara ON p0.path = yara.path + LEFT JOIN hash p0_hash ON p0.path = p0_hash.path + LEFT JOIN processes p1 ON p0.parent = p1.pid + LEFT JOIN hash p1_hash ON p1.path = p1_hash.path + LEFT JOIN processes p2 ON p1.parent = p2.pid + LEFT JOIN hash p2_hash ON p2.path = p2_hash.path +WHERE + p0.start_time > (strftime('%s', 'now') - 7200) + AND + yara.sigrule = ' + rule syscalls { + strings: + $inet_ntoa = "inet_ntoa" + $listen = "listen" + $connect = "connect" + $execve = "execve" + condition: + filesize < 10MB and $execve in (0..8192) and 2 of them +}' + AND yara.count > 0 + AND yara.path NOT IN ( + '/usr/sbin/auditd', + '/usr/bin/dbus-broker-launch', + '/usr/sbin/mcelog' + ) diff --git a/detection/persistence/yara-libtomcrypt-process.sql b/detection/persistence/yara-libtomcrypt-process.sql new file mode 100644 index 0000000..57fe33d --- /dev/null +++ b/detection/persistence/yara-libtomcrypt-process.sql @@ -0,0 +1,55 @@ +-- Linux program uses LibTomCrypt (rare) +-- +-- reference: +-- * https://www.deepinstinct.com/blog/bpfdoor-malware-evolves-stealthy-sniffing-backdoor-ups-its-game +-- +-- tags: persistent +-- interval: 86400 +-- platform: posix +SELECT + yara.strings, + -- Child + p0.pid AS p0_pid, + p0.path AS p0_path, + p0.name AS p0_name, + p0.start_time AS p0_start, + p0.cmdline AS p0_cmd, + p0.cwd AS p0_cwd, + p0.cgroup_path AS p0_cgroup, + p0.euid AS p0_euid, + p0_hash.sha256 AS p0_sha256, + -- Parent + p0.parent AS p1_pid, + p1.path AS p1_path, + p1.name AS p1_name, + p1.start_time AS p1_start, + p1.euid AS p1_euid, + p1.cmdline AS p1_cmd, + p1_hash.sha256 AS p1_sha256, + -- Grandparent + p1.parent AS p2_pid, + p2.name AS p2_name, + p2.start_time AS p2_start, + p2.path AS p2_path, + p2.cmdline AS p2_cmd, + p2_hash.sha256 AS p2_sha256 +FROM + processes p0 + JOIN yara ON p0.path = yara.path + LEFT JOIN hash p0_hash ON p0.path = p0_hash.path + LEFT JOIN processes p1 ON p0.parent = p1.pid + LEFT JOIN hash p1_hash ON p1.path = p1_hash.path + LEFT JOIN processes p2 ON p1.parent = p2.pid + LEFT JOIN hash p2_hash ON p2.path = p2_hash.path +WHERE + p0.start_time > (strftime('%s', 'now') - 7200) + AND + yara.sigrule = ' + rule redflags { + strings: + $libtomcrypt = "LibTomCrypt" + $email = "tomstdenis@gmail.com" + condition: + filesize < 10MB and 1 of them +}' + AND yara.count > 0 \ No newline at end of file diff --git a/detection/persistence/yara-strings-process-linux.sql b/detection/persistence/yara-strings-process-linux.sql new file mode 100644 index 0000000..175fa7b --- /dev/null +++ b/detection/persistence/yara-strings-process-linux.sql @@ -0,0 +1,115 @@ +-- Currently running program with Linux red flags +-- +-- reference: +-- * https://github.com/timb-machine/linux-malware/blob/725aad34e216cc024c93b04964b289f10f819e6e/defensive/yara/personal-malware-bazaar/unixredflags3.yara +-- +-- tags: persistent +-- interval: 7200 +-- platform: linux +SELECT + yara.strings, + -- Child + p0.pid AS p0_pid, + p0.path AS p0_path, + p0.name AS p0_name, + p0.start_time AS p0_start, + p0.cmdline AS p0_cmd, + p0.cwd AS p0_cwd, + p0.cgroup_path AS p0_cgroup, + p0.euid AS p0_euid, + p0_hash.sha256 AS p0_sha256, + -- Parent + p0.parent AS p1_pid, + p1.path AS p1_path, + p1.name AS p1_name, + p1.start_time AS p1_start, + p1.euid AS p1_euid, + p1.cmdline AS p1_cmd, + p1_hash.sha256 AS p1_sha256, + -- Grandparent + p1.parent AS p2_pid, + p2.name AS p2_name, + p2.start_time AS p2_start, + p2.path AS p2_path, + p2.cmdline AS p2_cmd, + p2_hash.sha256 AS p2_sha256 +FROM + processes p0 + JOIN yara ON p0.path = yara.path + LEFT JOIN hash p0_hash ON p0.path = p0_hash.path + LEFT JOIN processes p1 ON p0.parent = p1.pid + LEFT JOIN hash p1_hash ON p1.path = p1_hash.path + LEFT JOIN processes p2 ON p1.parent = p2.pid + LEFT JOIN hash p2_hash ON p2.path = p2_hash.path +WHERE + p0.start_time > (strftime('%s', 'now') - 7200) + AND + yara.sigrule = ' + rule redflags { + strings: + $bash_history = ".bash_history" + $google_chrome = "google-chrome" + $cron = "cron" + $dev_shm = "/dev/shm" + $dev_tcp = "/dev/tcp" + $dev_udp = "/dev/udp" + $iptables = "iptables" + $ld_so = "ld.so.conf" + $proc = "/proc" + $sudo = "sudo" + $systemctl = "systemctl" + $useradd = "useradd" + $var_tmp = "/var/tmp" + $var_run = "/var/run" + $dev_mqueue = "/dev/mqueue" + $bin_sh = "/bin/sh" + $pickup = "pickup -l" + $avahi = "avahi-daemon:" + $redhat4 = "Red Hat 4" + condition: + filesize < 10MB and 2 of them +}' + AND yara.count > 0 + AND p0.name NOT IN ( + 'chrome_crashpad', + 'X', + 'systemd', + 'NetworkManager', + 'systemd-journal', + 'Xorg', + 'slirp4netns', + 'nacl_helper' + ) + AND p0.path NOT LIKE '%/google/chrome/%' + AND p0.path NOT LIKE '%/chrome_crashpad_handler' + AND p0.path NOT LIKE '/nix/store/%/bin/%' + AND p0.path NOT LIKE '/nix/store/%/libexec/%' + AND p0.path NOT IN ( + '/usr/bin/bash', + '/usr/bin/gnome-software', + '/usr/bin/gpg-agent', + '/usr/bin/ibus-daemon', + '/usr/bin/NetworkManager', + '/usr/bin/nvidia-persistenced', + '/usr/bin/pulseaudio', + '/usr/bin/udevadm', + '/usr/bin/update-notifier', + '/usr/bin/Xwayland', + '/usr/lib/bluetooth/bluetoothd', + '/usr/lib/bluetooth/obexd', + '/usr/lib/systemd/systemd-journald', + '/usr/lib/systemd/systemd', + '/usr/libexec/accounts-daemon', + '/usr/libexec/bluetooth/bluetoothd', + '/usr/libexec/bluetooth/obexd', + '/usr/libexec/sssd/sssd_kcm', + '/usr/libexec/xdg-desktop-portal', + '/usr/sbin/acpid', + '/usr/sbin/auditd', + '/usr/sbin/cron', + '/usr/sbin/gssproxy', + '/usr/sbin/mcelog', + '/usr/sbin/NetworkManager', + '/usr/sbin/rsyslogd', + '/usr/sbin/smartd' + ) \ No newline at end of file diff --git a/detection/persistence/yara-unexpected-go-crypt-exec-process.sql b/detection/persistence/yara-unexpected-go-crypt-exec-process.sql new file mode 100644 index 0000000..cd60a16 --- /dev/null +++ b/detection/persistence/yara-unexpected-go-crypt-exec-process.sql @@ -0,0 +1,91 @@ +-- Currently running CryptoCoin miner +-- +-- reference: +-- * https://github.com/Neo23x0/signature-base/blob/master/yara/pua_cryptocoin_miner.yar +-- +-- tags: persistent +-- interval: 7200 +-- platform: posix +SELECT + yara.*, + -- Child + p0.pid AS p0_pid, + p0.path AS p0_path, + p0.name AS p0_name, + p0.start_time AS p0_start, + p0.cmdline AS p0_cmd, + p0.cwd AS p0_cwd, + p0.cgroup_path AS p0_cgroup, + p0.euid AS p0_euid, + p0_hash.sha256 AS p0_sha256, + -- Parent + p0.parent AS p1_pid, + p1.path AS p1_path, + p1.name AS p1_name, + p1.start_time AS p1_start, + p1.euid AS p1_euid, + p1.cmdline AS p1_cmd, + p1_hash.sha256 AS p1_sha256, + -- Grandparent + p1.parent AS p2_pid, + p2.name AS p2_name, + p2.start_time AS p2_start, + p2.path AS p2_path, + p2.cmdline AS p2_cmd, + p2_hash.sha256 AS p2_sha256 +FROM + processes p0 + JOIN yara ON p0.path = yara.path + LEFT JOIN hash p0_hash ON p0.path = p0_hash.path + LEFT JOIN processes p1 ON p0.parent = p1.pid + LEFT JOIN hash p1_hash ON p1.path = p1_hash.path + LEFT JOIN processes p2 ON p1.parent = p2.pid + LEFT JOIN hash p2_hash ON p2.path = p2_hash.path +WHERE + p0.start_time > (strftime('%s', 'now') - 7200) + AND + yara.sigrule = ' + rule cryptexec { + strings: + $c0 = "crypto/cipher.newCBC" ascii + $c1 = "crypto/aes.newCipher" + $e0 = "os/exec.(*Cmd).Run" ascii + $e1 = "os/exec.Command" ascii + condition: + 3 of them +}' + AND yara.count > 0 + AND p0.path NOT LIKE "/Users/%/go/bin/%" + AND p0.path NOT LIKE "/home/%/go/bin/%" + AND p0.path NOT LIKE "/Users/%/dev/%" + AND p0.path NOT LIKE "/home/%/dev/%" + AND p0.path NOT LIKE '%docker%' + AND p0.path NOT LIKE '%tailscale%' + AND p0.path NOT LIKE '%terraform%' + AND p0.path NOT LIKE '%rootlesskit%' + AND p0.path NOT LIKE '/opt/homebrew/%' + AND p0.name NOT IN ( + 'buildkit', + 'buildkitd', + 'cloud_sql_proxy', + 'containerd', + 'crane', + 'op', + 'kubectl', + 'go', + 'docker', + 'gopls', + 'launcher', + 'tflint', + 'cloud-sql-proxy', + 'pprof', + 'lens-k8s-proxy', + 'rootlesskit', + 'snap', + 'snapd', + 'sourcegraph-backend', + 'terraform-ls', + 'velociraptor', + 'wolfictl' + ) + AND p1.name NOT LIKE "%docker%" \ No newline at end of file diff --git a/detection/persistence/yara-unexpected-miner-process.sql b/detection/persistence/yara-unexpected-miner-process.sql new file mode 100644 index 0000000..e8946c9 --- /dev/null +++ b/detection/persistence/yara-unexpected-miner-process.sql @@ -0,0 +1,57 @@ +-- Currently running CryptoCoin miner +-- +-- reference: +-- * https://github.com/Neo23x0/signature-base/blob/master/yara/pua_cryptocoin_miner.yar +-- +-- tags: persistent +-- interval: 7200 +-- platform: posix +SELECT + yara.*, + -- Child + p0.pid AS p0_pid, + p0.path AS p0_path, + p0.name AS p0_name, + p0.start_time AS p0_start, + p0.cmdline AS p0_cmd, + p0.cwd AS p0_cwd, + p0.cgroup_path AS p0_cgroup, + p0.euid AS p0_euid, + p0_hash.sha256 AS p0_sha256, + -- Parent + p0.parent AS p1_pid, + p1.path AS p1_path, + p1.name AS p1_name, + p1.start_time AS p1_start, + p1.euid AS p1_euid, + p1.cmdline AS p1_cmd, + p1_hash.sha256 AS p1_sha256, + -- Grandparent + p1.parent AS p2_pid, + p2.name AS p2_name, + p2.start_time AS p2_start, + p2.path AS p2_path, + p2.cmdline AS p2_cmd, + p2_hash.sha256 AS p2_sha256 +FROM + processes p0 + JOIN yara ON p0.path = yara.path + LEFT JOIN hash p0_hash ON p0.path = p0_hash.path + LEFT JOIN processes p1 ON p0.parent = p1.pid + LEFT JOIN hash p1_hash ON p1.path = p1_hash.path + LEFT JOIN processes p2 ON p1.parent = p2.pid + LEFT JOIN hash p2_hash ON p2.path = p2_hash.path +WHERE + p0.start_time > (strftime('%s', 'now') - 7200) + AND yara.sigrule = ' + rule miner { + strings: + $tcp = "stratum+tcp://" ascii + $tls = "stratum+tls://" ascii + $ssl = "stratum+ssl://" ascii + $stratum = "stratum://" ascii + $normalhash = "\"normalHashing\": true," + condition: + filesize < 10MB and 1 of them +}' + AND yara.count > 0 \ No newline at end of file diff --git a/detection/persistence/yara-unexpected-rust-http-exec-process.sql b/detection/persistence/yara-unexpected-rust-http-exec-process.sql new file mode 100644 index 0000000..694acd6 --- /dev/null +++ b/detection/persistence/yara-unexpected-rust-http-exec-process.sql @@ -0,0 +1,56 @@ +-- Rust Program that uses both HTTP and Exec + +-- tags: persistent +-- interval: 7200 +-- platform: posix +SELECT + yara.*, + -- Child + p0.pid AS p0_pid, + p0.path AS p0_path, + p0.name AS p0_name, + p0.start_time AS p0_start, + p0.cmdline AS p0_cmd, + p0.cwd AS p0_cwd, + p0.cgroup_path AS p0_cgroup, + p0.euid AS p0_euid, + p0_hash.sha256 AS p0_sha256, + -- Parent + p0.parent AS p1_pid, + p1.path AS p1_path, + p1.name AS p1_name, + p1.start_time AS p1_start, + p1.euid AS p1_euid, + p1.cmdline AS p1_cmd, + p1_hash.sha256 AS p1_sha256, + -- Grandparent + p1.parent AS p2_pid, + p2.name AS p2_name, + p2.start_time AS p2_start, + p2.path AS p2_path, + p2.cmdline AS p2_cmd, + p2_hash.sha256 AS p2_sha256 +FROM + processes p0 + JOIN yara ON p0.path = yara.path + LEFT JOIN hash p0_hash ON p0.path = p0_hash.path + LEFT JOIN processes p1 ON p0.parent = p1.pid + LEFT JOIN hash p1_hash ON p1.path = p1_hash.path + LEFT JOIN processes p2 ON p1.parent = p2.pid + LEFT JOIN hash p2_hash ON p2.path = p2_hash.path +WHERE + p0.start_time > (strftime('%s', 'now') - 7200) + AND yara.sigrule = ' + rule http_exec { + strings: + $http_proxy = "HTTP_PROXY" ascii + $process_unix = "process_unix.rs" ascii + condition: + all of them +}' + AND yara.count > 0 + AND p0.name NOT IN ( + 'old', + 'fig-darwin-universal', + 'wezterm-gui' + ) diff --git a/detection/persistence/yara-unexpected-upx-process.sql b/detection/persistence/yara-unexpected-upx-process.sql new file mode 100644 index 0000000..ffe5aff --- /dev/null +++ b/detection/persistence/yara-unexpected-upx-process.sql @@ -0,0 +1,51 @@ +-- Currently running UPX executable +-- +-- tags: persistent +-- interval: 3600 +-- platform: posix +SELECT + yara.*, + -- Child + p0.pid AS p0_pid, + p0.path AS p0_path, + p0.name AS p0_name, + p0.start_time AS p0_start, + p0.cmdline AS p0_cmd, + p0.cwd AS p0_cwd, + p0.cgroup_path AS p0_cgroup, + p0.euid AS p0_euid, + p0_hash.sha256 AS p0_sha256, + -- Parent + p0.parent AS p1_pid, + p1.path AS p1_path, + p1.name AS p1_name, + p1.start_time AS p1_start, + p1.euid AS p1_euid, + p1.cmdline AS p1_cmd, + p1_hash.sha256 AS p1_sha256, + -- Grandparent + p1.parent AS p2_pid, + p2.name AS p2_name, + p2.start_time AS p2_start, + p2.path AS p2_path, + p2.cmdline AS p2_cmd, + p2_hash.sha256 AS p2_sha256 +FROM + processes p0 + JOIN yara ON p0.path = yara.path + LEFT JOIN hash p0_hash ON p0.path = p0_hash.path + LEFT JOIN processes p1 ON p0.parent = p1.pid + LEFT JOIN hash p1_hash ON p1.path = p1_hash.path + LEFT JOIN processes p2 ON p1.parent = p2.pid + LEFT JOIN hash p2_hash ON p2.path = p2_hash.path +WHERE + p0.start_time > (strftime('%s', 'now') - 7200) + AND yara.sigrule = ' + rule upx { + strings: + $upx_sig = "UPX!" + + condition: + $upx_sig in (0..1024) + }' + AND yara.count > 0 \ No newline at end of file