UNION SQL INJECTION PROCESS

DATE : 2023/11/30

UNION SQL INJECTION을 위한 재료가 모두 갖추어 졌다!!

이제우리의 목표였던 사용자 계정 정보 추출을 위해 SQL injection을 실행해볼 것이다.

다만 문제가 있다면,

(1) 사용자 계정 정보가 어떤 table에 들어있는 지 모른다.

(2) 그 table이 어느 DB에 들어있는 지도 모른다..

(3) table을 찾는다 한들, 어떤 column이 있는 지 모른다...

(4) 화면에 출력 되는 데이터가 어떤column의 값인지 모른다....!

(5) column의 총 개수도 모른다...!!

(6) SQL injection 취약점이 있는 지도 모른다!!! 🙀

즉 아는 게 없다!!! 총체적 난국이다.

그렇기 때문에 사실, 공격을 수행하기 위해서는 기본적으로 정보 수집이 필수이다.

따라서 우리에게 필요한 정보를 얻어가면서

SQL Injection에 성공할 수 있는 프로세스를 따라가 보도록 하자!

[ UNION SQL INJECTION PROCESS ]

[1] SQL injection POINT를 찾아내라!

SQL injection을 수행하기 위해서는 당연히, 이 공격을 수행할 수 있을지 확인해 봐야 한다.

게임 검색 기능을 제공하는 사이트에서 "over "라고 입력했더니 overwatch 라는 게임이

결과로 나온 걸 볼 수 있다.

우리는 이 사이트에 SQL injection을 수행할 수 있는 지가 궁금하기 때문에

over' and '1'='1

이라는 Query를 넣어볼 것이다.

그전에 잠깐! 확인할 부분이 있다면 지금 "over"를 입력했는데 "overwatch"가 결과로 나왔기 때문에

like %%가 사용된 가능성이 있음을 예측해볼 수 있다.

(watch, over, overw도 입력해봤다. 결과는 모두 동일!)

Query를 확인해봤더니 예상한 대로 like %__% 형태의 구문이 사용되고 있었다.

그렇다는 건

over' and '1'='1

을 입력하면 이 값이 %% 사이로 들어가기 때문에

'%___%'

맨 앞과 뒤에 따옴표와 % 기호가 있는 걸 감안해야 한다.

over%' and '1%'='1

따라서 ___에 입력한 값이 들어갔을 때, and '1'='1 과 같은 기능을 수행하도록 만들기 위해서는

이와 같이 값을 입력해야 함을 알 수 있다.

Query를 넣고 결과를 확인해보면!

아무런 이상 없이 "over"를 입력했을 때와 동일한 결과가 나온 걸 볼 수 있다!! 👏

이 말은 즉, Query를 넣었음에도 불구하고 정상적으로 결과를 얻을 수 있다는 뜻이기 때문에

SQL injection을 실행할 수 있다는 의미가 된다.


[2] column 개수 파악하기

SQL injection의 가능성을 확인했으니 이젠 본격적으로 우리가 원하는 table에 접근해 나갈 것이다.

그러기 위해서 union 연산자를 사용할 것이고,

union을 사용하기 위해 column 개수부터 파악할 필요가 있다.

UNION & ORDER BY에서 알아본 내용을 여기서 활용해보자 😏

over%' order by 1 #

맨 뒤에 남는 %' 를 제거하기 위해서 주석을 포함한 Query를 작성해보았다.

order by 1부터 실행해보면 결과가 아주 잘 나온다!

order by 2도 해보고, 3, 4.. 해보던 와중에!

over%' order by 5 #

order by 5를 딱 입력하는 순간..!

에러가 발생했다. 이는 곧 column의 개수가 4개임을 의미한다.

[3] 출력 되는 column의 위치 알아내기

column의 개수를 알아냈으니 몇 번째 column이 어느 위치에 출력 되고 있는 지 확인해보자.

over' UNION SELECT 1,2,3,4 #

이번에 사용할 Query는 위와 같다. 총 column의 개수가 4개 라는 건

UNION 앞 작성된 SELECT 문의 결과가 총 4개의 COLUMN을 포함한다는 뜻이다.

따라서 총 4개의 숫자를 달리해서 union으로 결과를 합쳐주면

화면과 같이 4개의 숫자 중 보이지 않는 숫자가 어떤 것인지 알 수 있기 때문에 ( 위에서는 1 )

해당 숫자를 넣은 위치의 column이 출력 되지 않는다는 점과( 위에서는 첫 번째 column )

출력된 column의 순번을 알 수 있다. (name = 2번째, score = 3번째, production = 4번째)

[4] DB name 알아내기

[1] ~ [3]번 과정을 통해 현재 WAS에 작성되어 있는 Query는 4개의 column을 꺼내온다는 점과

그 중 첫 번째 column은 화면에 나타나지 않는다는 점을 알아냈다.

이제는 첫 번째 column을 제외하고 화면 상에 데이터를 출력하는 2,3,4번째 column 중 하나를 골라서

