본문 바로가기
드림핵

[드림핵] baby-sqlite 풀이

by jwcs 2024. 1. 10.
728x90

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

 

baby-sqlite

로그인 서비스입니다. SQL INJECTION 취약점을 통해 플래그를 획득하세요! 해당 문제는 숙련된 웹해커를 위한 문제입니다.

dreamhack.io

 

sqlite에서 일어날 수 있는 sqli 문제이다.

 

/
/login

특별할 것 없어보인다. 바로 코드를 확인해보자.

 

#!/usr/bin/env python3
from flask import Flask, request, render_template, make_response, redirect, url_for, session, g
import urllib
import os
import sqlite3

app = Flask(__name__)
app.secret_key = os.urandom(32)
from flask import _app_ctx_stack

DATABASE = 'users.db'

def get_db():
    top = _app_ctx_stack.top
    if not hasattr(top, 'sqlite_db'):
        top.sqlite_db = sqlite3.connect(DATABASE)
    return top.sqlite_db


try:
    FLAG = open('./flag.txt', 'r').read()
except:
    FLAG = '[**FLAG**]'


@app.route('/')
def index():
    return render_template('index.html')


@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'GET':
        return render_template('login.html')

    uid = request.form.get('uid', '').lower()
    upw = request.form.get('upw', '').lower()
    level = request.form.get('level', '9').lower()

    sqli_filter = ['[', ']', ',', 'admin', 'select', '\'', '"', '\t', '\n', '\r', '\x08', '\x09', '\x00', '\x0b', '\x0d', ' ']
    for x in sqli_filter:
        if uid.find(x) != -1:
            return 'No Hack!'
        if upw.find(x) != -1:
            return 'No Hack!'
        if level.find(x) != -1:
            return 'No Hack!'

    
    with app.app_context():
        conn = get_db()
        query = f"SELECT uid FROM users WHERE uid='{uid}' and upw='{upw}' and level={level};"
        try:
            req = conn.execute(query)
            result = req.fetchone()

            if result is not None:
                uid = result[0]
                if uid == 'admin':
                    return FLAG
        except:
            return 'Error!'
    return 'Good!'


@app.teardown_appcontext
def close_connection(exception):
    top = _app_ctx_stack.top
    if hasattr(top, 'sqlite_db'):
        top.sqlite_db.close()


if __name__ == '__main__':
    os.system('rm -rf %s' % DATABASE)
    with app.app_context():
        conn = get_db()
        conn.execute('CREATE TABLE users (uid text, upw text, level integer);')
        conn.execute("INSERT INTO users VALUES ('dream','cometrue', 9);")
        conn.commit()

    app.run(host='0.0.0.0', port=8001)

전체 코드이다.

 

어떻게 flag를 구할 것인지 먼저 구상해보자.

 

    with app.app_context():
        conn = get_db()
        query = f"SELECT uid FROM users WHERE uid='{uid}' and upw='{upw}' and level={level};"
        try:
            req = conn.execute(query)
            result = req.fetchone()

            if result is not None:
                uid = result[0]
                if uid == 'admin':
                    return FLAG
        except:
            return 'Error!'
    return 'Good!'

검색 결과 첫 번째에 admin이 있으면 FLAG를 return 해준다. 근데 전체 코드에서 살펴볼 수 있듯이 admin은 레코드에 존재하지 않는다. 따라서 `select 'admin'` 과 같은 방식으로 출력해야한다.

 

sqli_filter = ['[', ']', ',', 'admin', 'select', '\'', '"', '\t', '\n', '\r', '\x08', '\x09', '\x00', '\x0b', '\x0d', ' ']

가장 먼저 떠오른 것이 union select를 사용하는 방법이었다. 그런데 select가 필터링되어 있다. 이를 어떻게 우회해야 할까?

 

select 필터링 우회 방법 (출처: https://learn.dreamhack.io/309#16)

https://www.sqlite.org/lang_select.html

 

SELECT

The SELECT statement is used to query the database. The result of a SELECT is zero or more rows of data where each row has a fixed number of columns. A SELECT statement does not make any changes to the database. The "select-stmt" syntax diagram above attem

www.sqlite.org

공식 문서에서도 이와 같은 내용을 찾아볼 수 있다. select-core 부분을 잘 살펴보면된다.

 

문자열 필터링 우회 (출처: https://learn.dreamhack.io/309#15)

admin 문자열이 필터링 되어있는 것은 이와 같이 우회가 가능하다.

 

이를 종합하여 버프스위트로 값을 전달해보겠다.

level 값 추가

level = request.form.get('level', '9').lower()

원래는 이렇게 서버에서 level의 기본값을 정해놨기 때문에 버프스위트로 잡았을 때 level 파라미터가 없을 것이다. 따라서 level 파라미터를 따로 만들어서 보내야 한다.

 

짜잔

 

방어 방법

 

입력값 검증이 충분히 이루어지지 않았다. sqli는 prepared statements를 통해 방어할 수 있다.

728x90
반응형

'드림핵' 카테고리의 다른 글

[드림핵] Dream Gallery 풀이  (0) 2024.01.22
[드림핵] login-1 풀이  (1) 2024.01.13
[드림핵] out of money 풀이  (0) 2024.01.10
[드림핵][wargame.kr] type confusion 풀이  (2) 2024.01.10
[드림핵] web-misconf-1 풀이  (0) 2024.01.08