'Tomcat'에 해당되는 글 6건
- 2011/02/15 SecureOS(RedCastle)를 이용한 웹 서버 보안 강화
- 2010/09/02 Tomcat Web Server SSL 설정
- 2009/06/18 Tomcat JSP DB(Oracle) 연동 소스코드
많은 기업들이 방화벽이나 IPS와 같은 네트워크 기반의 보안 솔루션을 도입하여 운영중인 서버들을 인터넷을 통해 시도되는 공격 위협으로부터 서버들을 보호하고 있다.
하지만 기업들도 어쩌지 못하는 취약한 구멍이 존재한다.
바로 기업의 홈페이지가 구동중인 웹 서버와 메일서버다. 그리고 기업들이 운영하는 B2B와 같이 인터넷에 공개할 수 밖에 없는 서버가 존재한다. 그리고 이렇게 인터넷에 공개되는 서비스들은 대부분 웹서버(TCP/80)로 운영되어 진다. 다른 서비스는 모두 차단되어 있지만 웹서비스를 수행하는 TCP/80은 기업으로서도 어쩔 수 없는 아킬레스건과 같은 존재다.
해커들은 이러한 아킬레스건을 절대 그냥 두지 않는다.
Apache, Tomcat, Weblogic, Webtob, Jeus 등 수많은 웹 서비스 관련 응용프로그램들이 존재한다. 이러한 응용프로그램들은 인터넷을 통해 수많은 사용자의 PC와 통신을 하고 있고 인터넷 어디서든 TCP/80을 통해 이 응용프로그램에 연결할 수 있기 때문에 해커들은 웹 서버 대몬의 취약성 혹은 웹 서버에서 실행되는 PHP, JSP, Servlet 등의 취약성을 찾기 위해 혈안이 되어 있다.
해커들이 웹서버를 공격하기 위해 사용하는 대표적인 취약성으로 OWASP 10대 취약성 이야기하곤 한다. OWASP는 Open Web Application Security Project의 약자로서 이 프로젝트에서는 매년 10대 웹 취약성을 발표하고 있다. 여기에서 발표된 대부분의 취약성은 웹 응용프로그램 즉 PHP, JSP, ASP, Servlet 등을 개발할 때 프로그램 소스 수준에서 발생할 수 있는 취약성들을 담고 있으며 취약성이 포함된 웹 응용프로그램을 구동할 경우 홈페이지 위/변조 및 악성코드 삽입 더 나아가 웹 응용프로그램의 관리자 권한 및 운영체제의 계정 탈취 혹은 운영체제의 관리자 권한 탈취까지도 이루어질 수 있게 된다.
보안이라하면 아직가지도 방화벽, IPS, 웹방화벽PKI,
VPN과 같은 네트워크 기반의 보안 솔루션만이 있다고 알고 있는 보안 담당자들을 많이 볼 수 있다. 하지만 이러한 네트워크 기반의 보안
솔루션들은 모두 흘러가는 패킷을 분해하여 데이터영역의 내용을 검사하거나 암호화하는 수준의 단순한 기능을 갖고 있다. 따라서 해커가 열려진 포트를
통해 단순한 공격도구가 아닌 웹서비스로 개발된 웹페이지 혹은 응용프로그램의 취약성을 공격하였을 경우 십중팔구 공격을 차단하지 못한다. 이는
서비스가 구동중인 운영체제 수준에서 근본적인 파일 접근통제를 수행하지 못하기
때문이다.
그렇다면 요즘 서버 운영체제의 보안을 강화하기 위해 많이 도입되기 시작한 Secure OS 제품을 이용하여 웹 서버의 보안도 강화할 수 있을까?
정답은 “그렇다” 이다.
특히 다음과 같은 부분에서는 다른 어떤 보안 솔루션도 따라오지 못할 만큼의 강력한 보안기능을 제공할 수 있다.
1. PHP, JSP, JS, ASP, HTML, Servlet 등 웹 응용프로그램의 위/변조 혹은 공격을 위한 소스 업로드 방지
2. 웹 서버 대몬 (httpd, java 등)의 취약성을 이용한 운영체제의 명령어 실행 차단
3. 웹 서버에서 구동중인 응용프로그램의 취약성을 이용한 운영체제의 명령어 실행 차단
4. 업로드 취약성을 이용해 공격도구를 업로드 하고 실행시키는 공격의 차단.
5. 웹 서버를 통해 운영체제 임시 디렉토리의 접근 권한이 있음을 이용해 공격 경유지로 이용하는 행위의 차단.
6. 웹 서버가 구동중인 계정의 권한을 탈취하여 수퍼유저 권한을 탈취하려는 시도의 차단.
이러한 기능을 제공할 수 있는 이유는 Secure OS가 커널수준에서 다음의 기능을 수행할 수 있기 때문이다.
1. 웹 서버 대몬 혹은 웹 서버가 구동중인 계정에서 소스파일 혹은 설정파일에 대해 특정 프로그램 이외에는 쓰기(Write, Create, Delete, Modify)를 하지 못하도록 할 수 있다.
2. 웹 서버 대몬(httpd, java 등)이 운영체제의 주요 명령어를 실행(Excute System Call)하지 못하도록 할 수 있다.
3. root 계정에서 웹 소스파일에 접근하지 못하도록 할 수 있다.
4. 업로드 경로 및 웹 소스의 경로에서 파일의 실행을 차단할 수 있다.
5. 웹 서버 대몬 혹은 웹 서버가 구동중인 계정에서 운영체제의 임시디렉토리에 접근하는 것을 차단할 수 있다.
6. 일반계정에서 root 계정으로의 이동을 원천적으로 차단할 수 있으며 백도어의 실행도 원천적으로 차단할 수 있다.
SecureOS (RedCastle)은
MAC(강제적 접근제어)와
DAC(임의적 접근제어) 보안 모델을
적절하게 적용함으로서 위의 기능들을 제공한다. 또한 웹 서버 뿐만 아니라 모든 서버의 내부에서 일어나는 행위에 대한 통제를 적절하게 수행할 수
있다.
디지털 커머스의 증가와 중요한 데이터간의 이동이 필요함에 따라서 보안은 모든 어플리케이션에서 중요한 자리를 차자하고 있습니다. 일반적으로 client 와 서버간에 사용자를 확인하기 위한 방법으로 username 과 password 를 체크합니다. 이를 사용하는 보안 처리 기법으로 Secure Sockets Layer (SSL) 과 Java Authentication and Authorization Service (JAAS)를 사용할 수가 있습니다. 먼저 SSL로 보안인증을 거치는 방법을 보고 java 에서 지원하는 다른 사용자 인증서비스인 JAAS을 jsp와 서블릿에서 사용하는 법을 보겠습니다.
1. 톰켓에서 사용자 인증 처리하기
톰켓으로 사용자 인증처리를 하기전에 먼저 username, password, role 을 등록해야 합니다. 등록하는 방법은 아주 쉽습니다. 톰켓이 설치된 폴더에서 /conf 에 보면 tomcat-user.xml 파일이 있습니다. 없으면 에디터 창에서 새로 만들어도 됩니다.
<?xml version='1.0' encoding='utf-8'?><?xml version='1.0' encoding='utf-8'?>
<tomcat-users>
<role rolename="dbadmin"/>
<role rolename="manager"/>
<user username="hans" password="hansworld" roles="dbadmin,manager"/>
<user username="jojo" password="33dsk3" roles="manager"/>
</tomcat-users>
위 소스에서 hans는 dbadmin과 manager의 권한을 갖고 jojo는 manager의 권한을 갖습니다.
다음으로 톰켓서버에서 SSL을 셋팅해야 합니다. 이는 username이나 password 가 http상에서 이동할 때 암호화 되어 이동하기 때문에 중간에 악의적인 의도로 가로채거나 훔쳐내는 것을 방지해 줍니다. SSL을 셋팅하기 위해선 2가지 절차를 거쳐야 합니다.
1. java sdk에서 지원해주는 keytool로 keystore 파일을 만듭니다. 이 파일은 보안 접속을 하는 서버가 디지털 인증을 암호화 해서 사용하는데 쓰여집니다.
2. 톰켓의 conf/server.xml 파일에 SSL Connector에 있는 주석을 제거합니다.
keytool은 java가 설치된 in 에서 찾을 수 있습니다.
%JAVA_HOME%inkeytool -genkey -alias tomcat -keyalg RSA
위의 명령을 실해하면 keystore 파일이 생성되는데 몇가지 질문을 합니다. 처음으로 패스워드를 물어보는데 톰켓에서 기본적으로 "changeit" 란 패스워드로 셋팅되어 있습니다. 나머지는 원하지 않으면 그냥 엔터키만 치면 됩니다.
Enter keystore password: changeit
What is your first and last name?
[Unknown]: Bruce Perry
What is the name of your organizational unit?
[Unknown]:
What is the name of your organization?
[Unknown]:
What is the name of your City or Locality?
[Unknown]:
What is the name of your State or Province?
[Unknown]:
What is the two-letter country code for this unit?
[Unknown]:
Is CN=Bruce Perry, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown correct? [no]: yes
Enter key password for <tomcat>
(RETURN if same as keystore password):
다음에 conf/server.xml 에 있는 SSL Connector 요소에 있는 주석을 제거합니다.
<!-- Define a SSL Coyote HTTP/1.1 Connector on port 8443 -->
<connector disableuploadtimeout="true" useurivalidationhack="false" secure="true" scheme="https" debug="0" acceptcount="100" enablelookups="true" maxprocessors="75" minprocessors="5" port="8443" classname="org.apache.coyote.tomcat4.CoyoteConnector">
<factory classname="org.apache.coyote.tomcat4.CoyoteServerSocketFactory" protocol="TLS" clientauth="false" />
</connector>
SSL은 일반 http 가 아닌 https 를 사용합니다. 또한 포트도 웹에서 80, 톰켓에서 8080 처럼 8443의 번호를 사용합니다.
https://localhost:8443/myhome/default.jsp
2. BASIC authentication BASIC Authentication
Basic 인증은 웹자원과 함께 사용되어온 보안 방법이고 거의 모든 브라우져가 이를 지원합니다. 일반적으로 사용자 이름과 비밀번호를 전송할 때 네트워크 상에서 Base64 인코딩 방식을 사용하는데 이는 디코딩하기 아주 쉽기때문에 보안적이라고 할 수 없습니다. 따라서 Basic Authentication 과 SSL 을 사용한 보안 방식을 사용합니다.
1. 먼저 처음에 설명했지만 username, password, role을 conf/tomcat-users.xml 에서 설정합니다.
2. security-constraint element 로 인증에 필요한 자원을 web.xml 파일에 기술합니다.
3. "BASIC"이라고 auth-method요소 사이에 적습니다. 이 auth-method 요소는 login-config요소에 들어갑니다.
<!-- Beginning of web.xml deployment descriptor -->
<security-CONSTRAINT>
<web-RESOURCE-COLLECTION>
<web-RESOURCE-NAME>JSP database component</web-RESOURCE-NAME>
<url-PATTERN>/myhome.jsp</url-PATTERN>
<http-METHOD>GET</http-METHOD>
<http-METHOD>POST</http-METHOD>
</web-RESOURCE-COLLECTION>
<auth-CONSTRAINT>
<role-NAME>dbadmin</role-NAME>
</auth-CONSTRAINT>
<user-DATA-CONSTRAINT>
<transport-GUARANTEE>CONFIDENTIAL</transport-GUARANTEE>
</user-DATA-CONSTRAINT>
</security-CONSTRAINT>
<login-CONFIG>
<auth-METHOD>BASIC</auth-METHOD>
</login-CONFIG>
<security-ROLE>
<role-NAME>dbadmin</role-NAME>
</security-ROLE>
<!-- Rest of web.xml deployment descriptor -->
web.xml 을 이렇게 편집한 후에 https://localhost:8443/myhome.jsp 로 들어가보면 아이디와 비밀번호를 입력하라는 창이 뜹니다. 여기서 만일 role 이 dbadmin 이 아니라면 아이디와 비밀번호가 맞아도 인증에 실패하게 됩니다. 반드시 해당 사용자가 인증에 필요한 role을 가지고 있어야 합니다.
3. Form-Based Authentication 의 사용
서블릿은 일반 BASIC authentication 말고도 사용자 기반 인증인 Form-Based Authentication 제공합니다. 이는 톰켓에서 보여주는 BASIC authentication 의 단순화를 덜어주며 일반적으로 사용하는 form 방식을 사용하기 때문에 이용하기도 편합니다. 이역시 SSL 과 HTTPS를 사용하여 네트워크상에서 이동하는 데이터들을 보호합니다.
먼저 web.xml 셋팅을 보겠습니다. 파일의 맨 처음부분에 보안 관련 element를 기술하게 됩니다. security-constraint 부분은 BASIC authentication 과 같습니다. login-config 셋팅부분이 약간 다르긴 하지만 그렇게 크게 다르지는 않습니다.
<login-CONFIG>
<auth-METHOD>FORM</auth-METHOD>
<form-LOGIN-CONFIG>
<form-LOGIN-PAGE>/login.html</form-LOGIN-PAGE>
<form-ERROR-PAGE>/loginError.jsp</form-ERROR-PAGE>
</form-LOGIN-CONFIG>
</login-CONFIG>
실제 jsp에서
<form>테그를 사용하여 사용자 정보를 전송하는데 이때 주의할 점은 form 태그의 action 요소의 값을 'j_security_ckeck' 로 하고 사용자 이름과 비밀번호의 이름을 'j_username' 과 'j_password'로 해야합니다. 로그아웃 시에는 HttpSession 객체의 invalidate() 메소드를 호출하면 됩니다.</form>
<%@ page import="java.sql.Connection" %>
<%@ page import="java.sql.DriverManager" %>
<%@ page import="java.sql.SQLException" %>
<%@ page import="java.sql.Statement" %>
<%@ page import="java.sql.ResultSet" %>
<%
String url = "jdbc:oracle:thin:@127.0.0.1:1521:orcl";
String id = "scott";
String pass = "tiger";
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try{
Class.forName("oracle.jdbc.driver.OracleDriver"); //드라이버 로딩
conn = DriverManager.getConnection(url, id, pass); //접속경로, 아이디, 패스워드
stmt = conn.createStatement(); //sql을 던지기 위한 도구
String query="select empno, ename, deptno from emp";
// insert, update, delete 문은 executeUpdate() 을 생성
// select 문은 executeQuery() 을 생성
rs = stmt.executeQuery(query);
while(rs.next()){
out.println(rs.getInt("empno")+" : ");
out.println(rs.getString("ename")+" : ");
out.println(rs.getInt("deptno")+"<br>");
}
} catch(ClassNotFoundException cnfe) {
out.println("드라이버를 찾을 수 없습니다.");
} catch(SQLException se) {
out.println(se.toString());
} finally { //닫을때는 맨마지막에 열린것부터 닫는다.
if(rs != null) rs.close();
if(stmt != null) stmt.close();
if(conn != null) conn.close();
}
%>
- 다른 방법
<%@ page import="javax.naming.InitialContext" %>
<%@ page import="javax.naming.Context" %>
<%@ page import="javax.sql.DataSource" %>
<%@ page import="javax.naming.NamingException" %>
<%@ page import="java.sql.Connection" %>
<%@ page import="java.sql.SQLException" %>
<%@ page import="java.sql.Statement" %>
<%@ page import="java.sql.ResultSet" %>
<%
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try{
Context initCtx = new InitialContext(); //context 선언
Context envCtx = (Context)initCtx.lookup("java:comp/env"); //톰캣의 설정을 가져옴
DataSource ds = (DataSource)envCtx.lookup("jdbc/oracle"); //설정에서 jdbc/oracle을 가져옴
conn = ds.getConnection();
stmt = conn.createStatement(); //sql을 던지기 위한 도구
String query="select empno, ename, deptno from emp";
// insert, update, delete => executeUpdate()
// select => executeQuery()
rs = stmt.executeQuery(query);
while(rs.next()){
out.println(rs.getInt("empno")+" : ");
out.println(rs.getString("ename")+" : ");
out.println(rs.getInt("deptno")+"<br>");
}
} catch(NamingException ne) {
out.println("설정명을 찾을 수 없습니다.");
} catch(SQLException se) {
out.println(se.toString());
} finally { //닫을때는 맨마지막에 열린것부터 닫는다.
if(rs != null) rs.close();
if(stmt != null) stmt.close();
if(conn != null) conn.close();
}
%>
- server.xml
<Context docBase="project1" path="/project1" reloadable="true" source="org.eclipse.jst.j2ee.server:project1">
<Resource name="jdbc/oracle" auth="Contener" type="javax.sql.DataSource"
driverClassName="oracle.jdbc.driver.OracleDriver" loginTimeout="10" maxWait="5000"
username="scott" password="tiger" url="jdbc:oracle:thin:127.0.0.1:1521:orcl"
testOnBorro="true"/>
</Context>

RedCastle Admin Guide.pdf
Prev

Facebook

