This blog post is going to cover an Osquery extension that I engineered with osquery-go to eradicate malware. This extension has the ability to delete files, kill processes, delete directories, and can be used with the builtin YARA table. This blog post will act as documentation for the setup and operation of this Osquery extension.
Background
What is Osquery?
Osquery exposes an operating system as a high-performance relational database. This allows you to write SQL-based queries to explore operating system data. With Osquery, SQL tables represent abstract concepts such as running processes, loaded kernel modules, open network connections, browser plugins, hardware events or file hashes. SQL tables are implemented via a simple plugin and extensions API.
What is Osquery-go?
In Osquery, SQL tables, configuration retrieval, log handling, etc. are implemented via a robust plugin and extensions API. This project contains Go bindings for creating Osquery extensions in Go. To create an extension, you must create an executable binary that instantiates an ExtensionManagerServer and registers the plugins that you would like to be added to Osquery. You can then have Osquery load the extension in your desired context (ie: in a long-running instance of OsqueryD or during an interactive query session with Osqueryi).
What is YARA?
YARA is a tool aimed at (but not limited to) helping malware researchers to identify and classify malware samples. With YARA you can create descriptions of malware families (or whatever you want to describe) based on textual or binary patterns. Each description, a.k.a rule, consists of a set of strings and a boolean expression which determine its logic.
Install Osquery
- Download https://pkg.osquery.io/darwin/osquery-4.1.2.pkg
- Install Osquery
Install/Setup go env
git clone https://github.com/CptOfEvilMinions/osquery-malware-removal
cd osquery-malware-removal
go get
Compile Osquery extension
GOOS=windows GOARCH=amd64 go build -o osquery_malware_removal.exe osquery-malware-removal.go
- Compile executable for Windows
GOOS=darwin GOARCH=amd64 go build -o osquery_malware_removal.macho osquery-malware-removal.go
- Compile executable for macOS
GOOS=linux GOARCH=amd64 go build -o osquery_malware_removal.elf osquery-malware-removal.go
- Compile executable for Linux
Test Osquery extension
Load Osqueri with extension
osqueryi --extension <Path to project>/osquery-malware-removal/osquery-malware-removal
.tables
SELECT * FROM malware_removal;
Delete file
- Open a new terminal
touch /tmp/hello0
touch /tmp/hello1
sudo chown root /tmp/hello1
- Back to Osqueryi
SELECT * FROM malware_removal WHERE file_path='/tmp/hello0';
SELECT * FROM malware_removal WHERE file_path='/tmp/hello1';
Delete directory
mkdir /tmp/testdir1
touch /tmp/testdir1/hello2
touch /tmp/testdir1/hello3
mkdir /tmp/testdir2
touch /tmp/testdir2/hello4
touch /tmp/testdir2/hello5
sudo chown root /tmp/testdir2/hello5
mkdir /tmp/testdir3
touch /tmp/testdir3/hello6
touch /tmp/testdir3/hello7
sudo chown root /tmp/testdir3
SELECT * FROM malware_removal WHERE dir_path='/tmp/testdir1';
SELECT * FROM malware_removal WHERE dir_path='/tmp/testdir2';
SELECT * FROM malware_removal WHERE dir_path='/tmp/testdir3';
SELECT * FROM malware_removal WHERE dir_path='/tmp/testdir4';
Delete a file with SHA256 hash
touch /tmp/hello8
shasum -a 256 /tmp/hello8
- Copy output from command
SELECT * FROM malware_removal WHERE dir_path='/tmp' AND file_hash='<SHA256 hash outout from above>';
SELECT * FROM malware_removal WHERE dir_path='/tmp' AND file_hash='<hash from above minus one character>';
Terminate process
ipython
import os
os.getpid()
- Copy output
SELECT * FROM malware_removal WHERE pid=<PID from above>;
SELECT * FROM malware_removal WHERE pid=<PID of ROOT process>;
SELECT * FROM malware_removal WHERE pid=<PID that doesn't exist>;
Testing Osquery extension with YARA
Test Osquery YARA table
The EICAR file is a UNmalicious file that all anti-virus products SHOULD alert on. We are going to download an EICAR file as our “malicious file” but it is benign
sudo mkdir /var/osquery/yara
sudo curl https://raw.githubusercontent.com/airbnb/binaryalert/master/rules/public/eicar.yara -o /var/osquery/yara/eicar.yara
cd ~/Downloads
curl http://www.eicar.org/download/eicar.com -o eicar.com
osqueryi
SELECT * FROM yara WHERE path like '/Users/%/Downloads/%' AND sigfile='/var/osquery/yara/eicar.yara';
JOIN YARA and malware_removal _table
sudo mkdir /var/osquery/Extensions
sudo cp osquery-malware-removal /var/osquery/Extensions/osquery-malware-removal.ext
osqueryi --extension /var/osquery/Extensions/osquery-malware-removal.ext
SELECT y.path, y.matches, y.count, m.status, m.status_bool FROM yara as y JOIN malware_removal as m ON y.path=m.file_path WHERE path like '/Users/%/Downloads/%' AND sigfile='/var/osquery/yara/eicar.yara' AND COUNT > 0;
Install/Setup Kolide + Osquery
Spin up Kolide with Docker
git clone https://github.com/CptOfEvilMinions/Kolide-Docker.git
cd Kolide-Docker
docker-compose run --rm kolide fleet prepare db --config /etc/kolide/kolide.yml
docker-compose up -d
- Open a browser to https://<Docker IP addr>:8443
- SET USERNAME & PASSWORD
- Enter username
- Enter password
- Enter e-mail
- Select “Submit”
- SET ORGANIZATION DETAILS
- Enter org name
- Enter org https://<FQDN>
- Select “Submit”
- SET KOLIDE WEB ADDRESS
- Enter https://<FQDN>
- Select “Submit”
Install/Setup OsqueryD + Osquery extensions on macOS
- Open terminal as sudo
cd /var/osquery
sudo curl https://raw.githubusercontent.com/CptOfEvilMinions/Kolide-Docker/master/conf/osquery/osquery.flags -o /var/osquery/osquery.flags
sudo sed -i '' 's/kolide_fqdn/kolide.hackinglab.local/g' osquery.flags
sudo sed -i '' 's/kolide_port/8443/g' osquery.flags
sudo chown root Extensions
- Go to Kolide
- Select “Add New Host”
- Copy key
- Back to terminal
echo '<Kolide key>' | sudo tee /var/osquery/osquery.key
openssl s_client -connect kolide.hackinglab.local:8443 -showcerts </dev/null 2>/dev/null|openssl x509 -outform PEM | sudo tee /var/osquery/certs/certificate.crt
sudo launchctl load /var/osquery/com.facebook.osqueryd.plist
- Go back to Kolide
Download EICAR file
curl http://www.eicar.org/download/eicar.com -o eicar.com
Remove malware with Kolide
- From the Kolide homepage select the host
SELECT * FROM osquery_extensions
SELECT * FROM yara WHERE path like '/Users/%/Downloads/%' AND sigfile='/var/osquery/yara/eicar.yara';
SELECT y.path, y.matches, y.count, m.status, m.status_bool FROM YARA as y JOIN malware_removal as m ON y.path=m.file_path WHERE path like '/Users/%/Downloads/%' AND sigfile='/var/osquery/yara/eicar.yara' AND COUNT > 0;
Discussion
No role-based access control (RBAC)
I don’t know of any open source fleet control managers that implement role-based access control to restrict which tables users can use. This means if a user has the ability to invoke a query on an Osquery agent they have the ability to invoke deletion of files or termination of processes.
Lessons learned
I am currently reading a book called “Cracking the Coding Interview” and it is a great book. One interesting part of the book is their matrix to describe projects you worked on and the matrix contains the following sections which are: challenges, mistakes/failures, enjoyed, leadership, conflicts, and what you’d do differently. I am going to try and use this model at the end of my blog posts to summarize and reflect on the things I learn. I don’t blog to post things that I know, I blog to learn new things and to share the knowledge of my security research.
Challenges
- Learning a new programming language which is golang
- Learning all the new data structures and data structure names, such as a slice is equivalent to a Python list and a map is equivalent to a directory
- Assuming that writing golang would automatically make the code compatible with all OSes. Unfortunately, that was not the case when I attempted to use the library
syscall
which is compatible with Linux and Darwin. I had to shift togopsutils
to ensure myterminateProcess
function worked on all platforms.
Enjoyed
- I loved that I got to engineer a new security mechanism for my favorite open source project Osquery
- Learning how to read the osquery-go struct blueprint to extract values.
- I frustratedly enjoyed learning how to enforce handling errors in golang. With languages like Python, the error is often abstracted away until it happens but golang enforces you to handle it and this is helping me learn how to handle different error cases.
- Implemented a successful golang project with a go mod – requirements.txt equivalent in Python
- Thinking of new edges cases to test my new Osquery extension against such as “What if I try to delete a directory that doesn’t exist?” or “What if I try to delete a hash that doesn’t exist?”. I was actually able to catch some and repair some errors in my code by doing this.
- Learning how to setup TravisCI + Github to release new builds
What You’d Do Differently
- I wish I knew how to do golang tests so I didn’t have to keep making files and directories manually to delete while testing
- The current extensions can delete files and kill processes but it doesn’t stop network connections. In an incident response scenario, you may want the ability to kill a network connection via firewall-based rule. Since Windows, macOS, and Linux all utilize different platforms for firewalls, I didn’t implement that functionality.
- At the current time of this writing, the extension does not provide the capability to remove malicious Registry entries, Scheduled Tasks, and more on Windows