본문 바로가기
정보보안/모의해킹

모의해킹 강의(SQL Injection Part1) 7 - 메타데이터 (주기적으로 복습)

by IT매니절 2024. 10. 22.

모의해킹 실무자가 알려주는, SQL Injection 공격 기법과 시큐어 코딩 : PART 1

강의주소 :  https://www.inflearn.com/course/sql-injection-secure-coding-1/dashboard

 

메타 데이터
데이터에 대한 데이터. 자료의 속성 등을 설명하는 데이터.
ex) 테이블명, 인코딩 설정, 권한 정보, 컬럼 데이터 타입, 길이 등등.

메타 데이터가 필요한 이유
메타 데이터를 모르면 injection이 불가능하기 때문
간단한 select 절만 살펴봐도, 컬럼명과 테이블명이 있어야 조회할 수 있다

 

메타 데이터 목록화를 진행할 때 데이터 사전(DD)을 조회하게 된다

공격 관점에서 메타 데이터 접근법
순차적 : 데이터베이스 목록화 > 테이블 목록화 > 컬럼 목록화
비순차적 : 원하는 개체 탐색 > 대상 개체 정보 목록화

 

순차적 접근은 중요 정보를 놓칠 확률이 낮지만, 많은 시간과 트래픽이 필요
비순차적 접근은 비교적 적은 시간과 트래픽 필요, 다만 중요 정보를 놓칠 수 있음

 

dbms별 데이터사전
MYSQL
information_schema.schemata
information_schema.tables
information_schema.columns

MSSQL
sysdatabases, sysobjects, syscolumns
(2005 이상) sys.databases, sys.oajects, sys.columns
information_schema.schemata
information_schema.tables
information_schema.columns

(속도는 sys~ 가 더 빠른편)

ORACLE
all_tables, all_tab_columns

 

 

 

MYSQL 실습

select * from information_schema.schemata

select SCHEMA_NAME from information_schema.schemata

 

조회하면, 이것이 바로 데이터베이스 목록화

select * from information_schema.tables

 

데이터를 조회하면 TABLE_SCHEMA가 데이터베이스명이라는 것을 알 수 있다

이 때 schemata에서는 SCHEMA_NAME이라는 이름이었다는 것을 혼동하지 말아야 한다 (같은 값을 가지지만 다른 이름의 컬럼)

select TABLE_NAME from information_schema.tables where TABLE_SCHEMA = 'BOARD'

board에 대한 테이블 목록화

 

select COLUMN_NAME from information_schema.columns where TABLE_name = 'members'

members에 대한 컬럼 목록화 (아무래도 중요정보를 탈취하려는 목적이니까)

 

컬럼을 토대로 데이터까지 목록화를 완성

 

 

목적성에 따라

테이블: mem, user, file, session, employee, amdin 등

컬럼: id, pw, pass, jumin, ssn, admin, card ... 등 의 키워드로 목록화를 진행

ex)

테이블

select TABLE_NAME from information_schema.tables where TABLE_SCHEMA = 'board' and TABLE_name like '%mem%'

 

컬럼

select TABLE_NAME, COLUMN_NAME from information_schema.columns where TABLE_SCHEMA = 'board' and COLUMN_NAME like '%id%'

=> 해당 결과를 토대로

select column_name from information_schema.columns where TABLE_SCHEMA ='board' and TABLE_NAME = 'members'

=> columns 목록화

 

 

 

MSSQL 실습

select * from master.sys.databases

(2005 미만 : select * from master..sysdatabases 지금도 사용은 가능함)

db_name() 함수에 인자값으로 database_id를 넣어 조회가능

uinion 공격이나 blind 공격에 사용 가능 

 

MYSQL의 경우 information_schema.tables 안에 모든 데이터베이스의 테이블이 존재했는데
MSSQL같은 경우 각 데이터베이스 내에 시스템 뷰가 존재함
때문에 현재 데이터베이스 외의 다른 데이터베이스에 접근하려면 이름을 알아야 한다
(select * from sys.objects 이렇게 앞에 board를 빼버리면 현재 데이터베이스 기준으로 조회함)

 

select * from board.sys.objects where type_desc = 'USER_TABLE' (또는 type='U')

시스템이 만든 테이블 말고 사용자 테이블만 조회

 

