crypto

Let's Failcrypt 2

Punkty: 253
Rozwiązań: 14

This is a fixed version of the task Let's Failcrypt, which had an unintended solution.

Let's Failcrypt allows you to easily generate a certificate for your domain.
We know that admin of crypto.legit-service.ovh uses this service.
Can you trick them into issuing a certificate for this domain without being the owner?

https://failcrypt2.ecsc19.hack.cert.pl


Source code:

app.py

import random
from os import urandom

from flask import Flask, render_template, request, session, send_from_directory

from challenge import verify

from secrets import flag

app = Flask(__name__)
app.secret_key = urandom(16)


@app.route('/static/bulma.min.css')
def css():
    return send_from_directory('/code/static/', 'bulma.min.css')


@app.route('/')
def index():
    nonce = hex(random.randint(2 ** 511, 2 ** 512))[2:-1]
    session['nonce'] = nonce
    return render_template('index.html', nonce=nonce)


@app.route('/verify', methods=['POST'])
def verify_access():
    try:
        key = request.form['pubkey']
        domain = str(request.form['domain'])
        nonce = int(session['nonce'], 16)
        if verify(key, domain, nonce):
            if domain == "crypto.legit-service.ovh":
                return render_template('result.html', content=flag)
            else:
                return render_template('result.html', content="Sorry, for now we are only able to generate certificates for 'crypto.legit-service.ovh'")
        else:
            return render_template('result.html', content="Nice try...")
    except Exception as e:
        return render_template('result.html', content="You've broken something...")



if __name__ == '__main__':
    app.run()


challenge.py

from Crypto.PublicKey import RSA
from Crypto.Util.number import bytes_to_long


def get_signature_record(domain):
    from dnsknife import resolver
    ans = resolver.query(domain, 'TXT')
    txt = ans.response.answer[0][0].strings[0]
    return bytes_to_long(txt)


def verify_signature(pubkey, signature, nonce):
    pubkey = RSA.importKey(pubkey)
    e, n = pubkey.e, pubkey.n

    # Don't allow weak keys
    if e < 65537:
        return False
    return pow(signature, e, n) == nonce


def verify(pubkey, domain, nonce):
    return verify_signature(pubkey, get_signature_record(domain), nonce)

Format flagi: ecsc19{litery_cyfry_i_znaki_specjalne}.

Aby wysłać flagę, musisz się zalogować.