UNION [2]
DATE : 2023/11/29
UNION [1]에 이어서 로그인 우회를 시도해보자!!
우리가 UNION 연산자를 이용한 Query를 입력했다고 상상해보면
ID : hanhxx' union select 'mario1','mario2
PASS : ???
맨 앞에 작성한 "hanhxx" 라는 값은 첫 번째 SELECT문으로 들어가게 된다.
그렇게 되면 hanhxx의 정보와 mario1, mario2가 합쳐진 결과가 만들어 지게 되고
if($db_pass == $user_pass) { ... } else { ... }
비밀번호를 비교하는 과정에서는 먼저 수행되어 결과를 도출한 hanhxx의 비밀번호로
비교 연산이 실행될 것이다.
이는 결국 hanhxx의 비밀번호를 오류 없이 입력했을 경우,
hanhxx 계정으로 로그인하는 것일 뿐 우회를 위한 Query로 사용할 수는 없다.
그.래.서
비밀번호를 비교하는 과정에서 ROW가 여러 개면 맨 위에 있는 ROW의 비밀번호로만
비교 연산에 사용되기 때문에
첫 번째 SELECT문의 ID 값을 비워버리고 (= 거슬리는 첫 번째 row 없애자!)
UNION으로 우리가 원하는 값을 비밀번호 연산 과정에서 사용하도록 만들자! 는 것이다. 💡
현재 사용자가 hanhxx라고 할 때, hanhxx는 mario 계정으로 로그인 시도를 하는 상황이라 생각해보자.
자신의 계정이 아니기 때문에 mario의 비밀번호를 모르는 hanhxx는 로그인을 우회할 필요가 있어 보인다.
ID : ' union select 'mario','hanhxx1234
PASS : hanhxx1234
고민 끝에 입력한 ID & PASSWORD는 위와 같았다.

식별과 인증이 분리되어 실행되는 로직이기 때문에, 우선 hanhxx가 입력한 ID로 SELECT문이 실행되었다.
SELECT문의 결과를 확인해보면, hanhxx가 입력한 값만 그대로 나오는 걸 볼 수 있다!!
이는 Query의 결과가 하나이기 때문에 hanhxx가 입력한 자신의 비밀번호가
결과로 반환 된 ROW의 비밀번호로 들어가게 되고
동시에 로그인할 때 입력한 비밀번호 또한 hanhxx 자신의 것이기 때문에
결국 hanhxx가 입력한 비밀번호와 Query 결과로 얻어온 비밀번호가 일치하게 됨으로써

로그인에 성공할 수 있게 된다.
즉, 자신의 비밀번호를 이용해 mario의 계정으로 로그인 우회를 성공한 것이다!
이렇게 해서 식별과 인증을 따로 실행하는 로그인 로직에서의 우회 방법을 살펴보았다.
전체적인 과정을 정리하면 다음과 같다 :
(1) union operator를 사용해 총 2개의 SELECT문이 실행될 수 있게 구성한다.
(2) UNION 앞에 작성된 select문의 결과가 나오지 않도록 id를 공백 처리한다.
(3) UNION 뒤에 작성된 select문에는 자신이 로그인하고자 하는 id & 사용할password를 입력
(4) (3)에서 사용한 password를 로그인 시 입력한다.
or, and 연산자를 이용한 경우의 Query 보다는 좀 더 어려울 수 있지만
UNION 연산자를 활용하는 방법이 있다는 걸 확실하게 얻어가자 🤗
Last updated