( U : 사용자 테이블
S : 시스템 테이블
P : 저장 프로시저
X : 확장 프로시저
IT : 내부 테이블
ET : 외부 테이블
V : 뷰 )

 

select * from board.sys.columns

무작정 조회해보면 아 이게 뭐지 싶음

 

이 때 중요한 것이 맨 앞의 object_id 값이다

select * from board.sys.columns where object_id='1221579390';

members 테이블의 object_id를 셋팅해 조회하면 컬럼들이 목록화된다.

 

그런데 이런 방식으로 진행하면 odbject id 값과 name을 둘 다 알아야 해서 시간이 더 오래 걸린다
이 때는 서브쿼리를 이용하거나

select * from board.sys.columns where object_id=(select object_id from board.sys.tables where name='members');

 

select * from board.sys.columns where object_id=object_id('members');

object_id 함수를 이용한다

 

그런데 이 때 object_id는 기본적으로 현재 데이터베이스를 기준으로 검색한다

DBeaver UI 중에 보면 데이터베이스를 선택할 수 있다

master 데이터베이스인 상태에서 조회하려면 board..members 처럼 앞에 데이터베이스명과 .. 을 붙여서 조회하여야 한다

 

select name, type_name(system_type_id) from board.sys.columns where object_id=object_id('members');

컬럼 타입을 알고 싶다면 type_name함수를 이용하여 system_type_id를 셋팅해준다

 

select id, idx, password, jumin from board..members;

마지막 데이터목록화

 

select name from sys.objects where type='U' and name like '%mem%';

=> mem을 기준으로 검색해보면 members 테이블이 나온다

select name from sys.columns where object_id=object_id('board..members')

=> id, idx, password, jumin 컬럼을 얻었다.

 

 

컬럼을 먼저 탐색하고 테이블을 탐색하는 경우

 

mssql은 각 데이터베이스별로 조회가 되기 때문에
비순차적 접근을 할 때도 데이터베이스 목록화는 해야 한다 (이름을 알아야 하니까)

 

select name, object_name(object_id) as 'table_name' from sys.columns where object_id in (select object_id from sys.objects where type='U');

=> object_name을 통해 테이블명까지 같이 붙여준다. 서브쿼리를 통해 in으로 사용자테이블에 속하는 컬럼만 리스트업했다.

 

이 때, object_name의 경우도 다른 데이터베이스를 조회하려면 db_id값이 필요하다

select name, object_name(object_id, db_id('board')) as 'table_name' from sys.columns where object_id in (select object_id from sys.objects where type='U');

=> db_id 함수에 원하는 데이터베이스명을 넣어서 db_id값을 object_name의 두 번째 인자값으로 셋팅해주면 된다

 

+ join 구문을 통해 조회할 때

select a.name, b.name from sys.objects a, sys.columns b where a.object_id = b.object_id and a.type='U' and b.name like '%id%';

 

 

 

 

ORACLE 데이터베이스 목록화

 

DBA_ : 데이터베이스의 모든 테이블, 컬럼 정보 (DBA 권한)
ALL_ : 현재 사용자가 접근 가능한 모든 테이블, 컬럼 정보
USER_ : 현재 사용자가 생성, 소유하는 모든 테이블, 컬럼 정보

 

SELECT * FROM all_tables;

 

SELECT DISTINCT owner FROM all_tables;

현재 접속한 사용자 권한으로 접근 가능한 테이블들

 

SELECT USER FROM dual; 로 현재 사용자명을 알 수 있다.
SELECT * FROM all_tables WHERE owner='C##TESTER'
이렇게 조회하면 해당 사용자가 만든 테이블만 조회된다

SELECT * FROM all_tab_columns WHERE owner='C##TESTER' AND TABLE_NAME='MEMBERS';
컬럼 목록화

SELECT id, password, jumin FROM C##TESTER.MEMBERS;
데이터 목록화

SELECT * FROM all_tables WHERE owner='C##TESTER' and table_name like '%id%'


비순차적 접근
테이블
SELECT * FROM all_tables WHERE owner='C##TESTER' and table_name like '%MEM%';
사용자는 있어도 되고 없어도 되고
컬럼
SELECT * FROM all_tab_columns WHERE owner='C##TESTER' AND column_name like '%ID%';