Oracle JVM Security 관련(16.05.17)

Oracle JVM에 대해 먼저 알아보자.

JVM이란 한번 작성한 코드를 OS, 플랫폼과 무관하게 재사용할 수 있도록 java application과 OS 중간에서 중계해주는 역할을 맡고 있다. 일반적으로 서버에 JVM을 설치하면 Unix/Linux의 경우 실행파일은 /usr/bin/java 에 위치하게 된다. 서버에 JVM이 설치되어 있음에도 불구하고 이와는 별개로 Oracle JVM을 설치하는 경우가 있는데 Oracle JVM은 왜 필요한 것일까?

Oracle을 설치할 때나 혹은 설치하고 나서 JVM을 설치히면 패키지나 프로시저내에서 PL/SQL 뿐만 아니라 java를 사용할 수 있게 된다. java의 강력한 기능을 생각하면 오라클 DB내에서 왠만한 것들은 다 할 수 있다는 의미이다.

그런데 일반적으로 JVM이 OS 리소스를 사용하기 위해서는 권한이 필요하다. 예를 들어 java class 실행 시 특정 디렉토리에 대한 read, write 권한이 필요한 경우가 있을 수 있고,
TCP 통신을 위한 socket 의 access, listen, connect 권한이 필요한 경우가 있다.

이를 위해 J2EE security standard 에서는 필요한 권한을 허용해주는 방법을 정의하여 제공하며 보통 별도의 파일에 필요한 grant 권한을 추가함으로써 관리한다. Oracle JVM에서도 예외는 아니며 작성한 java class가 올바르게 작동하기 위해서는 각종 권한이 필요할 수도 있다. 그럼 Oracle JVM에서는 이 권한을 어떻게 관리할까?

결론적으로 말하자면 Oracle DBMS 내 Policy Table을 이용하여 그 안에 grant, restrict 내용을 추가하여 관리한다. Policy Table은 DBA_JAVA_POLICY 뷰나 USER_JAVA_POLICY 뷰를 통해 내용을 확인할 수 있다. 이 테이블의 내용은 특정유저가, 어떤 오브젝트에 대해 어떤 action하는 것을 허용/불허할 것인지에 대한 내용을 담고 있다.

dba_java_policy.jpg

위 그림은 Oracle 11.2.0.3 버전에서 확인한 DBA_JAVA_POLICY 뷰의 내용이며 컬럼에 대한 설명은 아래를 참조.

  • KIND: Grant 인지, 혹은 Restrict 인지를 결정하는 것이며 Grant면 특정 오브젝트에 대해 action을 허용하는 것을 의미하고 Restrict면 action을 불허하는 것이다.
  • GRANTEE: 어떤 유저에게 부여되었는지를 가리킨다.
  • TYPE_NAME: 허용/불허 하고자 하는 오브젝트의 상위 모듈인 class 를 의미하는데, 사전 정의된 class를 입력하면 되지만 JAVA를 알아야 하는 부분으로 DBA에겐 좀 생소한 부분이다. 매뉴얼에서 확인했을 때, 이 항목에 올 수 있는 값은 아래와 같다.- java.util.PropertyPermission
    – java.io.SerializablePermission
    java.io.FilePermission
    – java.net.NetPermission
    java.net.SocketPermission
    – java.lang.RuntimePermission
    – java.lang.reflect.ReflectPermission
    – java.security.SecurityPermission
  • NAME: 허용/불허하고자 하는 오브젝트를 명시하며 TYPE_NAME에서 선택한 class에 따라 NAME의 형식은 달라진다. 사용 예시는 아래 참조.
  • ACTION: 허용/불허할 행위를 명시한다. NAME에 따라 올 수 있는 값이 달라진다.

Policy table에 내용을 업데이트하려면 DBMS_JAVA.GRANT_PERMISSION 프로시저를 이용하도록 한다. DBMS_JAVA 패키지를 사용하려면 JAVA_ADMIN 롤이 있어야 하며 DBA권한이 있으면 실행 가능하다.

예시1) EMP가 만든 java application이 /etc 디렉토리내 모든 파일에 대한 read/write 권한을 갖도록 하려면

