1️⃣ MySQL

MySQL의 Database, INFORMATION_SCHEMA를 사용하여 데이터베이스에 접근하는 방법에 대해 설명합니다.

📜Database

Database: 필요한 데이터를 유기적으로 결합하여 저장한 집합체: 통합된 정보들을 저장하여 운영할 수 있는 공용 데이터들의 묶음 데이터베이스는(Database) 여러 사람이 공유하여 사용할 목적으로 통합, 관리하는 데이터의 집합입니다. 새로운 환경에서도 기존의 데이터를 효율적으로 사용할 수 있도록 데이터를 구조화하여 저장한 것입니다.

📜MySQL

SQL은 Structured Query Language의 약자입니다. SQL은 데이터베이스에서 데이터를 정의, 조작, 제어하기 위해 사용하는 언어입니다. 그 중에서도 이 포스트는 MySQL 8.0에 대해 설명합니다.

MySQL은 Oracle과 더불어 가장 널리 사용되고 있는 데이터베이스 관리 시스템입니다. 다른 프로그래밍언어가 프로그램을 제작하기 위한 것이라고 한다면 SQL은 데이터베이스에 접근하기 위한 것이라고 할 수 있습니다.

MySQL의 구조는 다음과 같이 간단히 나타낼 수 있습니다.

Database Server ⊃ Database ⊃ Table(Field) ⊃ Column ⊃ Record

데이터베이스 서버 안에는 데이터베이스들이 있고, 데이터 베이스 안에는 테이블들이 있습니다. 그리고 테이블들은 칼럼(열)마다 레코드를 보관하고 있습니다.

MySQL을 이용해서 Database에 접근하는 법은 다음과 같습니다.

SELECT * FROM TERADA_TABLE;

위와 같은 코드(Code)를 Query, 쿼리문이라고 합니다. 사용자는 MySQL의 문법에 따라 Query를 작성하고, 이를 통해 데이터의 입출력, 조작, 조회 등을 할 수 있습니다. MySQL의 다양한 문법은 이곳에서 찾아 볼 수 있습니다.

📜INFORMATION_SCHEMA

데이터베이스의 양이 방대해지고, 그 데이터들을 효율적으로 관리하기위해서 메타데이터(Metadata)라는 것이 존재합니다. 메타데이터는 쉽게 말하자면 데이터의 데이터, 정보들에 관한 정보입니다.

MySQL은 INFORMATION_SCHEMA라는 이름의 데이터베이스에 메타데이터를 저장하고 있습니다. 이 INFORMATION_SCHEMA에는 데이터베이스, 테이블, 컬럼(column)의 이름, 컬럼의 데이터 타입, 접근 권한 등 아주 민감하고 중요한 정보가 들어있습니다.

이하부터는 INFORMATION_SCHEMA에 접근하여 그 정보들을 열람하는 방법에 대해 설명합니다.

예제는 다음과 같은 Database에서 진행합니다.

Database Server
└ information_schema
└ performance_schema
└ sys
└ mysql
└ COUNTRIES
    └ KOREA
    -------------------------------------
    | CITY_NAME | TAG       | IS_VISIT |
    | --------- | --------- | -------- |
    | SEOUL     | CAPITAL   | 1        |
    | JEJU      | MANDARINE | 1        |
    | BUSAN     | SEAGULL   | 0        |
    -------------------------------------
    └ JAPAN
    -------------------------------------
    | CITY_NAME | VILLAGE | IS_VISIT |
    | --------- | ------- | -------- |
    | TOKYO     | SIBUYA  | 1        |
    | OSAKA     | NANBA   | 0        |
    | FUKUOKA   | HAKATA  | 1        |
    -------------------------------------
    └ USA
    ----------------------------------------
    | STATE_NAME  | BASEBALL | IS_VISIT |
    | ----------- | -------- | -------- |
    | ILLINOIS    | CUPS     | 1        |
    | NEW YORK    | METS     | 0        |
    | LOS ANGELES | DODGERS  | 1        |

Note : COUNTRIES 는 데이터베이스의 이름입니다. 이외에는 시스템 데이터베이스입니다.

1. 데이터베이스 조회

데이터베이스 서버 내의 데이터베이스의 이름을 조회할 수 있습니다.

> SELECT SCHEMA_NAME 
  FROM INFORMATION_SCHEMA.SCHEMATA;
> ------------------------------
    |   SCHEMA_NAME          |
    |   -------------------- | 
    |   INFORMATION_SCHEMA   |
    |   PERFORMANCE_SCHEMA   |
    |   MYSQL                | 
    |   SYS                  |
    |   COUNTRIES            |
  ------------------------------

Note:SHOW DATABASE;또한 위와 같은 결과를 보입니다.

Note:INFORMATION_SCHEMA.SCHEMATA에는 데이터베이스이름(SCHEMA_NAME)이외의 칼럼도 있습니다.

