김승현

[Dreamhack : Web] error based sql injection 본문

Web/Dreamhack : Web

[Dreamhack : Web] error based sql injection

kshind 2023. 2. 24. 13:57

문제

 

간단한 error based sqli라고 한다. 풀어보자

 

 

풀이

userid쪽의 sql 쿼리문과 uid를 입력하는 창이 있다. guest를 한번 입력해보자.

그냥 저 위에 출력만 바뀌나? 아무거나 입력해보자

아무거나 입력해봤는데 입력이 됐고 이번에는 '--도 입력해보자

error문이 발생했고 mariaDB를 사용하는 것 같다. 소스코드로 가보자.

 

<코드 전체>

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

 

코드 초반부

os, flask, MYSQL을 import 하고 app = ... 를 통해서 플라스크 객체를 생성한다.

app.config로 시작하는 코드들은 모두 flask와 mysql을 연동시키는 코드들이다.

 

template 변수에 우리가 접속해서 봤던 모든 값들을 html 형식으로 저장해둔 것 같다.

 

@app.route('/', methods=['POST', 'GET']) == host3.dreamhack.games:[port]/

uid 변수에 전달받은 uid를 저장

 

만약 uid가 있다면 아래를 실행,

    cur 변수에 sql문을 실행할 수 있게 함  # cursor : 독립적으로 SQL 문을 실행할 수 있는 작업환경을 제공하는 객체

    cur로 SELECT * FROM user WHERE uid = '[uid 변수]';를 실행

    uid에 uid변수값을 넣어서 template을 반환함

   

    만약 위의 세 줄을 실행 중에 에러가 발생하면 해당 에러문 출력

 

코드 마지막 부분

 

이번엔 다운로드 파일 중 sql text 파일을 보도록 하자.

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라는 db가 없다면 users라는 db를 생성

users db의 모든 테이블에 대해 접근하는 dbuser가 로컬에서 접속가능하게 함 비밀번호는 dbpass

 

users 데이터베이스 접속

user 테이블 생성

    값이 추가될 때마다 자동으로 숫자가 증가하는 정수 타입의 idx 선언

    uid는 null이 아닌 char형 변수

    uqw도 null이 아닌 char형 변수

 

uid가 admin이고 upw가 DH{**FLAG**}인 데이터 추가

uid가 guest이고 upw가 guest인 데이터 추가

uid가 test이고 upw가 test인 데이터 추가

변경사항 저장

 

이런 느낌이다!

 

error based sqli 강의를 보면

SELECT extractvalue(1,concat(0x3a,(SELECT password FROM users WHERE username='admin')));

이런 코드가 있었는데 이걸

여기에 맞게 입력해야 된다.

강의의 코드를 조금 고쳐서 입력해보자.

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

위의 코드를 입력하면 에러랑 FLAG가 뜨지만 ...이 붙은 걸 봐선 flag처럼 사용할 수 있을 것 같다.. 

뒷내용을 봐야 되는데 어떤 걸 쓸까 생각하다가 강의에서 나온 substr이 떠올랐다.

substr(str, n1, n2)

str 문자열의 첫 자리를 1로 시작해서 n1자리부터 n2만큼의 문자들을 가져오게 사용할 수 있다. 이걸 활용하자.

DH{부터 951까지 총 28자리기 때문에 substr(upw, 29, 20) 29번째 숫자부터 적당한 숫자를 입력해서 값을 

끝까지 출력하게 해서 입력하면 된다(20은 임의로 입력한 값)

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

이렇게 코드를 짰고 입력해보면

둘을 이어붙이면 flag가 완성된다!

 

DH{c3968c78840750168774ad951fc98bf788563c4d}

'Web > Dreamhack : Web' 카테고리의 다른 글

[Dreamhack : Web] sql injection bypass WAF  (0) 2023.02.24
[Dreamhack : Web] blind sql injection advanced  (0) 2023.02.24
[Dreamhack : Web] blind-command  (0) 2023.02.23
[Dreamhack : Web] Carve party  (0) 2023.02.23
[Dreamhack : Web] web-ssrf  (0) 2023.02.23