UNION [3]

DATE : 2023/11/29

이번 POST에서 살펴볼 내용은 UNION [2]와 관련하여 궁금했던 두 가지 의문에 대해 다뤄볼 생각이다.

UNION [2]의 상황을 다시 떠올려보면

타인의 계정으로 로그인하고 싶은 hanhxx가 자신의 비밀번호를 이용해 로그인을 우회했다.

이 과정에서 든 첫 번째 의문은

"그렇다면 계정이 아예 없는 사람은 로그인을 우회할 수 없는 걸까?"였다.

자신의 비밀번호가 아닌 임의 값을 비밀번호로 사용하면 안 되는 가!! 에 대한 의문을 풀기 위해

바-로 값을 넣어보았다.

mario 계정으로 로그인을 시도하는 과정에서 DB에 들어있지 않은 비밀번호 1234를 입력해보기로 했다.

ID : ' union select 'mario', '1234
PASS : 1234

다음과 같이 값을 넣으면

이와 같은 Query가 완성되기 때문에

SELECT * FROM member WHERE id ='' UNION SELECT 'mario','1234'

결과로 나오는 ROW는

[Query Result]
> id = 'mario'
> pass = '1234'

우리가 입력한 값 그 자체일 것이다.

이 상태에서 사용자가 입력한 비밀번호와 Query 결과로 나온 비밀번호를 가져오면

if($user_pass == $db_pass) { ... }

두 값을 비교하는 과정에서 동일한 값, 1234가 비교되기 때문에

임의의 비밀번호를 사용하더라도 로그인 우회에 성공한 걸 볼 수 있다!


바로 이어서, 두 번째 궁금증을 해결해보도록 하자.

사실 UNION 연산자를 사용하기 위해서는 지켜야 할 규칙이 있는 데, 그 중 하나가

UNION 연산자 앞 뒤에 작성된 SELECT문의 결과는 동일한 column 개수를 가져야 한다는 것이다.

만약 첫 번째 SELECT문의 결과가 2개의 COLUMN을 가지는 데에 비해

두 번째 SELECT문의 결과가 3개의 COLUMN을 가진다면

두 SELECT문의 결과를 합쳐주는 UNION 입장에서는 COLUMN 수가 일치하지 않으니

"부족한 부분을 채워야 하나? 아닌가, 넘치는 쪽을 버려야 하나?" 싶을 것이다.

따라서 두 SELECT문이 반환하는 COLUMN 개수를 동일하게 만들어줄 필요가 있는데 문제는..!

UNION 연산자를 사용해 우리가 원하는 비밀번호를 사용할 수 있도록 하기 위해서는

(1) 첫 번째 SELECT문이 반환하는 COLUMN 개수가 몇 개인지

(2) 비밀번호가 몇 번째 COLUMN에 들어가는 지

를 알아야 한다.

그렇다 보니 사실 UNION SELECT 'mario','1234 의 경우는

(1) Query 결과가 2개의 column을 포함한다는 사실과 (id, pass)

(2) column의 순서가 id, pass 라는 걸 알기 때문에 바로 작성할 수 있었던 것이다.

그렇다면 여기서 당연히!

COLUMN의 개수를 어떻게 알아낼 수 있을지 궁금해질 것!!

(이번 POST에서는 (1)을 알아내기 위한 방법만 간단히 살펴볼 예정)

방법은 생각보다 단순하다.

SELECT * FROM member WHERE id = 'hanhxx' union SELECT 1

위와 같이 Query를 작성했다고 가정해보자.

UNION을 사용한 경우에 앞 뒤 SELECT문의 결과로 나온 COLUMN 개수가 일치하지 않으면

결과가 나오지 않는 것은 당연하며 Different number of columns 내용의 에러가 나오는 걸 볼 수 있다.

1 ) SELECT * FROM member WHERE id = 'hanhxx' union SELECT 1
2 ) SELECT * FROM member WHERE id = 'hanhxx' union SELECT 1, 1
3 ) SELECT * FROM member WHERE id = 'hanhxx' union SELECT 1, 1, 1
...

이처럼 의미 없는 값을 나열하면서 Query를 실행하다 보면

SELECT문의 결과와 column의 개수가 일치하는 경우에만

아래와 같이 에러가 발생하지 않을 것이다.

따라서 우리는 에러의 발생 유무로 COLUMN 개수를 알아낼 수 있게 된다. 👍

참고로 두 번째 SELECT문에서 1을 나열할 때, 중요한 건 1이라는 값이 아니라

1이 몇 개 나열되었는가(= 나열된 1의 개수가 곧 COLUMN의 개수)이기 때문에

1이 아닌 다른 값을 사용해도 상관없다!

이렇게 해서 UNION과 관련된 내용은 마무리 하고 다음 주제로 넘어 가보자!!

Last updated