Slide 1

Slide 1 text

Whitelisting LD_PRELOAD For Fun and No Profit

Slide 2

Slide 2 text

▪ Professional tinkerer & educator ▪ Recovering system administrator ▪ Love to make bad guys have bad days Tony Lambert Detection Engineer/Intel Red Canary @ForensicITGuy id -un

Slide 3

Slide 3 text

What is LD_PRELOAD and how is it used? Examining the rtld-audit subsystem Whitelisting LD_PRELOAD What worked and what didn’t Overview

Slide 4

Slide 4 text

▪ glibc & musl environment variable ▪ Injects arbitrary SO file into process ▪ LD_PRELOAD or /etc/ld.so.preload Intro to LD_PRELOAD

Slide 5

Slide 5 text

rtld.c

Slide 6

Slide 6 text

Get Started With Env Var LS SHELL=/bin/bash PATH=/long/list/of/folders … LD_PRELOAD=injected.so /proc/PID/env

Slide 7

Slide 7 text

Make It Persistent $ LD_PRELOAD=injected.so ls $ export LD_PRELOAD=injected.so # echo injected.so > /etc/ld.so.preload # echo LD_PRELOAD=injected.so >> /etc/profile

Slide 8

Slide 8 text

It Can Be Good! LS libdl.so libc.so test-libc.so

Slide 9

Slide 9 text

Evil Use Cases ■ Hooking functions and calls ■ Automatic code execution on load

Slide 10

Slide 10 text

Hooking Functions ■ Define function with same name ■ Manipulate output and fool user ■ libprocesshider

Slide 11

Slide 11 text

It Can be Very Bad! PS libc.so readdir() evil.so readdir() Intact Listing Bash Python evil.py Tainted Listing Bash ...

Slide 12

Slide 12 text

Hooking Example

Slide 13

Slide 13 text

Execution on Load ■ No knowledge of target binary needed ■ Code stored in ELF .init section ■ Zombie Ant Farm Project

Slide 14

Slide 14 text

Execution Example

Slide 15

Slide 15 text

The rtld-audit Subsystem ■ Audit API for the dynamic linker ■ Write a SO library to implement ■ Use with LD_AUDIT variable

Slide 16

Slide 16 text

Lots of functions la_objsearch() la_activity() la_objopen() la_objclose() la_preinit() la_symbind*() la_pltenter() la_pltexit()

Slide 17

Slide 17 text

At First, I Wanted to Log la_objsearch() la_activity() la_objopen() la_objclose() la_preinit() la_symbind*() la_pltenter() la_pltexit()

Slide 18

Slide 18 text

I Realized I Could Prevent la_objsearch() la_activity() la_objopen() la_objclose() la_preinit() la_symbind*() la_pltenter() la_pltexit()

Slide 19

Slide 19 text

Intercept Before Load la_objsearch() The dynamic linker invokes this function to inform the auditing library that it is about to search for a shared object. rtld-audit(7) manpage

Slide 20

Slide 20 text

You Had Me At “return NULL” la_objsearch() ...returns the pathname that the dynamic linker should use... If NULL is returned, then this pathname is ignored for further processing. rtld-audit(7) manpage

Slide 21

Slide 21 text

No content

Slide 22

Slide 22 text

Let’s Block Some Preloads! ■ Define unauthorized preloads ■ Define authorized preloads ■ Monitor for unauthorized loads ■ Mitigate the loads

Slide 23

Slide 23 text

Unauthorized Preloads ■ Unpredictable preloads ■ Unlimited forms of evil ■ Block by default

Slide 24

Slide 24 text

Authorized Preloads ■ Unpredictable system configuration ■ Wanted ease of administration ■ Modeled after cron.allow, hosts.allow

Slide 25

Slide 25 text

Monitor & Block Preloads ■ Intercept module search ■ Check the allowed list ■ Return NULL if not allowed to block

Slide 26

Slide 26 text

Enter Libpreloadvaccine! ■ LD_AUDIT SO library ■ Intercepts and blocks ■ Just worksTM github.com/ForensicITGuy/libpreloadvaccine Logo left intentionally blank.

Slide 27

Slide 27 text

Simple Logic

Slide 28

Slide 28 text

Simple Authorized List /etc/libpreloadvaccine.allow ■ Check the allowed list ■ Return NULL if not allowed to block

Slide 29

Slide 29 text

Simple Deployment 1. Compile with gcc 2. Move to folder 3. Set LD_AUDIT export LD_AUDIT=/usr/lib/libpreloadvaccine.so

Slide 30

Slide 30 text

Success! Sort of...

Slide 31

Slide 31 text

Catch it in Action!

Slide 32

Slide 32 text

And Bypass it After!

Slide 33

Slide 33 text

Lessons Learned

Slide 34

Slide 34 text

Keep Security Close to Code ■ Bolted on solutions don’t always work ■ Code inside rtld.c would be harder to bypass ■ Attackers with root can have unlimited access

Slide 35

Slide 35 text

FEEDBACK Q & A REDCANARY.COM/BLOG @REDCANARYCO GITHUB.COM/FORENSICITGUY/LIBPRELOADVACCINE @FORENSICITGUY