알아내야 하는 DB, Table, column 정보를 하나씩 추출해볼 것이다.

그 중에서도 제일 먼저 알아내야 하는 정보는 바로 DB!

어떤 DB가 존재하는 지 알아야 그 안에 들어있는 Table 정보를 얻을 수 있다.

DB 이름을 알아내기 위해 사용할 수 있는 Query는 다음과 같다.

select databaes()

문제는 이 Query를 UNION으로 어떻게 연결해줄 것이냐는 점이다. 생각보다 그리 어렵지 않다!

우선, [3]에서 알아낸 바와 같이 첫 번째 column 값은 화면에 출력 되지 않기 때문에 제외해야 한다.

그럼 2,3,4번째 column 중에 아무 곳에나 database()를 넣어주면 끝!

over%' UNION SELECT 1, 2, database(), 4 #

결과를 확인해보면 3번 째 column 위치에 database() 값이 들어가 있는 걸 볼 수 있다.

이로써 DB segfault_sql이 있다는 점이 알아냈다! 👏

[5] Table 이름 알아내기

앞에서 어떤 DB가 있는 지 알아냈으니 이제는, 그 DB 안에 어떤 Table이 들어있는 지 확인해보자

이때 사용할 Query는 아래와 같으며 이는,

SELECT table_name FROM information_schema.tables WHERE table_schema = 'DB_NAME'

어떤 Table이 들어있는 지에 대한 정보를 가지고 있는 DB information_schema에게

TABLE tables에서 내가 요청한 DB가 가지고 있는 Table 정보를 알려줘! 라고 Query를 날리는 구문이다.

말이 조금 헷갈릴 수 있는데, 여기서 informaiton_schema

DB에 대한 정보를 저장하는 DB로 흔히 말하는 meta data를 저장하고 있는 Data Base이다.

그 안에서도 굉장히 많은 Table이 존재하는 와중에

어떤 DB가 무슨 table을 가지고 있다! 라는 정보를 넣어둔 Tabletables에서

WHERE table_schema로 주어진 DB에 어떤 table이 들어있는 지 알려 달라는 요청인 셈이다.

따라서 우리는 segfault_sql이라는 DB가 있는 걸 확인했으니 이 DB에 어떤 table이 들어있는 지

알아내기 위해서는 :

SELECT table_name FROM information_schema.tables WHERE table_schema = 'segfault_sql'

이와 같은 Query를 작성해볼 수 있을 것이다.

그렇다면 이 Query도 3번째 column 위치에 넣어서 SQL injection을 실행해보자!

over%' union select 1,2,table_name,4 from information_schema.tables where table_schema='segfault_sql' #

결과를 확인해보면~

총 4개의 table(game, member, secret, secret_member)가 들어있는 걸 확인할 수 있다!!

[6] column 이름 알아내기

현재 시점에서 알아낸 정보는 DB segfault_sql 안에

총 4개의 table(game, member, secret, secret_member)이 들어있다는 것이다.

그렇다면 다음으로 궁금한 정보는 각 table에 어떤 column이 들어있느냐 것!!

column name을 알아내기 위한 Query는 다음과 같다.

SELECT column_name FROM information_schema.columns WHERE table_name='___'

[5]와 동일하게 information_schema에게 물어보는 데

이때 접근하는 테이블은 COLUMN에 대한 정보를 가지고 있는 TABLE columns 이다.

따라서 WHERE table_name으로 요청된 테이블의 column 정보를 알려 달라는 Query 되시겠다.

사용자 계정을 알아내는 것이 우리의 목표였기 때문에 member table 정보를 살펴보면!

over%' UNION SELECT 1,2,column_name,4 FROM information_schema.columns WHERE table_name='member'#

TABLE member에는 총 8개의 COLUMN이 들어있다는 사실을 알아낼 수 있게 되는 것이다!!

(+) 나머지 TABLE(secret, secret_member)

[7] 데이터 추출하기

[1] ~ [6] 과정을 통해 DB, Table, Column 이름까지 우리가 필요한 재료를 모두 수집할 수 있었다.

마지막으로 원하는 데이터를 추출하기 위해 Table에서 column을 지정해 SELECT 하기만 하면 끝!

Table secret 내용이 궁금해서

> SELECT idx, secret FROM secret 

> over%' UNION SELECT 1, idx, secret, 4 FROM secret #

제일 먼저 실행해보았다.

UNION으로 TABLE secret의 정보를 출력해보면 Flag를 얻을 수 있다!

(+) Table secret_member 데이터 추출하기


이렇게 해서 Query의 결과가 화면에 제공되는 경우,

데이터 추출을 어떤 단계에 걸쳐 수행할 수 있을 지 대해 살펴보았다!

전반적인 과정이나 사용한 Query를 외울 필요는 없지만

Query가 뜻하는 바가 무엇이고, 그 과정에서 사용된 information_schema와 같은 개념 정도는

알아두는 게 좋을 듯하다!

Last updated