exec DBMS_JAVA.GRANT_PERMISSION(grantee =>’EMP’ , type_schema=>’java.io.FilePermission’, name=>’/etc/*’, action=>’read,write’) ;

예시2) EMP가 만든 java application이 TCP 통신이 필요하며 서버 abc.example.com:443 로의 연결이 가능하도록 권한을 구성하려면

abc.example.com이 DNS를 통해 IP를 확인할 수 있도록 resolve권한과 연결을 위한 connect 권한을 준다.

exec DBMS_JAVA.GRANT_PERMISSION(grantee =>’EMP’ , type_schema=>’java.net.SocketPermission’, name=>’abc.example.com:443‘, action=>’resolve,connect’) ;

 

RESTRICT

GRANT외에 RESTRICT도 가능한데 DBMS_JAVA.RESTRICT_PERMISSION 프로시저를 이용하면 된다. 가령 EMP유저가 /etc/passwd 파일을 read/write 하지 못하도록 제한할 경우 사용할 수 있다. 아래 두 커맨드를 조합하면 EMP는 /etc/passwd 파일을 제외하고 /etc 디렉토리 안에 존재하는 모든 파일에 대해서 read/write 권한을 갖게 된다.
(참고로 모든 유저에게 GRANT/RESTRICT 권한을 줄 경우 grantee에 PUBLIC을 넣으면 된다)

exec DBMS_JAVA.GRANT_PERMISSION(grantee =>’EMP’ , type_schema=>’java.io.FilePermission’, name=>’/etc/*’, action=>’read,write’) ;
exec DBMS_JAVA.RESTRICT_PERMISSION(grantee =>’EMP’ , type_schema=>’java.io.FilePermission’, name=>’/etc/passwd’, action=>’read,write’) ;

 

REVOKE/DISABLE/ENABLE

GRANT하거나 RESTRICT했던 내용을 disble할 수 있는데 REVOKE_PERMISSION이나 DISABLE_PERMISSION 프로시저 중에 하나를 사용하면 된다. 두 프로시저의 차이점은 사용해야 하는 변수에 있다. REVOKE 프로시저의 경우 GRANT/RESTRICT 할 때 처럼 4개의 변수를 모두 나열해야 하며 DISABLE의 경우 SEQ 컬럼에 있는 값을 변수로 넣으면 된다. ENABLE 시킬 때는 DISABLE과 같이 SEQ 값을 변수로 넣어주면 된다.

— DISABLE 시키기
exec dbms_java.disable_permission(85);

or
exec dbms_java.revoke_permission(grantee =>’EMP’ , type_schema=>’java.io.FilePermission’, name=>’/etc/*’, action=>’read,write’) ;

— ENABLE 시키기
exec dbms_java.enable_permission(85);

 

DELETE

말 그대로 Policy Table에 있는 항목을 삭제하는 것이다. DBMS_JAVA.DELETE_PERMISSION 프로시저를 이용하면 된다. 주의 사항으로 delete 하기 전에 disable이 되어 있을 것, 변수는 SEQ 값만 받는다는 것이다.

exec dbms_java.delete_permission(85);

 

ROLE: JAVAUSERPRIV / JAVASYSPRIV

오라클 8i부터 JAVAUSERPRIV와 JAVASYSPRIV 롤이 존재하는데 이 Role들은 언제 쓰는 것일까?

먼저 JAVAUSERPRIV 롤이 가지고 있는 권한들이다.
위의 예에서 봤던 socket에 대한 connect, resolve권한과 모든 파일의 read 권한이 있는 것을 확인할 수 있다.

JAVAUSERPRIV

다음은 JAVASYSPRIV 롤이다. JAVAUSERPRIV가 제공하는 것보다 더 넓은 범위의 권한을 가지고 있다.

JAVASYSPRIV

이 Role을 유저에게 부여하면 일일이 Policy Table에 등록하는 절차가 필요없어지게 된다. 그러나 사실 이 2개의 Role은 데이터베이스 버전 호환성을 위해 존재하는 것이고 가급적 사용하지 않도록 해야 한다. 즉 최소한의 필요한 권한만 식별하여 Policy Table에 등록하는 것이 옳다.