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('admin', 'DH{**FLAG**}');
INSERT INTO user(uid, upw) values('guest', 'guest');
INSERT INTO user(uid, upw) values('test', 'test');
FLUSH PRIVILEGES;
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/>
<form>
    <input tyupe='text' name='uid' placeholder='uid'>
    <input type='submit' value='submit'>
</form>
'''

@app.route('/', methods=['POST', 'GET'])
def index():
    uid = request.args.get('uid')
    if uid:
        try:
            cur = mysql.connection.cursor()
            cur.execute(f"SELECT * FROM user WHERE uid='{uid}';")
            return template.format(uid=uid)
        except Exception as e:
            return str(e)
    else:
        return template

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

이 문제는 말 그대로 오류 기반 sql injection 문제다.

들어가기 전에, error based sql injection에 대해 정리하고 들어가도록 하자.

error based sql injection

<aside> 💡 데이터베이스 오류 메시지를 활용하여 데이터베이스에 대한 정보를 획득하는 SQL Injection 기법

</aside>

→ 주로 데이터베이스에 대한 정보를 획득하기 위해 사용되는 공격 기법이다. SQL의 잘못된 문법이나 자료형 불일치 등에 의해 데이터베이스가 알려주는 데이터베이스 오류 메시지에 의존하여 수행된다. 따라서 웹 애플리케이션에서 데이터베이스 오류를 표시해주는 경우에 주로 사용할 수 있다. 공격자는 SQL 쿼리의 잘못된 문법을 사용해 고의적으로 오류를 유발시키고, 해당 오류 정보를 바탕으로 데이터베이스명, 테이블, 컬럼 정보 등의 데이터베이스 정보와 구조를 알아내어 개인 정보와 같은 민감한 데이터를 획득할 수 있다.

Untitled

공격 기법

해당 문제는 mysql 기반으로 작성되었으므로, mysql을 기반으로 공격 기법을 작성하도록 하겠다.

여기서, XPath 방식을 활용해서 문제를 풀어볼 예정이다.

XPath

XPath 방법은 extractvalue() 함수를 활용하는 기법으로 MySQL 기준 5.1 이상의 버전에서만 유효하다.