One Step Closer
2 minutos de lectura
Se nos proporciona el código fuente en Python para cifrar la flag, y una aplicación Flask que llama a la función de cifrado:
from Crypto.Util.number import long_to_bytes, bytes_to_long, getPrime, inverse
import random
FLAG = b'HTB{--REDACTED--}'
p = getPrime(1024)
q = getPrime(1024)
n = p * q
e = 257
def encrypt_flag():
a = random.getrandbits(1024)
b = random.getrandbits(1024)
flag = bytes_to_long(FLAG)
msg = a*flag + b
ct = pow(msg, e, n)
return {'ct': format(ct, 'x'), 'n': format(n, 'x'), 'e': format(e, 'x'), 'a': format(a, 'x'), 'b': format(b, 'x')}
from flask import *
from chall import encrypt_flag
app = Flask(__name__)
@app.route('/', methods=['GET'])
def index():
return render_template('index.html')
@app.route('/api/get_flag', methods=['GET'])
def get_flag():
payload = encrypt_flag()
return jsonify(payload)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=1337)
Podemos expresar los cálculos anteriores de un criptosistema RSA en términos matemáticos (sea
Teniendo en cuenta que podemos llamar a encrypt_flag
varias veces, podríamos matizar que:
Esto es un claro ejemplo de ataque de Franklin-Reiter related-message, ya que podemos definir dos polinomios
Como
Podemos implementar el ataque en SageMath así:
def composite_modulus_gcd(f, g):
if g == 0:
return f.monic()
return composite_modulus_gcd(g, f % g)
def franklin_reiter(n, e, ct1, ct2, a1, a2, b1, b2):
P.<x> = PolynomialRing(Zmod(n))
f = (a1 * x + b1) ^ e - ct1
g = (a2 * x + b2) ^ e - ct2
return -composite_modulus_gcd(f, g).coefficients()[0] % n
Nótese el uso de composite_modulus_gcd
porque
Lo único que falta es tomar los parámetros de cifrado de la aplicación Flask y realizar el ataque:
$ sage solve.sage 104.248.162.85:32441
HTB{RSA_f1n1t3_d1ffs_@nd_r31473d_m355493_4774ck5_:eyes:}
El script completo se puede encontrar aquí: solve.sage
.