From 315ae724add532aa7959aa5f3a4475890b31f349 Mon Sep 17 00:00:00 2001 From: Yan Date: Fri, 27 Sep 2024 23:55:37 -0700 Subject: [PATCH] cpa over http --- cryptography/cpa-http/DESCRIPTION.md | 6 +++ cryptography/cpa-http/run | 62 ++++++++++++++++++++++++++++ cryptography/module.yml | 2 + 3 files changed, 70 insertions(+) create mode 100644 cryptography/cpa-http/DESCRIPTION.md create mode 100755 cryptography/cpa-http/run diff --git a/cryptography/cpa-http/DESCRIPTION.md b/cryptography/cpa-http/DESCRIPTION.md new file mode 100644 index 00000000..c5a06ec5 --- /dev/null +++ b/cryptography/cpa-http/DESCRIPTION.md @@ -0,0 +1,6 @@ +Okay, now we'll try that attack in a slightly more realistic scenario. +Can you remember your SQL to carry out the attack and recover the flag? + +---- +**HINT:** +Remember that you can make select return chosen plaintext by doing `SELECT 'my_plaintext'`! diff --git a/cryptography/cpa-http/run b/cryptography/cpa-http/run new file mode 100755 index 00000000..83da56f7 --- /dev/null +++ b/cryptography/cpa-http/run @@ -0,0 +1,62 @@ +#!/opt/pwn.college/python + +from base64 import b64encode, b64decode +from Crypto.Cipher import AES +from Crypto.Util.Padding import pad +from Crypto.Random import get_random_bytes + +import tempfile +import sqlite3 +import random +import flask +import os + +app = flask.Flask(__name__) + +class TemporaryDB: + def __init__(self): + self.db_file = tempfile.NamedTemporaryFile("x", suffix=".db") + + def execute(self, sql, parameters=()): + connection = sqlite3.connect(self.db_file.name) + connection.row_factory = sqlite3.Row + cursor = connection.cursor() + result = cursor.execute(sql, parameters) + connection.commit() + return result + +key = get_random_bytes(16) +cipher = AES.new(key=key, mode=AES.MODE_ECB) + +db = TemporaryDB() +# https://www.sqlite.org/lang_createtable.html +db.execute("""CREATE TABLE secrets AS SELECT ? AS flag""", [open("/flag").read()]) + +@app.route("/", methods=["GET"]) +def challenge_get(): + query = flask.request.args.get("query") or "'A'" + + try: + sql = f'SELECT {query} FROM secrets' + print(f"DEBUG: {sql=}") + pt = db.execute(sql).fetchone()[0] + except sqlite3.Error as e: + flask.abort(500, f"Query: {query}\nError: {e}") + except TypeError: + # no records found + pt = "A" + + ct = cipher.encrypt(pad(pt.encode(), cipher.block_size)) + + return f""" + Welcome to pwn.secret! +
Query:
+
+ Query:
{sql}

+ Results:
{b64encode(ct).decode()}
+ + """ + +app.secret_key = os.urandom(8) +app.config['SERVER_NAME'] = f"challenge.localhost:80" +app.run("challenge.localhost", 80) diff --git a/cryptography/module.yml b/cryptography/module.yml index 1b8af49d..4082502b 100644 --- a/cryptography/module.yml +++ b/cryptography/module.yml @@ -19,6 +19,8 @@ challenges: name: AES - id: cpa name: Chosen-plaintext Attack +- id: cpa-http + name: CPA-over-HTTP - id: level-5 name: level5 - id: level-6