2023-08-24
One of the things that I love most about the wandering path of my career journey is that I get to do lots of new things. I enjoy building on things that I know to do things that I’ve never done before.
I’ve been involved in one form or another with detection engineering (DE) for the last 10 years. My detection engineering team at my day job uses git and a CI/CD pipeline to manage and deploy our detection rules into our SIEM. So from that perspective, this blog is about “things I know”.
But I don’t have much history contributing technical content to open source projects, and I’ve never authored a Sigma rule. So that will be “things I’ve never done before”.
By and large, the experience of writing and submitting my first Sigma rule was really painless and enjoyable. For anybody involved or looking to get involved with DE, I can recommend the project as a great way to learn more and give back to the community.
Back in July, I noticed a post from @Skyper@fosstodon.org on detecting if your commands were executing from a shell that’s resident in a container or not. I took a few minutes to read their blog, and I learned some new things about container residence discovery.
I had also been working through a training course on writing Sigma rules, and it felt like a great opportunity to try out my new learnings alongside this new rule format, so let’s begin!
You should take some time to read through the blog, it’s well-done. But I’m going to summarize what I took away from it:
ls -id /
will emit the inode number for the root directory. If it’s low (like 1 or 2) you’re native; if it’s large you’re probably containerized./proc/1/cgroup
likely end in /
but they’re much different under Docker. /.dockerenv
is expected.With this information in hand, I’m starting to piece together a plan:
ls -id /
could be written a lot of different ways, because switch positions are interchangeable. So something like ls -id /
and ls -di /
and even ls -pdqi /
would all give the attacker what they’re looking for./proc
virtual file system exposes system information as files. Since the blog describes what the attacker is looking for, we should imagine all of the default or common tools for examining files. We want to cover cat /proc/1/cgroup
as well as grep docker /proc/1/cgroup
or a number of creative combinations. Strategically, anything that attempts to emit or match the contents of that virtual file will provide an attacker with their goal of knowing about the environment.One other important thing: I need to take a look at the Sigma rule repository and see if anyone else has done anything else like this. If they have, I should check there work and see if it needs updated. If they haven’t, then it’d be a good candidate for a new rule.
To do so, let’s interrogate the repository:
(I submitted the initial version of this rule on Jul 31, 2023. If you want to follow along, checkout the Jul 28 commit of the SigmaHQ rules repository, with id 8dca7aa1ba3c119a6aa6f6bad49252eaf2fd5514).
git clone https://github.com/SigmaHQ/sigma.git
git checkout 8dca7aa1ba3c119a6aa6f6bad49252eaf2fd5514
And let’s do some light reconnaissance on whether something like what we’ve described already exists:
cd sigma/rules/linux
grep -rl T1082 ./*
grep -rl T1613 ./*
grep -rl ontainer ./*
Looking at that output, we should check the contents of:
None of these match what we’re trying to detect, so that’s good.
Given my relatively rudimentary level of experience with containers, I hunted around for more answers to “How can I tell if my process is in a container?”. I found some great info on Stack Overflow that both confirmed the’s approach and uncovered a few new techniques:
How to determine if a process runs inside LXC / Docker
/proc/2
to be kthreadd./proc/*/sched
should emit a pid that matches the pid we interrogate (so /proc/1/sched
should show pid 1, /proc/7/sched
should show pid 7, etc.)So I ended up with an initial rule that:
/
/proc/2
/proc/*/cgroup
and /proc/*/sched
for mismatches/.dockerenv
Putting all of this into a sigma rule looked like this: Lnx container discovery #4380
As instructed, I tried to make what I was doing conform to the SigmaHQ standards and Rule Creation Guide.
The ultimate outcomes? A really straightforward process! My rule got picked up after PR and sat waiting a short time for review. Once the review was completed, since it was fairly complicated, it was divided into three distinct rules.
So there we are! A few hours of research, some formatting, and a PR later… then wait some short few days to get a review… and voila! Three Sigma rules by me! :)