T09 · Insecure Skill Coding Practices
- Location
scripts/office/soffice.py:56- Finding
Predictable LD_PRELOAD Shim Path Enables Local Arbitrary Code Execution
- Content
View full analysis
dict: env = os.environ.copy() if platform.system() == "Linux": env["SAL_USE_VCLPLUGIN"] = "svp" if _needs_shim(): shim = _ensure_shim() env["LD_PRELOAD"] = str(shim) return env _SHIM_SO = Path(tempfile.gettempdir()) / "lo_socket_shim.so" def _ensure_shim() -> Path: if _SHIM_SO.exists(): return _SHIM_SO src = Path(tempfile.gettempdir()) / "lo_socket_shim.c" src.write_text(_SHIM_SOURCE) subprocess.run( ["gcc", "-shared", "-fPIC", "-o", str(_SHIM_SO), str(src), "-ldl"], check=True, capture_output=True, ) src.unlink() return _SHIM_SO ``` ### Technical Analysis The code stores the compiled native shim at a predictable, system-wide temporary path such as `/tmp/lo_socket_shim.so`. If that path already exists, `_ensure_shim()` accepts it without validating: - File ownership - File permissions - Whether it is a regular file or symbolic link - Its cryptographic digest or expected contents - Whether it was created by the current process When Unix-domain sockets are unavailable, `get_soffice_env()` assigns this path to `LD_PRELOAD`. The dynamic linker consequently loads the referenced library before starting LibreOffice. A malicious shared library can execute arbitrary native code through a constructor before the legitimate program begins. The implementation also has a time-of-check/time-of-use race between the existence check and compilation. Predictable handling of `lo_socket_shim.c` presents an additional collision and symlink risk. ### Attack Path 1. A local attacker with access to the shared temporary directory prepares a malicious shared object containing a constructor that executes attacker ...[truncated 1130 chars]- Remediation
View remediation
