Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Whitelisting LD_PRELOAD For Fun and No Profit

Whitelisting LD_PRELOAD For Fun and No Profit

Sometimes bolting a security solution on the side of technology just doesn’t work as well as built-in protection. One example of this on Linux systems is libpreloadvaccine, a whitelisting solution I built that aimed, and failed, to provide foolproof protection against abuse of LD_PRELOAD process injection. This talk will cover how adversaries use LD_PRELOAD, how its built-in audit system works, and how the audit system can be leveraged for whitelisting. We’ll also examine design and implementation considerations for whitelisting, closing the talk by showing how checks built into the dynamic linker would be much more effective than a solution thrown on top.

Tony M Lambert

February 01, 2020

More Decks by Tony M Lambert

Other Decks in Programming


  1. ▪ Professional tinkerer & educator ▪ Recovering system administrator ▪

    Love to make bad guys have bad days Tony Lambert Detection Engineer/Intel Red Canary @ForensicITGuy id -un
  2. What is LD_PRELOAD and how is it used? Examining the

    rtld-audit subsystem Whitelisting LD_PRELOAD What worked and what didn’t Overview
  3. ▪ glibc & musl environment variable ▪ Injects arbitrary SO

    file into process ▪ LD_PRELOAD or /etc/ld.so.preload Intro to LD_PRELOAD
  4. 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
  5. It Can be Very Bad! PS libc.so readdir() evil.so readdir()

    Intact Listing Bash Python evil.py Tainted Listing Bash ...
  6. Execution on Load ▪ No knowledge of target binary needed

    ▪ Code stored in ELF .init section ▪ Zombie Ant Farm Project
  7. The rtld-audit Subsystem ▪ Audit API for the dynamic linker

    ▪ Write a SO library to implement ▪ Use with LD_AUDIT variable
  8. At First, I Wanted to Log la_objsearch() la_activity() la_objopen() la_objclose()

    la_preinit() la_symbind*() la_pltenter() la_pltexit()
  9. 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
  10. 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
  11. Let’s Block Some Preloads! ▪ Define unauthorized preloads ▪ Define

    authorized preloads ▪ Monitor for unauthorized loads ▪ Mitigate the loads
  12. Authorized Preloads ▪ Unpredictable system configuration ▪ Wanted ease of

    administration ▪ Modeled after cron.allow, hosts.allow
  13. Monitor & Block Preloads ▪ Intercept module search ▪ Check

    the allowed list ▪ Return NULL if not allowed to block
  14. Enter Libpreloadvaccine! ▪ LD_AUDIT SO library ▪ Intercepts and blocks

    ▪ Just worksTM github.com/ForensicITGuy/libpreloadvaccine Logo left intentionally blank.
  15. Simple Deployment 1. Compile with gcc 2. Move to folder

    3. Set LD_AUDIT export LD_AUDIT=/usr/lib/libpreloadvaccine.so
  16. 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