Created
March 29, 2024 23:50
-
-
Save lietu/9f01eb7cb47a893341883c03b24682f6 to your computer and use it in GitHub Desktop.
Scan system for libraries and binaries potentially affected by any unknown liblzma vulnerabilities. Tested on Python 3.11
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import asyncio | |
import os | |
import shutil | |
import subprocess | |
from pathlib import Path | |
# Base configuration | |
LIB_DIRS = ["/lib", "/lib32", "/usr/lib", "/usr/lib32"] | |
BIN_DIRS = [ | |
"/bin", | |
"/sbin", | |
"/usr/bin", | |
"/usr/sbin", | |
"/usr/local/bin", | |
"/usr/local/sbin", | |
] | |
COMPROMISED_LIBS = {"/usr/lib/liblzma.so.5", "/usr/lib32/liblzma.so.5"} | |
# ---- SCRIPT LOGIC ---- # | |
def resolve(path_str) -> str: | |
return str(Path(path_str).resolve().absolute()) | |
LDD = shutil.which("ldd") | |
_COMPROMISED_LIBS = {resolve(path) for path in COMPROMISED_LIBS} | |
# Resolve all libraries to scan | |
ALL_SYSTEM_LIBS = set() | |
for lib_dir in LIB_DIRS: | |
lib_path = Path(lib_dir) | |
for found_lib in lib_path.glob("**/*.so*"): | |
ALL_SYSTEM_LIBS.add(resolve(found_lib.absolute())) | |
# Resolve all binaries to scan | |
ALL_BINS = set() | |
for bin_dir in BIN_DIRS: | |
bin_path = Path(bin_dir) | |
for found_bin in bin_path.glob("**/*"): | |
ALL_BINS.add(resolve(found_bin)) | |
# Counters | |
AFFECTED_BINARIES = 0 | |
SAFE_BINARIES = 0 | |
# Shell colors | |
CYAN = "\033[96m" | |
GREEN = "\033[92m" | |
YELLOW = "\033[93m" | |
RED = "\033[91m" | |
ENDC = "\033[0m" | |
async def uses_compromised_lib(full_path_to_check: str) -> bool: | |
proc = subprocess.run( | |
[LDD, full_path_to_check], | |
stdout=subprocess.PIPE, | |
stderr=subprocess.PIPE, | |
) | |
for line in proc.stdout.decode().splitlines(): | |
if line.strip() == "not a dynamic executable": | |
return False | |
# Each line looks like one of these: | |
# linux-vdso.so.1 (0x0000000000123abc) | |
# liblzma.so.5 => /usr/lib/liblzma.so.5 (0x0000000000123abc) | |
# /lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x0000000000123abc) | |
parts = line.split("=>") | |
if len(parts) > 1: | |
resolved = resolve(parts[1].strip().split(" ")[0]) | |
if resolved in _COMPROMISED_LIBS: | |
return True | |
return False | |
async def find_compromised_lib_usage(): | |
""" | |
Recursively search for libraries that may be affected | |
""" | |
print("Searching for other libraries using compromised libraries known of so far...") | |
found_more = False | |
for lib_to_check in ALL_SYSTEM_LIBS: | |
if lib_to_check not in _COMPROMISED_LIBS: | |
if await uses_compromised_lib(lib_to_check): | |
_COMPROMISED_LIBS.add(lib_to_check) | |
found_more = True | |
print(f"{YELLOW}{lib_to_check}{ENDC} is potentially compromised") | |
if found_more: | |
await find_compromised_lib_usage() | |
async def find_compromised_libs(): | |
print("Scanning for libraries") | |
await find_compromised_lib_usage() | |
print("") | |
async def find_compromised_bins(): | |
global AFFECTED_BINARIES, SAFE_BINARIES | |
print("Scanning for binaries") | |
for bin_to_check in sorted(ALL_BINS): | |
path_to_check = Path(bin_to_check) | |
if path_to_check.is_file() and os.access(bin_to_check, os.X_OK): | |
if await uses_compromised_lib(bin_to_check): | |
print(f"{RED}{bin_to_check}{ENDC} is potentially compromised") | |
AFFECTED_BINARIES += 1 | |
else: | |
SAFE_BINARIES += 1 | |
print("") | |
async def main(): | |
await find_compromised_libs() | |
await find_compromised_bins() | |
print( | |
f"Found {RED}{len(_COMPROMISED_LIBS):,}{ENDC} potentially compromised libraries " | |
f"of {CYAN}{len(ALL_SYSTEM_LIBS):,}{ENDC} total" | |
) | |
print( | |
f"Found {RED}{AFFECTED_BINARIES:,}{ENDC} potentially affected binaries " | |
f"of {CYAN}{len(ALL_BINS):,}{ENDC} total" | |
) | |
print(f"Probably safe binaries: {GREEN}{SAFE_BINARIES:,}{ENDC}") | |
if __name__ == "__main__": | |
asyncio.run(main()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment