关于 security-django
security-django 是供开发者审查 Django 应用的安全审计技能,涵盖部署设置、中间件与 CSRF,以及常见漏洞,并提供较安全的代码模式和审计命令。
主要功能
- 01关键设置审查
- 02安全中间件与 CSRF 检查
- 03常见漏洞模式
- 04更安全的代码示例
- 05快速审计命令
- 06部署加固清单
适用场景
- 01审查 Django 生产环境设置
- 02检查 CSRF 豁免与中间件
- 03查找注入和路径遍历风险
- 04检查身份验证与 DRF 权限
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ igorwarzocha/ opencode-workflows --skill security-django安装后在 Claude Code 中输入/security-django确认已加载。
附带文件scripts/scan.sh
详细介绍
针对 Django 应用的安全审计模式,涵盖关键设置、安全中间件、CSRF 保护和常见漏洞。
关键设置(settings.py)
SECRET_KEY
# ❌ CRITICAL: Hardcoded or committed
SECRET_KEY = 'django-insecure-abc123...'
SECRET_KEY = 'my-super-secret-key'
# ✓ From environment
import os
SECRET_KEY = os.environ['DJANGO_SECRET_KEY']
# ✓ Or use django-environ
import environ
env = environ.Env()
SECRET_KEY = env('SECRET_KEY')
检查: SECRET_KEY 是否存放在 .env 中,且 .env 是否已加入 .gitignore?
DEBUG
# ❌ CRITICAL: Debug in production
DEBUG = True # Exposes full stack traces, settings, SQL queries
# ✓ Environment-controlled
DEBUG = os.environ.get('DEBUG', 'False').lower() == 'true'
ALLOWED_HOSTS
# ❌ CRITICAL: Accept any host
ALLOWED_HOSTS = ['*']
# ❌ HIGH: Empty in production (500 errors, but still bad)
ALLOWED_HOSTS = []
# ✓ Explicit hosts
ALLOWED_HOSTS = ['example.com', 'www.example.com']
安全中间件
必需的中间件
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware', # MUST be first!
# ...
'django.middleware.csrf.CsrfViewMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
检查: 是否包含 SecurityMiddleware,且位于靠前的位置?
安全中间件设置
# ✓ Enable these in production
SECURE_BROWSER_XSS_FILTER = True # Deprecated but harmless
SECURE_CONTENT_TYPE_NOSNIFF = True
SECURE_HSTS_SECONDS = 31536000 # 1 year
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True
SECURE_SSL_REDIRECT = True # Force HTTPS
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
CSRF 保护
禁用 CSRF(严重)
# ❌ CRITICAL: Globally disabled
MIDDLEWARE = [
# 'django.middleware.csrf.CsrfViewMiddleware', # Commented out!
]
# ❌ HIGH: Decorator abuse
@csrf_exempt
def payment_webhook(request): # MAY be OK for webhooks with other auth
...
@csrf_exempt
def update_profile(request): # MUST NOT do this!
...
审计: 搜索 @csrf_exempt,每处都需要有合理说明。
CSRF 可信来源(Django 4.0+)
# ❌ Too permissive
CSRF_TRUSTED_ORIGINS = ['https://*']
# ✓ Explicit
CSRF_TRUSTED_ORIGINS = ['https://example.com', 'https://admin.example.com']
常见漏洞
SQL 注入
# ❌ Raw SQL with string formatting
User.objects.raw(f"SELECT * FROM users WHERE id = {user_id}")
cursor.execute(f"DELETE FROM logs WHERE date < '{date}'")
# ✓ Parameterized
User.objects.raw("SELECT * FROM users WHERE id = %s", [user_id])
cursor.execute("DELETE FROM logs WHERE date < %s", [date])
# ✓ ORM (safe by default)
User.objects.filter(id=user_id)
命令注入
# ❌ User input in subprocess
import subprocess
subprocess.run(f"convert {user_filename} output.png", shell=True)
os.system(f"process {user_input}")
# ✓ Use arrays, avoid shell=True
subprocess.run(["convert", user_filename, "output.png"])
路径遍历
# ❌ User-controlled path
def download(request, filename):
return FileResponse(open(f'uploads/{filename}', 'rb'))
# ✓ Validate path
import os
def download(request, filename):
safe_name = os.path.basename(filename)
filepath = os.path.join(settings.UPLOAD_DIR, safe_name)
if not filepath.startswith(settings.UPLOAD_DIR):
raise Http404()
return FileResponse(open(filepath, 'rb'))
IDOR(不安全的直接对象引用)
# ❌ No ownership check
class DocumentView(View):
def get(self, request, doc_id):
doc = Document.objects.get(id=doc_id)
return JsonResponse(doc.to_dict())
# ✓ Check ownership
class DocumentView(LoginRequiredMixin, View):
def get(self, request, doc_id):
doc = Document.objects.get(id=doc_id, owner=request.user)
return JsonResponse(doc.to_dict())
缺少身份验证装饰器
# ❌ No auth required
def admin_dashboard(request):
return render(request, 'admin/dashboard.html', {'users': User.objects.all()})
# ✓ Auth required
@login_required
@user_passes_test(lambda u: u.is_staff)
def admin_dashboard(request):
...
Django REST Framework
# Check DRF settings
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
# ❌ SessionAuth without CSRF = vulnerable
'rest_framework.authentication.SessionAuthentication',
],
'DEFAULT_PERMISSION_CLASSES': [
# ❌ Allow any by default
'rest_framework.permissions.AllowAny',
# ✓ Require auth by default
'rest_framework.permissions.IsAuthenticated',
],
}
快速审计命令
# Check critical settings
rg "(SECRET_KEY|DEBUG|ALLOWED_HOSTS)" settings*.py
# Find csrf_exempt usage
rg "@csrf_exempt" . -g "*.py"
# Django deployment checklist (high signal)
python manage.py check --deploy
# Find raw SQL
rg "\.raw\(|cursor\.execute\(" . -g "*.py" -A 1
# Find subprocess/os.system
rg "(subprocess\.|os\.system|os\.popen)" . -g "*.py"
# Check for missing login_required
rg "^def " views.py | head -20 # Then check which have decorators
# Find shell=True
rg "shell\s*=\s*True" . -g "*.py"
加固检查清单
- SECRET_KEY 来自环境变量,而非硬编码
- 生产环境中 DEBUG = False
- 明确设置 ALLOWED_HOSTS(不使用通配符)
- 已启用并配置 SecurityMiddleware
- 已启用 CSRF 中间件
- SECURE_SSL_REDIRECT = True
- SESSION_COOKIE_SECURE = True
- CSRF_COOKIE_SECURE = True
- 没有未经合理说明的 @csrf_exempt
- 所有视图都具有适当的身份验证装饰器
- 没有使用字符串格式化的原始 SQL
- DRF 将 IsAuthenticated 设为默认权限
评论
支持 Markdown