# Vulnerable: File write with user-controlled paths and content
from django.http import JsonResponse
from django.views import View
from django.conf import settings
import os
# Dangerous: Direct file write with request data
class FileWriteView(View):
def post(self, request):
filename = request.POST.get('filename', '')
content = request.POST.get('content', '')
directory = request.POST.get('directory', '')
# CRITICAL: User controls file path and content
if directory:
file_path = os.path.join(settings.MEDIA_ROOT, directory, filename)
else:
file_path = os.path.join(settings.MEDIA_ROOT, 'uploads', filename)
try:
with open(file_path, 'w') as f:
f.write(content)
return JsonResponse({'status': 'File written successfully'})
except Exception as e:
return JsonResponse({'error': str(e)})
# Another dangerous pattern
def save_user_config(request):
config_name = request.POST.get('config_name', '')
config_data = request.POST.get('config_data', '')
user_id = request.POST.get('user_id', '')
# Dangerous: User controls config path and content
config_path = f'/var/app/configs/{user_id}/{config_name}.conf'
try:
os.makedirs(os.path.dirname(config_path), exist_ok=True)
with open(config_path, 'w') as f:
f.write(config_data)
return JsonResponse({'status': 'Config saved'})
except Exception as e:
return JsonResponse({'error': str(e)})
# Log file creation
def create_log_entry(request):
log_name = request.GET.get('log', '')
log_content = request.POST.get('content', '')
date = request.GET.get('date', '')
# Dangerous: User-controlled log path
log_path = f'/var/log/app/{date}/{log_name}.log'
try:
os.makedirs(os.path.dirname(log_path), exist_ok=True)
with open(log_path, 'a') as f:
f.write(log_content + '\n')
return JsonResponse({'status': 'Log entry created'})
except Exception as e:
return JsonResponse({'error': str(e)})
# Template file creation
def save_template(request):
template_name = request.POST.get('template_name', '')
template_content = request.POST.get('template_content', '')
template_type = request.POST.get('type', '')
# Dangerous: User controls template path and content
template_path = os.path.join(settings.BASE_DIR, 'templates', template_type, template_name)
try:
os.makedirs(os.path.dirname(template_path), exist_ok=True)
with open(template_path, 'w') as f:
f.write(template_content)
return JsonResponse({'status': 'Template saved'})
except Exception as e:
return JsonResponse({'error': str(e)})
# File upload with custom path
def upload_file_custom_path(request):
if 'file' not in request.FILES:
return JsonResponse({'error': 'No file uploaded'})
uploaded_file = request.FILES['file']
custom_path = request.POST.get('path', '')
filename = request.POST.get('filename', uploaded_file.name)
# Dangerous: User controls file path
full_path = os.path.join(settings.MEDIA_ROOT, custom_path, filename)
try:
os.makedirs(os.path.dirname(full_path), exist_ok=True)
with open(full_path, 'wb') as f:
for chunk in uploaded_file.chunks():
f.write(chunk)
return JsonResponse({'status': 'File uploaded', 'path': full_path})
except Exception as e:
return JsonResponse({'error': str(e)})
# Backup file creation
def create_backup_file(request):
backup_name = request.POST.get('backup_name', '')
backup_data = request.POST.get('data', '')
backup_dir = request.POST.get('directory', 'daily')
# Dangerous: User controls backup path
backup_path = f'/backups/{backup_dir}/{backup_name}.bak'
try:
with open(backup_path, 'w') as f:
f.write(backup_data)
return JsonResponse({'status': 'Backup created'})
except Exception as e:
return JsonResponse({'error': str(e)})
# Secure: Safe file write operations in Django
from django.http import JsonResponse
from django.views import View
from django.conf import settings
from django.core.exceptions import ValidationError
from django.core.files.storage import default_storage
from pathlib import Path
import os
import re
import json
# Safe: Validated file write
class SafeFileWriteView(View):
def post(self, request):
filename = request.POST.get('filename', '')
content = request.POST.get('content', '')
try:
# Validate inputs
validated_data = self.validate_file_write_data(filename, content)
# Write file safely
file_path = self.write_file_safely(validated_data)
return JsonResponse({
'status': 'File written successfully',
'filename': validated_data['filename']
})
except ValidationError as e:
return JsonResponse({'error': str(e)}, status=400)
def validate_file_write_data(self, filename, content):
# Validate filename
if not filename or len(filename) > 100:
raise ValidationError('Invalid filename length')
# Only allow safe characters in filename
if not re.match(r'^[a-zA-Z0-9._-]+$', filename):
raise ValidationError('Filename contains invalid characters')
# Prevent hidden files and traversal
if filename.startswith('.') or '..' in filename:
raise ValidationError('Invalid filename format')
# Check file extension
allowed_extensions = ['.txt', '.json', '.csv', '.log']
if not any(filename.lower().endswith(ext) for ext in allowed_extensions):
raise ValidationError('File extension not allowed')
# Validate content
if not content:
raise ValidationError('Content cannot be empty')
if len(content) > 1024 * 1024: # 1MB limit
raise ValidationError('Content too large')
# Basic content validation
try:
content.encode('utf-8')
except UnicodeEncodeError:
raise ValidationError('Content contains invalid characters')
return {'filename': filename, 'content': content}
def write_file_safely(self, data):
# Define safe base directory
upload_dir = Path(settings.MEDIA_ROOT) / 'user_uploads'
upload_dir.mkdir(exist_ok=True)
# Construct safe file path
file_path = upload_dir / data['filename']
# Validate path is within upload directory
try:
resolved_path = file_path.resolve()
upload_dir_resolved = upload_dir.resolve()
resolved_path.relative_to(upload_dir_resolved)
except ValueError:
raise ValidationError('File path outside allowed directory')
# Check if file already exists
if resolved_path.exists():
raise ValidationError('File already exists')
# Write file
try:
with open(resolved_path, 'w', encoding='utf-8') as f:
f.write(data['content'])
return resolved_path
except PermissionError:
raise ValidationError('Permission denied')
except Exception:
raise ValidationError('File write error')
# Safe: Configuration management
def safe_save_user_config(request):
config_type = request.POST.get('config_type', '')
config_data = request.POST.get('config_data', '')
try:
# Validate inputs
validated_config = validate_config_data(config_type, config_data)
# Save configuration safely
save_config_safely(request.user, validated_config)
return JsonResponse({'status': 'Configuration saved'})
except ValidationError as e:
return JsonResponse({'error': str(e)}, status=400)
def validate_config_data(config_type, config_data):
# Validate config type
allowed_types = ['theme', 'notifications', 'privacy', 'display']
if config_type not in allowed_types:
raise ValidationError('Configuration type not allowed')
# Validate config data
try:
config_obj = json.loads(config_data)
except json.JSONDecodeError:
raise ValidationError('Invalid JSON format')
# Validate config structure based on type
if config_type == 'theme':
allowed_keys = {'color_scheme', 'font_size', 'layout'}
allowed_values = {
'color_scheme': ['light', 'dark', 'auto'],
'font_size': ['small', 'medium', 'large'],
'layout': ['compact', 'comfortable', 'spacious']
}
elif config_type == 'notifications':
allowed_keys = {'email_notifications', 'push_notifications', 'frequency'}
allowed_values = {
'email_notifications': [True, False],
'push_notifications': [True, False],
'frequency': ['immediate', 'daily', 'weekly']
}
# Add other config type validations...
# Validate keys and values
validated_config = {}
for key, value in config_obj.items():
if key in allowed_keys and value in allowed_values.get(key, [value]):
validated_config[key] = value
return {'type': config_type, 'data': validated_config}
def save_config_safely(user, config_data):
# Use Django model to save configuration
from .models import UserConfiguration
config, created = UserConfiguration.objects.get_or_create(
user=user,
config_type=config_data['type'],
defaults={'config_data': config_data['data']}
)
if not created:
config.config_data = config_data['data']
config.save()
# Safe: Log entry creation
def safe_create_log_entry(request):
log_type = request.POST.get('log_type', '')
message = request.POST.get('message', '')
try:
# Validate inputs
validated_log = validate_log_entry(log_type, message)
# Create log entry safely
create_log_entry_safely(request.user, validated_log)
return JsonResponse({'status': 'Log entry created'})
except ValidationError as e:
return JsonResponse({'error': str(e)}, status=400)
def validate_log_entry(log_type, message):
# Validate log type
allowed_types = ['user_action', 'system_event', 'error', 'security']
if log_type not in allowed_types:
raise ValidationError('Log type not allowed')
# Validate message
if not message or len(message) > 1000:
raise ValidationError('Invalid message length')
# Sanitize message
clean_message = re.sub(r'[\x00-\x1f\x7f-\x9f]', '', message)
return {'type': log_type, 'message': clean_message}
def create_log_entry_safely(user, log_data):
# Use Django logging framework
import logging
logger = logging.getLogger(f'app.{log_data["type"]}')
log_message = f'User {user.id} ({user.username}): {log_data["message"]}'
if log_data['type'] == 'error':
logger.error(log_message)
elif log_data['type'] == 'security':
logger.warning(log_message)
else:
logger.info(log_message)
# Safe: Template management
def safe_save_template(request):
template_id = request.POST.get('template_id', '')
template_content = request.POST.get('content', '')
try:
# Validate inputs
validated_template = validate_template_data(template_id, template_content)
# Save template safely
save_template_safely(request.user, validated_template)
return JsonResponse({'status': 'Template saved'})
except ValidationError as e:
return JsonResponse({'error': str(e)}, status=400)
def validate_template_data(template_id, content):
# Validate template ID
if not template_id.isdigit():
raise ValidationError('Invalid template ID')
template_id = int(template_id)
# Validate content
if not content or len(content) > 10000:
raise ValidationError('Invalid template content length')
# Basic HTML validation (remove dangerous elements)
import html
clean_content = html.escape(content)
return {'id': template_id, 'content': clean_content}
def save_template_safely(user, template_data):
# Use Django model to save template
from .models import UserTemplate
try:
template = UserTemplate.objects.get(
id=template_data['id'],
user=user
)
template.content = template_data['content']
template.save()
except UserTemplate.DoesNotExist:
raise ValidationError('Template not found or access denied')
# Safe: File upload with validation
def safe_upload_file(request):
if 'file' not in request.FILES:
return JsonResponse({'error': 'No file uploaded'}, status=400)
uploaded_file = request.FILES['file']
file_category = request.POST.get('category', '')
try:
# Validate file and category
validated_upload = validate_file_upload(uploaded_file, file_category)
# Save file safely
file_path = save_uploaded_file_safely(request.user, validated_upload)
return JsonResponse({
'status': 'File uploaded successfully',
'filename': validated_upload['filename']
})
except ValidationError as e:
return JsonResponse({'error': str(e)}, status=400)
def validate_file_upload(uploaded_file, category):
# Validate file size
max_size = 10 * 1024 * 1024 # 10MB
if uploaded_file.size > max_size:
raise ValidationError('File too large')
# Validate filename
filename = uploaded_file.name
if not filename or len(filename) > 255:
raise ValidationError('Invalid filename')
# Sanitize filename
safe_filename = re.sub(r'[^a-zA-Z0-9._-]', '_', filename)
# Validate file type
allowed_types = {
'images': ['image/jpeg', 'image/png', 'image/gif'],
'documents': ['application/pdf', 'text/plain'],
'data': ['text/csv', 'application/json']
}
if category not in allowed_types:
raise ValidationError('Invalid file category')
if uploaded_file.content_type not in allowed_types[category]:
raise ValidationError('File type not allowed for this category')
return {
'file': uploaded_file,
'filename': safe_filename,
'category': category
}
def save_uploaded_file_safely(user, upload_data):
# Define safe upload directory
upload_dir = Path(settings.MEDIA_ROOT) / 'user_files' / str(user.id) / upload_data['category']
upload_dir.mkdir(parents=True, exist_ok=True)
# Generate unique filename
import uuid
unique_filename = f"{uuid.uuid4()}_{upload_data['filename']}"
file_path = upload_dir / unique_filename
# Save file
uploaded_file = upload_data['file']
try:
with open(file_path, 'wb') as f:
for chunk in uploaded_file.chunks():
f.write(chunk)
return file_path
except Exception:
raise ValidationError('File save error')