_ _
_ _ ___| | | _____ __
| | | |/ _ \ | |/ _ \ \ /\ / /
| |_| | __/ | | (_) \ V V /
\__, |\___|_|_|\___/ \_/\_/
|___/
- Just add blue.
Simple binary modifications that will trigger a canarytoken when a binary is executed.
Ideal for boobytrapping production systems against attackers.
Currently there are four methods:
- yellow is a targetted approach with a binary that will trigger the token then execute the real binary based on a file extension of your choosing.
- spe is a variation on the above using a similar approach to Thinkst's recently added "Sensitive Process Execution" token for Windows.
- libyellow is a cross-system notification and will transparently trigger a canarytoken for any binary name you specify when it's injected via LD_PRELOAD
- ldsoyellow is a fully functional glibc linker (ld.so) that will trigger a canarytoken for any binary that uses it
Register a DNS canary token of your own at canarytokens. You can read more about how they work at the docs.
It will looks something like this: pz21qtyfsidipvrsuzs9n2udi.canarytokens.com
Put it into the environmental variable TOKEN with:
export TOKEN="c28y9l4dw0drj62un0cm4rwz6.canarytokens.com"
The Dockerfiles have an example, working token in them, you can check its activity history here. You really should use your own though.
Dockerfiles implementing each of these build methods are available.
If you have a suitable default build environment (e.g. build-essential on debian based systems or build-base on alpine based systems), you can compile libyellow or yellow very simply. ldsoyellow is more involved.
You can see simple end-to-end example of Building and Installing yellow in the Dockerfile
s.
gcc -o yellow yellow.c canary32.c
See Dockerfile.yellow
No building required.
Make sure to update the list of binary's you want to alert on in the alert_list array.
gcc -shared -fPIC libyellow.c canary32.c -o libyellow.so
See Dockerfile.libyellow
or Dockerfile.libyellow.debian
for Alpine and Debian versions.
Check the Dockerfile.ldsoyellow
for a working example. You'll need the glibc sources (I recommend using the official package version to be as close to the real linker as possible).
apt-get source libc6
Apply the patch rtld.c.patch
cd /glibc-*
patch < rtld.c.patch
Configure glibc with sanity checks disabled and pointing to the right libdir (assuming 64bit system)
mkdir glibcbuild && cd glibcbuild
/glibc-*/configure --disable-sanity-checks --libdir=$(dirname $(find / -name "libc.so.6"|grep 64))
Build as normal
make
All variants use the TOKEN environment variable to specify the canary token URL. The environment variable name can be changed, or even hardcoded if you prefer. Again, Dockerfiles exist for each of these.
yellow is intended to trigger on specific binaries you rename and alias to it, much like how busybox is used. You'll need to rename the binary to use the ".canary" extension, then create a symlink (or copy) of yellow for the original binary name. For example:
cp yellow /usr/bin
mv /usr/bin/id /usr/bin/id.canary
ln -s /usr/bin/yellow /usr/bin/id
After this any execution of id
will trigger your canary token.
See Dockerfile.yellow
The sensitive process execution method uses the same technique as above, except it triggers with a shell script rather than a binary, and comes with an installer. Run spe_install.sh
passing it your DNS token and name of the binary you want to trigger on. The binary doesn't need to exist.
For example:
./spe_install.sh "c28y9l4dw0drj62un0cm4rwz6.canarytokens.com" /bin/id
Will create an alert any time id
is run.
This is a copy of the Windows token method described here
libyellow is intended to trigger on any binary used where it has been injected via LD_PRELOAD but only alert on the ones you specify in the code. This can be done per session by setting the LD_PRELOAD environment variable to point to it, or across the system by adding it into the /etc/ld.so.preload
file. The latter can break your system if the library isn't working on it, so it's recommended you test it using LD_PRELOAD first.
Remember to put your token in the TOKEN environment variable as described under "Pre-Work" above.
LD_PRELOAD example:
cp libyellow.so /usr/lib/
export LD_PRELOAD=/usr/lib/libyellow.so
Then run a target binary, check that it behaves as expected, and you get a canary alert.
Once you're happy everything is working, you can add it across the system with (this won't work on musl based systems like alpine, where the LD_PRELOAD method is used instead):
cp libyellow.so /usr/lib
echo /usr/lib/libyellow.so >> /etc/ld.so.preload
See Dockerfile.libyellow
or Dockerfile.libyellow.debian
for Alpine and Debian versions.
ldsoyellow is intended to trigger on specific binaries where the binary is modified to use it instead of the default linker. You could replace the default linker with it for a system wide effect, but that would likely be too noisy.
The Dockerfile.ldsoyellow
example includes doing this for /bin/cat
. First the arm'ed linker is copied next to the legitemate linker:
cp <arm'd linker> /lib64/ld-linux-x86-64.so.3
Then the binary is modified to use it instead of the legitemate one:
sed -i "s/\/lib64\/ld-linux-x86-64.so.2/\/lib64\/ld-linux-x86-64.so.3/" /bin/cat
See Dockerfile.ldsoyellow
.
If you wanted to run Docker in Docker for, say, a build environment where you had limited control of the build directives, and be alerted if someone broke out, you could do something like the example in Dockerfile.dind-rootless
. This example uses yellow
but could use any or all the other variants.
It boobytraps binaries in the host which shouldn't be accessible from a container.