Prevention of OS Command Injection attacks
import os
from django.http import HttpResponse
def run_command(request):
command = request.GET.get('command')
result = os.system(command)
return HttpResponse(result)
The above code is a simple Django view that takes a command from the HTTP GET parameters and executes it on the server using
os.system()
. This is a clear example of an OS command injection vulnerability, as it allows any user to run arbitrary commands on the server.
In this case, the
command
parameter is directly taken from the user input (HTTP GET parameter) without any sanitization or validation. This means that an attacker could inject any command they want. For example, they could use the
;
character to add additional commands, or use command substitution with
$(command)
to execute the output of another command.
Moreover, the
os.system()
function is used to execute the command, which is a high-risk function as it executes the command in a subshell, allowing the command to interact with the environment, change directories, read and write files, and even spawn new processes.
This can lead to a variety of attacks, including but not limited to: data theft, data modification, denial of service, or even full system compromise if the application is running with high privileges.
import os
import subprocess
from django.http import HttpResponse
from django.core.exceptions import ValidationError
ALLOWED_COMMANDS = ['ls', 'date', 'uptime'] # Define your own list of allowed commands
def validate_command(command):
if command not in ALLOWED_COMMANDS:
raise ValidationError(f'Invalid command: {command}')
def run_command(request):
command = request.GET.get('command')
validate_command(command)
result = subprocess.run([command], capture_output=True, text=True)
return HttpResponse(result.stdout)
The updated code includes several changes to mitigate the risk of OS Command Injection:
1. Input Validation and Sanitization: The
validate_command
function is introduced to validate the 'command' parameter against a whitelist of allowed commands (
ALLOWED_COMMANDS
). If the command is not in the whitelist, a
ValidationError
is raised. This ensures that only predefined, safe commands can be executed.
2. Safer Function Usage: The
os.system
function is replaced with
subprocess.run
. Unlike
os.system
,
subprocess.run
does not invoke a shell by default, making it less susceptible to shell injection attacks. The
capture_output=True
argument is used to capture the command's output, and
text=True
is used to return the output as a string.
3. Error Handling: Django's built-in
ValidationError
is used for error handling. If an invalid command is provided, a clear, user-friendly error message is returned without revealing any sensitive system information.
4. Privilege Limitation and Web Application Firewall (WAF): These are not reflected in the code but are important considerations. The application should be run with the least privileges necessary to limit potential damage from an attack. Additionally, using a WAF can provide an extra layer of security by filtering out malicious input.