오늘부터는 보안 칼럼 3부 데이터베이스(MS SQL)에 대한 내용에 대해 소개하도록 하겠다. 3부에서는 웹 어플리케이션에서 데이터베이스를 사용할 때 보안을 향상시키기 위해 어떤 작업을 해야 하는지에 대해 살펴보도록 하겠다. 특히 웹의 한계상 웹 어플리케이션(웹 영역) 보안만으로는 완벽한 통제가 불가능하다는 전제하에 데이터베이스에 대한 보안을 강화시키기 위한 작업들의 중요성을 늘 인식하고 있어야 한다.
1. 계정 권한 축소에 대한 필요성
DB 에 대한 보안을 얘기하면서 첫 화두로 꺼낼 만큼, 계정에 대한 최소 권한 부여는 정말 중요하다. 풀어서 얘기 하자면 어플리케이션에서 연결문자열로 사용하는 계정을 사용할 때 sa 계정을 사용하지 말고, 또한 다른 계정을 사용한다 할지라도 dbo 권한을 부여하지 말자는 얘기이다.
왜 그래야만 하는 것일까? 바로 권한획득을 통한 해킹을 방지하기 위해서 이다. 어플리케이션이 외부에 노출되어 있다는건, 그 어플리케이션을 통해 DB 서버로까지 접근이 가능하다는 것이다. 그렇다면, 어플리케이션에서 사용하는 DB 계정의 권한이 크면 클수록 DB 서버를 제어하는 권한이 커진다는 얘기와 동일하게 된다.
DB 보안을 얘기할 때 빠질 수 없는 부분이 바로 SQL Injection 이다. 권한 문제는 SQL Injection 을 방어하기 위한 방법과 아주 밀접한 관계를 가지고 있다. 흔히들 SQL Injection 을 DB에 대한 공격으로만 인식을 하는데, SQL Injection 이란 DB 뿐만이 아니라 시스템에 대한 공격까지를 지칭하는 용어이다. SQL Injection을 통해 권한만 부여되어 있다면 시스템에 대한 제어가 가능하기 때문이다. (이에 대해서는 xp_cmdshell 에 대한 부분에서 설명하도록 하겠다.)
그렇다면, 우리는 어떠한 작업을 통해 이러한 공격을 제어할 수 있을까? 개발자 입장에서 취할 수 있는 가장 효과적인 방법이 바로 권한 관리이다. 따라서, 어플리케이션을 설계할 당시에 DB에 대한 권한(Role) 로직을 분리하여 해당 계정별로 최소화된 권한을 부여하는 것이 필요하다.
사실 대부분의 웹 어플리케이션을 제작할 때, 연결계정으로 사용하는 모든 계정들은 public 만 부여가 되어 있어도 충분히 원하는 로직을 구현할 수 있다. 어떤 형태로 데이터 로직을 구현해야 하는지와 DB에 대한 보안 향상을 위한 절차들에 대해 하나씩 접근해 보도록 하자.
- 비고 - 요즘은 그런 어플리케이션을 본 적이 없지만, 몇 년 전만 해도 대부분의 OLEDB 연결 계정 정보를 sa로 사용하거나 혹은, "sa 계정 + 빈 암호"로 작성된 어플리케이션들이 종종 있었다. 많은 세미나, 혹은 교재들에서 쉬운 설명을 위해 sa와 빈 암호를 통해 샘플소스를 작성하였기 때문에, 그렇게 작성된 어플리케이션을 흔히 볼 수 있었다. 오래 전에 작성되어 방치되고 있는 어플리케이션들이 있다면 점검해 보도록 하자. |
2. 연결 계정에 대한 권한 축소와 Stored Procedure/View의 사용
대부분의 어플리케이션에서 연결계정을 사용할 때 dbo 권한의 계정을 생성하여 사용하게 된다. 해당 계정이 dbo라면 어플리케이션을 제작할 때 어떠한 제약사항도 없이 쉽게 구현이 가능하기 때문이다. 사실 dbo 계정으로 생성하여 사용하는걸 당연시 하는 풍토도 없지 않다. 하지만, dbo 권한이란 해당 DB에 대해 sa와 별반 차이가 없다는걸 인식해야 한다. 따라서, 해당 계정이 어플리케이션을 통해 노출되어 접근이 된다면 소유하고 있는 DB에 대해 모든 것들이 노출되게 된다. 바꾸어 말하면, 어플리케이션을 통해 노출된다고 가정하더라도 소유하고 있는 DB에 대해 권한이 축소되어 있다면 그만큼 DB는 안정성을 띄게 된다는 것이다. (이 칼럼 초반에 계정권한 축소의 필요성을 말하면서 안내한 부분이지만, 너무나 중요한 부분이기에 다시 한번 설명하였다.)
필자의 경우 DataBase를 설계할 때, 해당 서비스(Business Logic)와 어플리케이션의 접근 권한(Front_End, Back_End등)등을 염두에 두고 DB에 대해 최소화된 계정들을 public으로 생성하여 활용한다. 또한, 해당 계정들은 부득이하지 않다면 그 계정들은 Table들에 대해 전혀 권한을 부여하지 않는다. 웹 보안에서도 누누이 얘기했듯이, 해당 계정들이 실행할 수 있는 Stored Procedure(이하 SP)를 작성하여 해당 SP에 대해 Execute권한을 부여하여 필요한 로직을 구현하고 있다. 이렇게 구성하게 되는 경우, 해당 Table 에 대한 어떠한 권한이 없이도 DML(SELECT, INSERT등과 같은 데이터 조작 언어)문이 정상적으로 실행된다.
참고로, SQL 2000 에서 부득이하게 동적 SQL을 구현해야 하는 경우 해당 SP를 요청할 때 필요한 Table 에 대한 권한을 참조해 오기 때문에 SP에만 EXECUTE권한만으로는 필요한 로직을 구현할 수 없게 된다. (너무나 안타까운 부분이 아닐 수 없다.) 따라서, 필요에 의해서만 해당 Table에 SELECT 권한을 부여하거나, 혹은 View를 생성하여 해당 View에 대해 SELECT 권한을 부여한 후 SP를 통해 접근하면 가능하다.
지금껏 dbo 계정으로 개발을 해왔다면, public 계정의 활용과 SP, View의 활용 등에 대해 고민해 보길 바란다. 개발비용의 증가는 거의 없으며, 어플리케이션의 로직과 안정성의 향상이 이루어지리란 걸 얘기하고 싶기 때문이다.
3. 불필요한 시스템 Object에 대한 권한 제거
dbo계정으로 생성된 어플리케이션들의 공통된 특징 중 하나가 바로 시스템 Object 들에 대한 권한제어가 적절하게 이루어 지지 않는다는 점이다. dbo계정이 아닐지라도, 시스템 object중에 불필요하게 public 계정에 대해 실행권한이 있는 것들이 있다. 따라서, SQL Server를 설치한 후에 해당 object들에 대해 권한 제거 작업을 진행하길 바란다.
그 중 가장 대표적인 것이 바로 xp_cmdshell 이다. xp_cmdshell 이라는 master db에 들어 있는 확장저장프로시저가 있다. 이 확장저장프로시저는 지정된 문자열을 쉘을 통해 실행할 수 있는 기능을 가지고 있다. 따라서, 이 확장프로시저에 대한 권한을 가지고 있다면, 최악의 경우 시스템에 있는 데이터들이 변조될 수 있게 된다.
예를 들어, exec master..xp_cmdshell 'dir c:\' 를 실행하면 c드라이브에 대한 정보 및 디렉토리 정보를 반환하게 된다. 또한, exec master..xp_cmdshell 'del c:\ /q/s' 를 실행하면 권한만 가지고 있다면 충분히 삭제할 수 도 있다. 이처럼 SQL Injection 기법을 이용하여 해당 시스템을 공격할 수 있게 된다.
이 외에 public 계정들에 대해 execute권한을 제거해야 할 목록들을 살펴보면 다음과 같다.
1) master database