SQL Injction 취약점을 이용한 인증과정 우회

SQL Injection 취약점

- 외부 입력값에 쿼리 조작 문자열 (# ')  포함 여부를 확인하지 않고 쿼리문 생성 및 시행에 사용하는 경우

- 쿼리의 구조와 의미가 변형되어 실행되는 취약점

 

원래는 ID(식별정보)와 PW(인증정보)를 비교하여 로그인을 해야하는데, 쿼리의 구조와 의미가 변형되면 ID(식별정보)만으로도 로그인이 가능해집니다.

 

예상되는 문제점

- 권한 밖의 데이터 접근 가능

- 해당 데이터베이스가 동작하는 서버를 원격에서 조작 가능(서버의 제어권 탈취)

- 해당 쿼리를 통해 제공하는 기능을 우회 또는 오용하는 것이 가능


#1 사용자 계정을 모르는 상태로 로그인 시도

(1) Window xp에서 http://victim:8080/openeg사이트에 접속하여 임의 값을 넣어 로그인을 해봅니다.

로그인 시도
로그인 실패

 

(2) 사용자 입력 값이 서버로 전달되는 과정을 확인해봅니다.

오른쪽 마우스 클릭 > 소스보기를 클릭합니다. 

=> 개발자도구(F12) 또는 소스보기를 통해서 확인

=> 요청 파라미터를 이용하여 서버로 전달

=> 서버로 전달될 때 http://victim:8080/openeg/login.do?userId=user&userPw=pass 로 전달됩니다.

 

Q. 요청 파라미터로 전달된 값이 서버 내부에서 어떻게 사용될까?

A. 아마 쿼리(SQL)을 만들고 실행하는데 사용될 것이라 유추

select * from 테이블명 where userId(컬럼명) = 'user' and userPw(컬럼명) = 'pass';

=> 쿼리 실행 결과가 있으면 로그인 성공

=> 쿼리 실행 결과가 없으면 로그인 실패

 

#2 사용자 입력값이 서버로 전달되어 그대로 사용되는지 확인

(1) Id와 Pw를 다음과 같이 입력하여 로그인해봅니다.

로그인 시도

=> 서버로 전달될 때 http://victim:8080/openeg/login.do?userId=user'&userPw=pass' 로 전달됩니다.

 

서버 내부에서는 다음과 같이 처리됩니다.

select * from 테이블명 where userId = 'user'' and userPw= 'pass'';

[해석] userId의 컬럼 값이 user'' and userPw= 인 데이터를 조회하는 쿼리

=> 해석할 수 없는 쿼리 즉, 구문오류가 발생합니다.

 

(2) 이전과는 다른 화면이 출력됩니다.

=> 이 오류 페이지로 시스템 내부의 구성을 확인할 수 있고, 사용자 입력 값이 전달되고 사용되는 과정에서 아무런 처리 없이 그대로 사용되는 것도 확인할 수 있습니다. 

 

#3 수집한 정보를 이용하여 추가 공격 시도

(1) Id와 Pw를 다음과 같이 입력하여 로그인해봅니다.

로그인 시도
로그인 실패

=> 서버로 전달될 때 http://victim:8080/openeg/login.do?userId=user' #&userPw=pass 로 전달됩니다.

 

서버 내부에서는 다음과 같이 처리됩니다.

select * from 테이블명 where userId = 'user' #' and userPw= 'pass';

[해석] userId의 컬럼 값이 user 인 데이터를 조회하는 쿼리

=> 쿼리 실행 결과가 있으면 로그인 성공

=> 쿼리 실행 결과가 없으면 로그인 실패

 

*로그인 처리를 하는 쿼리문의 구조와 의미가 변형되었습니다. 로그인을 하기 위해서 ID(식별정보)와 PW(인증정보)가 필요했으나 위의 방식을 이용하면 ID(식별정보)만으로도 로그인이 가능해집니다.

 

#4 사이트에 가입된 회원 ID 조회

회원가입을 클릭하여 해당 사이트에 admin이라는 ID가 존재하는지 확인합니다.

회원가입으로 ID가 존재하는지 확인

=> 해당 사이트에는 admin이라는 ID가 존재합니다.

 

#5 ID: admin으로 로그인 시도

(1) Id와 Pw를 다음과 같이 입력하여 로그인해봅니다.

로그인 시도
로그인 성공

=> 서버로 전달될 때 http://victim:8080/openeg/login.do?userId=admin' #&userPw=pass 로 전달됩니다.

 

서버 내부에서는 다음과 같이 처리됩니다.

select * from 테이블명 where userId = 'admin' #' and userPw= 'pass';

[해석] userId의 컬럼 값이 admin 인 데이터를 조회하는 쿼리

 

=> 관리자로 로그인하여 관리자 권한을 획득하였습니다.

 

안전한 처리 방법

입력 -> 처리 -> 출력

안전한 입력은 개발자가 의도한 형태와 내용으로 입력하는 것입니다. 안전하지 않은 입력은 프로그램 외부에서 전달된 값을 입력하는 것입니다.

처리 시에 안전하게 구현하기 위한 방법으로는 외부입력값을 최소화 하는 것이 좋습니다. 꼭 필요한 항목에 한해서만 외부입력을 처리합니다. 또 외부 입력 검증 및 제한 후 사용해야합니다. 즉, 입력값 필터링이 있어야 안전합니다.