Shared Library Hijacking

How shared libraries being loaded by Linux app can be manipulated to provide an advantage to an attacker. This approach is similar to DLL hijacking, which is commonly used to compromise Windows.

Linux app search needed app library copy with the following sequence order:

  1. Directories listed in the application's RPATH value.

  2. Directories specified in the LD_LIBRARY_PATH environment variable.

  3. Directories listed in the application's RUNPATH value.

  4. Directories specified in /etc/ld.so.conf.

  5. System library directories: /lib, /lib64, /usr/lib, /usr/lib64, /usr/local/lib, /usr/local/lib64, and potentially others.

We can potentially hijack or place our own versions of shared libraries in places earlier in the chain in order to control the application's behavior.

Via LD_LIBRARY_PATH

Privesc pre-requisite: use .bashrc set alias method to bypass env_reset setting on sudo

LD_LIBRARY_PATH environment variables are not passed even with this approach, so need to include it in the .bashrc alias explicitly.

alias sudo="sudo LD_LIBRARY_PATH=/home/offsec/ldlib"

echo 'alias sudo="sudo LD_LIBRARY_PATH=/home/offsec/ldlib"' >> .bashrc

source ~/.bashrc

sudo top

(rmb to be in /bin/bash)

We want to hijack the library of a program that a victim is likely to run, especially as sudo.

Need to remember that whichever library we're hijacking will be unavailable to the requesting program. Find something that won't break the system if all programs are prevented from using it, something that is likely to be loaded by the application but not likely to be called (e.g. error reporting library).

Run the ldd command in the target machine on the targeted program. This will give us information on which libraries are being loaded when the targeted program is being run.

Target from the results:

libgpg-error.so.0 => /lib/x86_64-linux-gnu/libgpg-error.so.0

Set our environment variable for LD_LIBRARY_PATH to where our arbitrary library is located and rename our .so file to match the one we're hijacking.

Run the targeted program and check if error message specifying which symbol it's looking for -

The error message specifies that the symbol it's looking for is tagged with GPG_ERROR_1.0. We can infer that it's part of the library we're replacing (libgpg-error.so.0).

The result is a list of variable definitions, one for each missing symbol, that we can copy and paste just under our initial constructor definition in our hax.c source code file.

If the target library requires version information in the associated libraries, we can fix this with the help of a map file that identifies particular symbols as being associated with a given version of the library.

and run the targeted command e.g. top

If an error occurred that required libgpg_error, the application would likely crash.

Via LD_PRELOAD (function hooking)

An environment variable that, when defined on the system, forces the dynamic linking loader to preload a particular shared library before any others. As a result, functions that are defined in this library are used before any with the same method signature that are defined in other libraries. Methods we define in a library loaded by LD_PRELOAD will override methods loaded later on.

The original libraries are also still being loaded, we can call the original functions and allow the program to continue working as intended.

Sudo will explicitly ignore the LD_PRELOAD environment variable for a user unless the user's real UID is the same as their effective UID (same as LD_LIBRARY_PATH).

Need to find an application that the victim is likely to frequently use, e.g. cp

targeted function is geteuid()

We don't need to define a constructor function as we did in the previous examples. This is because we want to fire our payload when a library function is being called, rather than when the library is loaded. Also, this will allow us to "patch" what the library is doing and still retain its original behavior.

Last updated