2. 테이블 조회

데이터베이스명을 알아내었다면 데이터베이스 내의 테이블의 정보 또한 획득할 수 있습니다.

> SELECT TABLE_NAME 
  FROM INFORMATION_SCHEMA.TABLES 
  WHERE TABLE_SCHEMA="COUNTIRES";
> ----------------------
    |   TABLE_NAME   |
    |   ----------   | 
    |   KOREA        |
    |   JAPAN        |
    |   USA          | 
  ----------------------

Note: INFORMATION_SCHEMA.TABLE에서 TABLE_SCHEMA는 해당 테이블이 속한 DB를 가리킵니다.

다음과 같이 출력 결과를 필터링할 수도 있습니다.

> SELECT TABLE_NAME 
  FROM INFORMATION_SCHEMA.TABLES 
  WHERE TABLE_SCHEMA="COUNTIRES" 
  LIMIT 0,1;
> ---------------------
    |   TABLE_NAME   |
    |   ----------   | 
    |   KOREA        |
  ---------------------
 
> SELECT MAX(TABLE_NAME) 
  FROM INFORMATION_SCHEMA.TABLES 
  WHERE TABLE_SCHEMA="COUNTIRES";
> ---------------------
    |   TABLE_NAME   |
    |   ----------   | 
    |   USA          |
  ---------------------

Note: 실제로 위와같은 방법이 Blind SQL Injection에서 사용됩니다.

위와 같은 방법을 통해 USE COUNTRIES;SHOW TABLES;을 사용하지 않고 데이터베이스 내의 테이블을 조회할 수 있습니다. INFORMATION_SCHEMA.TALBES 에는 테이블명(TABLE_NAME) 뿐만 아니라 테이블의 행 수(TABLE_ROWS) 같은 정보도 포함되어있습니다.

3. 컬럼 조회

테이블에 접근했다면 이제 테이블 속에 어떤 컬럼들이 있는지 확인할 수 있습니다. 이번엔 조금 다른 방식으로 데이터베이스를 특정해보겠습니다.

> SELECT COLUMN_NAME 
  FROM  INFORMATION_SCHEMA.COLUMNS 
  WHERE TABLE_SCHEMA!="INFORMATION_SCHEMA" 
  AND TABLE_SCHEMA!="PERFORMANCE_SCHEMA" 
  AND TABLE_SCHEMA!="MYSQL" 
  AND TABLE_SCHEMA!="SYS";
> ----------------------
    |   COLUMN_NAME   |
    |   ----------    | 
    |   CITY_NAME     |
    |   STATE_NAME    |
    |   TAG           |
    |   VILLAGE       |
    |   BASEBALL      |
    |   IS_VISIT      |
  ----------------------

메타데이터 데이터베이스 이외의 데이터베이스를 선택함으로서 사용중인 데이터베이스를 특정하였고, INFORMATION_SCHEMA.COLUMNS가 가지고 있는 정보 중 컬럼명(COLUMN_NAME)만을 획득하였습니다. 하지만 이것은 데이터베이스 내의 모든 컬럼명을 가져오는 것으로 테이블마다 컬럼명이 다르다면 어떤 컬럼이 어떤 테이블에 속해 있는지 알 수 없을 것입니다. 따라서 특정한 테이블의 컬럼명을 가져오기 위해서 다음과 같은 Query를 작성할 수 있습니다.

> SELECT COLUMN_NAME 
  FROM INFORMATION_SCHEMA.COLUMNS 
  WHERE TABLE_NAME="JAPAN";
> ----------------------
    |   COLUMN_NAME   |
    |   ----------    | 
    |   CITY_NAME     |
    |   VILLAGE       |
    |   IS_VISIT      |
  ----------------------

4. 레코드 조회

데이터베이스명, 테이블명, 컬럼명을 파악했다면 이제 어떤 레코드에도 접근할 수 있습니다. 위에서 조회한 정보를 바탕으로 다음과 같이 Query를 작성해 볼 수 있습니다.

> SELECT CITY_NAME, VILLAGE
  FROM JAPAN;
> ---------------------------
    | CITY_NAME | VILLAGE |
    | --------- | ------- |
    | TOKYO     | SIBUYA  |
    | OSAKA     | NANBA   |
    | FUKUOKA   | HAKATA  |
  ----------------------------
> SELECT VILLAGE 
  FROM JAPAN 
  WHERE VILLAGE 
  IN ('SHINJUKU','SIBUYA','OMOTESANDO','HANEDA');
> ------------------
    |   VILLAGE   |
    |   --------  | 
    |   SIBUYA    |
  ------------------

위의 내용들을 바탕으로 다양한 SubQuery와 함께 INFORMATION_SCHEMA의 데이터를 자유롭게 열람할 수 있습니다.