Full Report
Go is built to run concurrent code. In this CTF challenge, a subtle issue is abused around concurrency. The challenge has key-value store HTTP service. The service also has an arbitrary file read vulnerability by specifying the name. However, the flag file cannot be simply read because there is a flag string check. This protection can be bypassed using /proc file system. However, this requires the intended solution to have a file descriptor open for the flag. This works but wasn't the intended solution. Still, a super clever abuse and solve! The intended solution is a subtle issue with Go. The /get and /set HTTP handlers allow for concurrent access. The err variable for the arbitrary file read flag check is global! This means that other threads, such as set can use this variable as well. So, here's how to exploit it: Use the arbitrary file read to read the flag on the /get API. This will return an error because of the string check. Use /set to change the error variable to be false. The check on /get call on error will now fail because it was set in the other thread. Flag is read! Concurrency is Golang is a core component of the design. As a result, insecure concurrent uses should be checked for. I loved both the intended and unintended solutions for this!
Analysis Summary
# Vulnerability: Global Variable Race Condition in Go HTTP Service
## CVE Details
- **CVE ID**: N/A (CTF Challenge Scenario)
- **CVSS Score**: 7.5 (High) - Estimated based on unauthorized data access.
- **CWE**: CWE-362 (Concurrent Execution using Shared Resource with Improper Synchronization - 'Race Condition'), CWE-22 (Improper Limitation of a Pathname to a Restricted Directory).
## Affected Systems
- **Products**: Custom Go-based Key-Value Store HTTP Service.
- **Versions**: Internal/Challenge build.
- **Configurations**: Services where HTTP handlers share global state variables for error handling or logic checks without proper synchronization (mutexes/atomic types).
## Vulnerability Description
The vulnerability stems from two primary flaws:
1. **Arbitrary File Read**: The `/get` API allows users to specify filenames, enabling the reading of files outside the intended scope via directory traversal or direct naming.
2. **Insecure Concurrency (Race Condition)**: The application utilizes a **global** `err` variable to store the result of a security check (a string filter designed to block access to the "flag" file). Because Go handles HTTP requests concurrently using goroutines, this global variable is shared across all active threads. A developer oversight allows one request to overwrite the state of the `err` variable while another request is mid-execution.
## Exploitation
- **Status**: PoC available (CTF context).
- **Complexity**: Medium (Requires precise timing/synchronization of requests).
- **Attack Vector**: Network (HTTP).
### Exploitation Steps:
1. **Trigger 1**: Initiate a `/get` request for the restricted flag file. The application performs a string check, finds the flag, and sets the global `err` variable to `true`.
2. **Trigger 2 (Race)**: Simultaneously send a `/set` request that triggers a successful operation, forcing the global `err` variable to be overwritten to `false` (or `nil`).
3. **Bypass**: If the first thread checks the value of the global `err` after the second thread has overwritten it, the security block is bypassed, and the flag content is returned to the attacker.
*Note: An unintended solution also exists utilizing the `/proc` filesystem if the flag file descriptor remains open.*
## Impact
- **Confidentiality**: High (Full unauthorized access to restricted system files/flags).
- **Integrity**: Low (Ability to manipulate global error states).
- **Availability**: None reported.
## Remediation
### Patches
- **Code Fix**: Remove global variables for error handling. Use local function-scoped variables or pass variables through context to ensure thread isolation.
- **Input Validation**: Implement strict path sanitization to prevent arbitrary file access.
### Workarounds
- Implement a `sync.Mutex` to lock the global variable during the check-and-read operation, though this is less efficient than using local variables.
- Deploy a Web Application Firewall (WAF) to block directory traversal patterns and access to sensitive paths like `/proc`.
## Detection
- **Indicators of Compromise**: High volumes of concurrent `/get` and `/set` requests from the same source IP. Logs showing attempts to access sensitive files or files containing "flag" keywords.
- **Detection Methods**: Static Analysis Security Testing (SAST) tools can identify the use of global variables in concurrent functions. Dynamic Analysis (DAST) can detect race conditions through high-concurrency fuzzing.
## References
- [hxtps://www.youtube.com/watch?v=REPLACE_WITH_ACTUAL_VIDEO_ID] (Defanged)
- Go Memory Model: [hxtps://go.dev/ref/mem] (Defanged)
- CWE-362 Detail: [hxtps://cwe.mitre.org/data/definitions/362.html] (Defanged)