▗ ▛▘▀▌█▌▜▘▛▘▀▌ ▙▖█▌▙▖▐▖▌ █▌ Linux Physical Security based on eBPF When eBPF met CanaryTokens
Caetra (/kaˈetɾa/) was the shield used by Iberian
Caetra uses eBPF (extended Berkeley Packet Filters) to try secure a Linux machine against physical threats, like implants installation or badUSB usage, or at least be aware about a potential attack, monitoring kernel kprobes related with hardware interactions like attaching an USB, detaching an HID or uplug the laptop from power source. It uses BPF Compiler Collection BCC to do the kernel tracing and manipulation program.
In order to be able to notify the user or cybersecurity responsables by now Caetra uses Thinkst Canary and/or Telegram Bot. On the other hand a more defensive approach has been implemented on USB Shield that allows to de-authorize the attached device.
The idea is to leave Caetra running when you leave your machine unattended, e.g. when it's lock or on suspension mode.
The first release v1.0.0 has been wirten for the eBPF Summit: Hackathon Edition 2025. Videos for Hackathon
$ git clone https://github.com/carvilsi/caetra'
$ cd caetra
Check next Dependencies section.
-
Python vers >= 3.12
Right now eBPF requires to be execute as root.
sudo ./caetra.py
Shields are the eBPF programs that monitors the physical interaction with the equip.
Consists on kernel space code in c and user space script in python.
Right now all the Shields are based on kprobes
Current implemented Caetra's Shields:
Shield that triggers notification when the backlight of screen changes.
This could means that someone aproached to your machine.
kprobe: backlight_device_set_brightness
This shields triggers when a Bluetooth device connects or tries to connect or bind to your machine.
kprobe: hci_conn_request_evt
Triggers when a Bluetooth device has been disconected from the machine.
kprobe: hci_disconn_complete_evt
This Shield will trigger when the machine goes out from hibernation mode.
kprobe: unregister_pm_notifier
Triggers when an HID device has been deatached from your machine.
Here we are thinking about a possible keyboad implant e.g. a keylogger
kprobe: hid_add_device
kprobe: hid_device_remove
This Shield triggers when there is a HID interaction; the mouse has been moved or a key from external keyboard has been pressed.
kprobe: hid_report_raw_event
Triggers when there is changes on networking for inet device
kprobe: inet_alloc_ifa
kprobe: inetdev_event
Shield that triggers when there is any input interaction, e.g. trackpad, touchscreen, keyboard, etc...
kprobe: input_handle_event
The Shield reacts when a MMC (MultiMediaCard) is inserted. e.g. SDCard.
kprobe: mmc_sd_runtime_suspend
Triggers when the power source changes.
Thinking that someone has been disconnected the laptop from power plug, e.g. to access hardware parts to perform a phiysical RAM memory dump. (
kprobe: power_supply_changed
This Shield reacts when an USB has been connected to the machine.
We are thinking here about a badUSB or data exfiltration from the equip. (same idea than CanaryUSB)
This Shields can de-authorize the USB device, via configuration.
kprobe: usb_notify_add_device
What Caetra uses to send you a notification, when any Shield has been trigger.
It is possible to configure each shield to handle custom notification for it, via toml file under src/shields/[shield]/[shield.toml]. e.g. if you want that specific shield to send the notification to a certain Telegram Bot or mail in case of CanaryToken usage. Check an example here
Will send an email with data related with the triggered Shield via DNS Canarytoken powered by Thinkst Canary.
Get your DNS Canarytoken and add it to the token variable on general configuration file or specific shield one.
Will use Telegram Bot API to send data related with the triggered Shield to the configured Telegram Chat.
Create your Telegram Bot and set the bot_api_key variable on general configuration or on specific shield one.
Then add the bot to a chat and set the chat_id on general configuration or on specific shield one.
Note: To retrieve the desired telegram chat ID after added the bot to the chat and interacted with it, run:
$ curl https://api.telegram.org/bot<BOT_API_KEY>/getUpdates | jq .result[0].message.chat.id
Caetra by default will do logging on logs/ folder with file rotating behaviour. The main logging level could be set on toml configuration file with the variable level under logging section.
The Shields by default will log on syslog with warning level.
To check the syslog Caetra's messages:
$ journalctl -r --grep='caetra_shields'
.
├── caetra.py (main script)
├── config (general configuration)
├── logs (Caetra logs)
├── src
│ ├── caetra_exceptions.py
│ ├── constants.py
│ ├── senders (all the things related with notifications)
│ ├── shields (the Shields, code for kernel and user space among specific Shield configuration)
│ └── utils (the utils stuff)
└── tools
├── caetra_shield_generator
└── follow_rabbit_hole
Things that could help Caetra's Shields development.
You'll find it under tools folder
An interactive Caetra's Shield interactive generator:
Run it with:
$ python caetra_bpf_generator.py
The above command without parameters will ask for related variables to generate the new Caetra's Shield.
The new Shield will be under the generator-output folder.
Usage: caetra_bpf_generator.py [OPTIONS]
Options:
--shield-name TEXT New caetra shield name.
[required]
--shield-description TEXT Write down about what this Shield
does.
--kprobe-event TEXT Kprobe event. [required]
--kheaders-include TEXT Linux header to includ on kernel c
code, e.g. 'linux/usb.h'
[required]
--kstrct TEXT Linux struct to retrieve data,
e.g. 'usb_device' [required]
--shield-enable BOOLEAN If this Shield will be enabled or
not [required]
--shield-feature TEXT Will be the feature variable for
the Shield.
--action-label TEXT The label that describes the
physical interaction, e.g. 'usb
attached' [required]
--canarytoken-sender
--canarytoken TEXT
--telegram-sender
--telegram-chat-id TEXT
--telegram-bot-api-key TEXT
--help Show this message and exit.
A bash script to help follow related kprobes structures.
$ sudo ./rabbit_hole_structures.sh <structure_name>
Note and example: In order to check the related structs for a specific kprobe use bpftrace tool:
$ sudo bpftrace -lv kprobe:backlight_device_set_brightness
Output:
kprobe:backlight_device_set_brightness
struct backlight_device * arg0
long unsigned int arg1
So for this output you could follow the rabbit into the hole like:
$ sudo ./rabbit_hole_structures.sh backlight_device
This will create a file called backlight_device_rabbit_hole.strct that has all the related structures.
- accelerometers (I don't have a device with an accelerometer sensor)
- cli
- general logger configuration
- rethink how to run the whole thing; ponder about running all the shields on multhread mode
- implement elasticSearch and Kibana