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.

Ab07041e64bf608fe7483df7899db87c?s=128

Tony M Lambert

February 01, 2020
Tweet

More Decks by Tony M Lambert

Other Decks in Programming

Transcript

  1. Whitelisting LD_PRELOAD For Fun and No Profit

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

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

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

    file into process ▪ LD_PRELOAD or /etc/ld.so.preload Intro to LD_PRELOAD
  5. rtld.c

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

    /proc/PID/env
  7. 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
  8. It Can Be Good! LS libdl.so libc.so test-libc.so

  9. Evil Use Cases ▪ Hooking functions and calls ▪ Automatic

    code execution on load
  10. Hooking Functions ▪ Define function with same name ▪ Manipulate

    output and fool user ▪ libprocesshider
  11. It Can be Very Bad! PS libc.so readdir() evil.so readdir()

    Intact Listing Bash Python evil.py Tainted Listing Bash ...
  12. Hooking Example

  13. Execution on Load ▪ No knowledge of target binary needed

    ▪ Code stored in ELF .init section ▪ Zombie Ant Farm Project
  14. Execution Example

  15. The rtld-audit Subsystem ▪ Audit API for the dynamic linker

    ▪ Write a SO library to implement ▪ Use with LD_AUDIT variable
  16. Lots of functions la_objsearch() la_activity() la_objopen() la_objclose() la_preinit() la_symbind*() la_pltenter()

    la_pltexit()
  17. At First, I Wanted to Log la_objsearch() la_activity() la_objopen() la_objclose()

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

    la_symbind*() la_pltenter() la_pltexit()
  19. 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
  20. 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
  21. None
  22. Let’s Block Some Preloads! ▪ Define unauthorized preloads ▪ Define

    authorized preloads ▪ Monitor for unauthorized loads ▪ Mitigate the loads
  23. Unauthorized Preloads ▪ Unpredictable preloads ▪ Unlimited forms of evil

    ▪ Block by default
  24. Authorized Preloads ▪ Unpredictable system configuration ▪ Wanted ease of

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

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

    ▪ Just worksTM github.com/ForensicITGuy/libpreloadvaccine Logo left intentionally blank.
  27. Simple Logic

  28. Simple Authorized List /etc/libpreloadvaccine.allow ▪ Check the allowed list ▪

    Return NULL if not allowed to block
  29. Simple Deployment 1. Compile with gcc 2. Move to folder

    3. Set LD_AUDIT export LD_AUDIT=/usr/lib/libpreloadvaccine.so
  30. Success! Sort of...

  31. Catch it in Action!

  32. And Bypass it After!

  33. Lessons Learned

  34. 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
  35. FEEDBACK Q & A REDCANARY.COM/BLOG @REDCANARYCO GITHUB.COM/FORENSICITGUY/LIBPRELOADVACCINE @FORENSICITGUY