본문 바로가기

드림핵

드림핵 error based sql injection

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

 

 

문제는 이와 같다.

 

문제 파일을 다운 받고 열어봤다.


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

코드는 Flask 웹 애플리케이션을 만들어 MySQL 데이터베이스에서 사용자 정보를 조회한다.

사용자가 입력한 uid에 대해 SQL 쿼리를 실행하고 결과를 HTML로 보여준다.

 

 

 

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;

 

  • 이터베이스 생성: users라는 데이터베이스를 생성
  • 사용자 권한 부여: dbuser라는 사용자에게 users 데이터베이스에 대한 모든 권한을 부여
  • 데이터베이스 선택: users 데이터베이스를 사용한다.
  • 테이블 생성: user라는 테이블을 생성하며, 사용자 ID와 비밀번호를 저장한다.
  • 데이터 삽입: admin, guest, test 사용자의 ID와 비밀번호를 테이블에 추가한다.
  • 권한 반영: 변경된 권한을 즉시 반영한다.

 

나는 admin의 비밀번호를 찾아야 하는 것이다.

 

문제에 들어와서 SQL injection문을 넣어봤다.

 

 

1' and extractvalue(concat(0x0a,(select database())));--

내가 넣은 코드는 이와 같다. 현재 선택된 데이터베이스의 이름을 추출하는 코드이다.

 

1': SQL 쿼리에 주입된 문자열의 시작을 나타내며, 기존 쿼리를 종료시키고 새로운 조건을 추가

and: 조건을 추가하여 쿼리의 실행 지속한다.

extractvalue(0x0a, ...): XML 데이터를 추출하는 MySQL 함수 

concat(0x0a, concat(0x0a, (select database())))

- concat 함수는 여러 문자열을 연결하는 함수이다.

- 첫 번째 concat은 두 줄 바꿈 문자를 추가한다.

- 두 번째 concat은 현재 사용 중인 데이터베이스의 이름을 반환한다.

(select database()): 현재 선택된 데이터베이스의 이름을 반환하는 서브쿼리이다.

--: SQL에서 주석을 시작하는 기호로 그 뒤의 내용을 무시하게 한다.

 

 

 

 

데이터베이스 이름이 users임을 알 수 있다.

 

 

 

 

1' and extractvalue(0x3a,concat(0x3a,(SELECT upw FROM user LIMIT 0,1)));--

 

and: 새로운 조건을 추가하여 쿼리의 실행을 계속하도록 한다.

concat(0x3a, (SELECT upw FROM user LIMIT 0,1))

0x3a(콜론 문자)와 서브쿼리에서 가져온 결과를 연결한다.

(SELECT upw FROM user LIMIT 0,1): user 테이블에서 첫 번째 사용자(인덱스 0)의 비밀번호(upw)를 선택하는 서브쿼리

 

 

 

플래그값이 너무 길어서 잘린다. 

 

 

 

1' and extractvalue(0x3a,concat(0x3a,(SELECT substr(upw,20,25) FROM user LIMIT 0,1)));--

20-25번째 문자를 출력하게 했다.

 

뒷부분을 출력해서 합쳤다.

 

 

 

 

 

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

weblog-1  (1) 2024.10.30
sql injection bypass WAF  (0) 2024.10.30
드림핵 blind sql injection advanced  (2) 2024.10.02
easy-login  (0) 2024.05.22
web-misconf-1  (0) 2024.05.22