| Tiago Coimbra

15. Race Condition

A digital illustration of a green, devilish creature with sharp fangs and a ferocious expression. The figure’s head is adorned with horns and mechanical details, with an overall symmetrical design, set against a black background.

Race Condition

Category: #Code-Execution-Attack

Attack: A race condition occurs when multiple processes or threads access shared resources in an unpredictable sequence, leading to inconsistent results, data corruption, or security vulnerabilities.

Attack Code Example (Race Condition in File Access):

# Exploit race condition in a file access program
while true; do
    ln -sf /etc/passwd /tmp/vulnerable_file;
    ln -sf /tmp/exploit /tmp/vulnerable_file;
done

The attack script rapidly switches between files, exploiting a race condition in a program that accesses /tmp/vulnerable_file, causing the program to unintentionally write to /etc/passwd.

Vulnerable Code Example (Python):

import os
import time

def write_to_file(filename):
    if os.path.exists(filename):
        with open(filename, 'w') as f:
            f.write("Sensitive data\n")
        print("File written successfully")
    else:
        print("File does not exist")
        time.sleep(2)  # Simulate race condition window
        with open(filename, 'w') as f:
            f.write("Data written after check")

In this example, a time gap between checking if the file exists and writing to it introduces a race condition that could be exploited.

Remediation Steps:

  • Atomic Operations: Ensure file operations are atomic (i.e., operations that complete in a single step).
  • File Locking: Use file locking mechanisms to prevent multiple processes or threads from accessing the same resource simultaneously.
  • Avoid Time-of-Check-Time-of-Use (TOCTOU) Issues: Ensure that the state of the file remains consistent between checking it and using it.

Safe Code Example (Using flock for File Locking in Python):

import fcntl

def write_to_file(filename):
    with open(filename, 'w') as f:
        fcntl.flock(f, fcntl.LOCK_EX)  # Lock file to prevent race conditions
        f.write("Sensitive data\n")
        fcntl.flock(f, fcntl.LOCK_UN)  # Unlock the file after writing
    print("File written safely with locking")

Reference: Race Conditions - PortSwigger