T05 · Unauthorized Access and Privilege Escalation
- Location
music-server.py:17- Finding
Predictable lock file allows symlink-based file truncation and permission modification
- Content
View full analysis
Vulnerability Details
File Location:
music-server.py, lines 17 and 28-36
Vulnerability Type: Insecure temporary file handling and symbolic-link following
Risk Level: HighVulnerable Code
python LOCK_FILE = Path(os.environ.get("MUSIC_LOCK_FILE", "/tmp/music_player.lock")) def save_lock_file(): """Save server port to lock file""" try: with open(LOCK_FILE, 'w') as f: f.write(str(CONTROL_PORT)) os.chmod(LOCK_FILE, 0o666) # Make it readable by all except Exception as e: print(f"Error saving lock file: {e}", file=sys.stderr)Technical Analysis
The default lock file uses the predictable path
/tmp/music_player.lock, located in a shared temporary directory. The file is opened in write mode without preventing symbolic-link traversal, checking ownership, or atomically ensuring that a new regular file is being created.If the path is a symbolic link,
open(..., 'w')follows the link and truncates the target before writing the port number. The subsequentos.chmod()also follows the link under normal platform behavior and attempts to change the target permissions to0666, making it writable by every local user.Exploitability depends on operating-system protections for shared temporary directories, such as Linux protected-symlink settings, and on the permissions and identity under which the server runs. These mitigations should not be relied upon as the application's security boundary.
Attack Path
- A local attacker identifies that the server will use
/tmp/music_player.lock. - Before the server starts, the attacker places a symbolic link at that path pointing to a file writable by the account that will run the server.
- A victim or privileged service account starts
music-server.py. open(LOCK_FILE, 'w')follows the symbolic link, truncates the target, and writes12346.os.chmod(LOCK_FILE, 0o666)attempts to ma ...[truncated 757 chars]
- A local attacker identifies that the server will use
- Remediation
View remediation
Remediation Suggestions
- Store runtime state in a private per-user runtime directory, such as
$XDG_RUNTIME_DIR, with directory permissions of0700. - Create the file atomically using
os.open()withO_CREAT,O_EXCL, and, where supported,O_NOFOLLOW. - Create the lock file with mode
0600; do not make it world-writable. - Before using an existing path, use
lstat()and reject symbolic links and non-regular files. - Verify that the file is owned by the expected user.
- Prefer an advisory lock on an already securely opened descriptor rather than treating a predictable pathname as authoritative.
- Avoid running the music server with elevated privileges.
- Store runtime state in a private per-user runtime directory, such as
