UNION [3]
DATE : 2023/11/29
Last updated
DATE : 2023/11/29
Last updated
이번 POST에서 살펴볼 내용은 UNION [2]와 관련하여 궁금했던 두 가지 의문에 대해 다뤄볼 생각이다.
UNION [2]의 상황을 다시 떠올려보면
타인의 계정으로 로그인하고 싶은 hanhxx가 자신의 비밀번호를 이용해 로그인을 우회했다.
이 과정에서 든 첫 번째 의문은
"그렇다면 계정이 아예 없는 사람은 로그인을 우회할 수 없는 걸까?"였다.
자신의 비밀번호가 아닌 임의 값을 비밀번호로 사용하면 안 되는 가!! 에 대한 의문을 풀기 위해
바-로 값을 넣어보았다.
mario 계정으로 로그인을 시도하는 과정에서 DB에 들어있지 않은 비밀번호 1234를 입력해보기로 했다.
다음과 같이 값을 넣으면
이와 같은 Query가 완성되기 때문에
결과로 나오는 ROW는
우리가 입력한 값 그 자체일 것이다.
이 상태에서 사용자가 입력한 비밀번호와 Query 결과로 나온 비밀번호를 가져오면
두 값을 비교하는 과정에서 동일한 값, 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)을 알아내기 위한 방법만 간단히 살펴볼 예정)
방법은 생각보다 단순하다.
위와 같이 Query를 작성했다고 가정해보자.
UNION을 사용한 경우에 앞 뒤 SELECT문의 결과로 나온 COLUMN 개수가 일치하지 않으면
결과가 나오지 않는 것은 당연하며 Different number of columns 내용의 에러가 나오는 걸 볼 수 있다.
이처럼 의미 없는 값을 나열하면서 Query를 실행하다 보면
SELECT문의 결과와 column의 개수가 일치하는 경우에만
아래와 같이 에러가 발생하지 않을 것이다.
따라서 우리는 에러의 발생 유무로 COLUMN 개수를 알아낼 수 있게 된다. 👍
참고로 두 번째 SELECT문에서 1을 나열할 때, 중요한 건 1이라는 값이 아니라
1이 몇 개 나열되었는가(= 나열된 1의 개수가 곧 COLUMN의 개수)이기 때문에
1이 아닌 다른 값을 사용해도 상관없다!
이렇게 해서 UNION과 관련된 내용은 마무리 하고 다음 주제로 넘어 가보자!!