Hack. Eat. Sleep. Repeat!!!
@app.route('/profile', methods=['GET', 'POST'])
def profile():
if not session.get('username'):
return redirect('/login')
profiles_file = 'profile/' + session.get('username')
profiles_file = profiles_file if profiles_file.endswith('.html') else profiles_file + '.html'
if commonpath((app.root_path, abspath(profiles_file))) != app.root_path:
return render_template('error.html', msg='Error processing profile file!', return_to='/profile')
if request.method == 'POST':
with open(profiles_file, 'w') as f:
f.write(request.form.get('profile'))
return redirect('/profile')
profile=''
if exists(profiles_file):
with open(profiles_file, 'r') as f:
profile = f.read()
return render_template('profile.html', username=session.get('username'), profile=profile)
@app.route('/show_profile', methods=['GET', 'POST'])
def show_profile():
if not session.get('username'):
return redirect('/login')
profiles_file = 'profile/' + session.get('username')
if commonpath((app.root_path, abspath(profiles_file))) != app.root_path:
return render_template('error.html', msg='Error processing profile file!', return_to='/profile')
profile = ''
if exists(profiles_file):
with open(profiles_file, 'r') as f:
profile = f.read()
return render_template('show_profile.html', username=session.get('username'), profile=profile)
Arbitrary file write and read to Remote Code Execution
.The code picks the username and use it to create an html file which we can see as a jinja template
.The username query is not filtered which allows us to control the path and rewrite other files e.g templates in the templates
directory.The mode of exploitation revoles around “controlling the path to one of the templates with the username e.g ../templates/error.html
which will be read,later we can inject the template with code like config.__init.\_\_globals\_\_.os.popen('ls').read()
.profiles_file = 'profile/' + session.get('username')
profiles_file = profiles_file if profiles_file.endswith('.html') else profiles_file + '.html'
if commonpath((app.root_path, abspath(profiles_file))) != app.root_path:
return render_template('error.html', msg='Error processing profile file!', return_to='/profile')
if request.method == 'POST':
with open(profiles_file, 'w') as f:
f.write(request.form.get('profile'))
return redirect('/profile')
profile=''
if exists(profiles_file):
with open(profiles_file, 'r') as f:
profile = f.read()
True
as seen in the code.app.config['TEMPLATES_AUTO_RELOAD'] = True
../templates/error.html
error.html
.I was able to trigger it by registering an already registered user.Code-:@app.route('/register', methods=['GET', 'POST'])
def register():
if request.method == 'POST':
username = request.form.get('username')
if username in users:
return render_template('error.html', msg='Username already taken!', return_to='/register') ### Template gets triggered here
PWNME{afb7daa3a595522882f6a9efae30c4ec}