Yauzabomber

Server-Side Template Injection (SSTI) in SMS template

Description

http://tasks.yauzactf.com:30003/

Your task is to learn a new service for fast sending messages at

Solution

Unintended

The .git directory and source code were exposed on the webserver. In app.py, the flag is exposed.

@app.route("/shop/", methods=['POST'])
@require_authorization
def shop_form(current_user):
    item_id = int(request.form.get('id'))
    user_obj, item_obj = db.ShopItem().buy_item(item_id, current_user.id)
    shop_items = db.ShopItem().list_items()

    if user_obj is None:
        return render_template("shop.html", shop_items=shop_items, error=1)

    if item_obj.phone == '+7777-(777)-777777':
        db.User().delete_login(current_user.login)
        return render_template("shop.html", shop_items=shop_items, flag='YauzaCTF{$M$_B000mb3r_$$t1_vu1n}')

    return render_template("shop.html", shop_items=shop_items, success=1)

Intended

There is a vulnerability in the "new chat" feature.

When sending an SMS to a number that does not begin with +1337 or 1337, the send_sms function in sms.py is called, with the keyword argument vulnfunc=db.User().add_money_to_login.

In the send_sms function, Flask's render_template_string function is used to generate the SMS message.

The resulting template is user-controllable, since login is our username.

We can then exploit Server-Side Template Injection (SSTI). Since the add_money_to_login function is added to the template context, we can manipulate the login variable to invoke this function. We essentially need two accounts, with one of the usernames being:

Then, when sending an SMS message, the following is called:

When rendering the template, the add_money_to_login function is called, adding money to our other account.

Now that we have sufficient money, we can buy the flag!

Last updated

Was this helpful?