이번 포스팅에선 인증 우회에 대해 이야기해보겠습니다.
인증 우회는 간단하게 말하면 로그인을 우회하는 방법이라고도 할 수 있겠습니다.
이러한 방법에는 쿠키를 변조하거나, 아니면 직접 url에 접근해서 페이지를 이동한다거나 하는 여러 방법이 있겠지만 그 중에서도 특히 SQL Injection에 대해 이야기하겠습니다.
DB에 연결된 로그인 페이지는 SQL문을 이용해서 DB에 접근해 로그인 인증 절차를 간다는 것을 이전 포스팅에서 본 적이 있습니다. 여기서 중요한 점은 사용자가 입력하는 입력값에 대해 검증을 제대로 하지 않는 취약점을 가지고 있으면 SQL문을 끼워넣을 수 있다는 것입니다. 공격자가 입력창에 악의적으로 SQL문을 끼워넣어 공격하는 것이 바로 SQL Injection입니다.
SQl문을 입력창에 적으면 무엇을 할 수 있기에 이것이 공격이라고 할까요?
이 취약점을 막지않으면 인증을 우회할 수 있습니다. 아이디나 비밀번호를 몰라도 로그인을 할 수 있는 경우도 있고, 아이디만 알아도 로그인을 할 수 있는 등 보안에 큰 취약점을 갖게 되는것입니다.
select * from userTBL where id='[uid]' and pw='[upw]'라는 코드로 로그인 인증을 하는 페이지가 있다고 가정해봅시다. id에 적은 값은 uid로 가고 pw에 적은 값은 upw로 가서 인증을 하는 경우입니다.
여기서 aab 라는 아이디를 알고있다면 id 창에 aab' #을 적고 비밀번호는 모르니까 아무렇게나 적으면?
select * from userTBL where id='aab' #' and pw='123' 이런식으로 SQL문이 DB로 전달될 겁니다. 여기서 핵심은 #은 주석이기때문에 뒤에 있는 것이 주석처리가 됩니다. 즉 DB에서 받은 SQL문은 select * from userTBL where id='aab'까지인 것이니 'aab'인 값이 존재하므로 로그인을 할 수 있게 되는 것입니다.
주석처리와 동일하게 select * from userTBL where id='[uid]' and pw='[upw]'코드를 쓴다고 가정하겠습니다. 이번엔 OR 연산자를 이용하는 것입니다. select문에 where 조건은 true와 false를 사용하는 조건문이라고 봐도 됩니다. 그래서 DB에 값이 존재하면 true인 1을, 없으면 false인 0을 준다고 볼 수있죠.
이번에는 id 창에 aab' or '1'='1을 적고 pw 창에는 아무거나 적어보겠습니다.
select * from userTBL where id='aab' or '1'='1' and pw='123'이 되겠네요.
여기서 핵심은 연산자의 우선순위입니다. and와 or는 논리 연산자에 속하는데 이 연산자간에 우선순위가 존재합니다. and가 or보다 순위가 높고, 이것을 적용하면 먼저 '1'='1' and pw='123'의 연산을 해야겠네요. 1은 1이 맞으니 true, 1입니다. 뒤에 pw는 잘 모르니 틀렸을거고 0이라고 하겠습니다.
and 연산자는 둘 다 1이어야 1이기때문에 0, 즉 false겠죠. 그 이후 or 연산자를 적용하는 것입니다.
id='aab' or 0이라는 연산을 하는데 aab라는 id가 존재한다는 것은 알고 있었으니 true, 1입니다.
그리고 or 연산자는 둘 중 하나만 1이어도 1이므로 1 or 0은 1, true입니다. 그렇기 때문에 'aab'를 select한 결과가 존재하고 로그인이 되는 것입니다.
이렇듯 SQL Injection은 중요한 취약점이니 페이지를 만들 때 신경써서 SQL구문을 끼워넣지 못하도록 잘 설계하는 것이 중요한 것으로 보입니다.