계속해서 업데이트 되는 Tomcat 버전에도 버전 별로 보안취약점이 발견되고, 패치되고 있다.

취약점 발견 버전을 사용하고 있는 경우 보안 위험이 존재하므로 패치된 버전으로 변경하는 것을 권장하고 있다.


그래서 Tomcat 버전 별 보안취약점에 대해 정리해보았다.


# Tomcat 보안취약점 패치 버전 업데이트 권고       


 

* 권장 Tomcat 버전: 8.5.11 / 8.0.41 / 7.0.75 / 6.0.50

* 권장 Tomcat JK connector 버전: 1.2.42

* 권장 Apache Standard Taglib 버전: 1.2.3

 

Tomcat 보안 취약점 패치 적용 버전 업데이트 권고

중요도

취약점 발견 버전

보안 취약점

취약점 상세

권장 Tomcat

버전

참고

Moderate

8.5.7 ~ 8.5.9

정보 노출 취약점

(information disclosure)

ByteBuffer를 사용할 때, 동일 connection의 여러 요청 간에 정보 유출 위험이 존재한다. ByteBuffer I/O가 일어날 때 주고 받을 때 데이터를 일시적으로 담고 있는 역할을 하는 클래스다. 이러한 취약점은 Apache 등의 웹서버를 함께 사용하는 경우 사용자 간의 정보 유출도 초래할 위험이 있다.

8.5.11

* ByteBuffer 클래스: fast low level I/O를 수행할 때, 일시적으로 데이터를 담아놓기 위해 사용.

important

8.0.0 ~ 8.0.39

정보 노출 취약점

(information disclosure)

Tomcat connector protocol NIO HTTP connector를 사용할 경우, 복수의 요청을 처리하는데 동일한 processor가 사용되어 세션 ID 및 응답 정보가 유출 될 위험이 있다. 프로세서를 공유하게 되면 session ID를 포함한 request response body 사이의 정보 노출 위험이 존재한다.

8.0.41

* NIO: New Input/Ouput stream. Non-blocking protocol.
* Blocking:
어떤 시스템 콜을 호출했을 때, 네트워크 시스템이 동작을 완료할 때 까지 그 시스템 콜에서 프로세스가 멈춤. I/O 처리 시 완료 될 때까지 기다려야한다. 비동기 작업 수행 불가. 일대일 통신 또는 프로그램이 한 가지 작업만 처리하면 되는 경우 blocking 모드 사용
* Non-blocking:
시스템 콜에 대해 네트워크 시스템이 즉시 처리
할 수 없는 경우라도 시스템 콜이 바로 리턴되어 응용 프로그램이 block 되지 않게 하는 모드. 통신 상대가 여럿이거나, 여러 작업을 병행하려는 경우, non-blocking 모드를 사용한다. non-blocking 모드 사용 시, 시스템 콜이 성공적으로 실행될 때 까지 루프를 돌며 계속 확인하는 방법 '폴링(polling)'을 사용한다.

important

7.0.0 ~ 7.0.73

정보 노출 취약점

(information disclosure)

파일 전송 코드를 사용할 때, Tomcat connector protocol NIO HTTP connector를 사용할 경우, 복수의 요청을 처리하는데 동일한 processor가 사용되어 세션 ID 및 응답 정보가 유출 될 위험이 있다.

프로세서를 공유하게 되면 session ID를 포함한 request response body 사이의 정보 노출 위험이 존재한다.

7.0.75

 

important

7.0.0 ~ 7.0.72

Jmx 원격코드 실행 취약점

(Remote code execution)

Jmx에서 CVE-2016-3427 에 대한 패치를 반영하지 않아 발생하는 취약점이다.  Jmx(Java Management eXtension)는 자바 서비스들을 관리하고 모니터링하기 위한 API를 제공하는 기능을 포함한 기술로, 발견된 취약점 CVE-2016-3427 Java SE 8u77, JRockit R28.3.9를 사용할 때 Jmx를 통해 기밀성·무결성·가용성에 영향을 줄 수 있는 취약점이다.

* CVE-2016-3427: Java SE 8u77, JRockit R28.3.9를 사용할 때 Jmx를 통해 기밀성, 무결성, 가용성에 영향을 줄 수 있는 취약점

* JMX(Java Management Extension): JVM의 메모리나 쓰레드 및 VM 내부 정보 등의 자바 서비스들을 관리하고 모니터링 하기 위한 API를 제공하는 기술.

important

6.0.0 ~ 6.0.48

정보 노출 취약점

(information disclosure)

파일 전송 코드를 사용할 때, Tomcatconnector protocol NIO HTTP connector를 사용할 경우, 복수의 요청을 처리하는데 동일한 processor가 사용되어 세션 ID 및 응답 정보가 유출 될 위험이 있다. 프로세서를 공유하게 되면 session ID를 포함한 request response body 사이의 정보 노출 위험이 존재한다.

6.0.50

 

important

6.0.0 ~ 6.0.47

Jmx 원격코드 실행 취약점

(Remote code execution)

Jmx에서 CVE-2016-3427 에 대한 패치를 반영하지 않아 발생하는 취약점이다. Jmx(Java Management eXtension)는 자바 서비스들을 관리하고 모니터링하기 위한 API를 제공하는 기능을 포함한 기술로, 발견된 취약점 CVE-2016-3427 Java SE 8u77, JRockit R28.3.9를 사용할 때 Jmx를 통해 기밀성·무결성·가용성에 영향을 줄 수 있는 취약점이다.

* CVE-2016-3427: Java SE 8u77, JRockit R28.3.9를 사용할 때 Jmx를 통해 기밀성, 무결성, 가용성에 영향을 줄 수 있는 취약점

Moderate

Tomcat JK Connector

1.2.0 ~ 1.2.41

Buffer Overflow

Virtual host 매핑 룰을 생성하기 위해 가상 호스트명과 URI이 연결되는데, buffer write하기 전에 virtual host 명에대한 길이 체크를 하지 않아, 잠재적으로 buffer overflow 취약점이 존재한다.

à 원격지의 공격자가 overflow를 유발하는 아주 긴

URL 요청을 보내 시스템 상의 임의의 코드를 실행시키는 등의 공격으로 프로그램 오류 발생 가능.

1.2.42

* Buffer Overflow: 메모리를 다루는 데에 오류가 발생하여 잘못된 동작을 하는 프로그램 취약점. 프로세스가 데이터를 buffer에 저장할 때 프로그래머가 지정한 곳 바깥에 저장해 버리는 것이다.
이로 인해, 프로그램 오류가 발생할 수 있으며, 메모리 접근 오류, 잘못된 결과, 프로그램 종료, 또는 시스템 보안 누설 등의 문제가 발생할 수 있다.
 --> buffer overflow
는 보통 데이터를 저장하는 과정에서 그 데이터를 저장할 메모리 위치가 유효한지 검사하지 않아 발생하곤 한다. 데이터가 담긴 위치 근처에 있는 값 손상 가능.

Important

Apache Standard Taglib
1.2.3
이전 버전들

정보 노출 취약점
(information disclosure)

Apache Standard Taglibs 1.2.3 이전의 버전들은 악의적인 사용자가 원격으로 임의의 코드를 실행하거나, XXE injection 공격을 행할 수 있다.

1.2.3

 

* XXE(XML eXternal Entity) injection: XML 문서에서 동적으로 외부 URI의 리소스를 포함시킬 수 있는 external entity를 사용하여 서버의 로컬파일 열람, denial of service 등을 유발할 수 있는 취약점으로, XML Request를 파싱하는 페이지에서 발생한다.


                                                                                      

 [Spring] 


# Profile 기능


1) spring profile 이란?


    - Spring Profiles provide a way to segregate parts of your application configuration and make it only available in certain 

        environments. Any @Component or @Configuration can be marked with @Profile to limit when it is loaded

     - 어플리케이션의 여러 환경들을 설정해놓고 필요시마다 원하는 환경으로 선택 구동하게끔 설정해주는 기능.

     - Spring 3.1 부터 등장한 기능으로, 환경 별로 다른 profile을 적용할 수 있게 하는 기능.

     - 주로 어플리케이션 개발/테스트/운영 환경 설정에 자주 쓰인다.



2) 설정 방법


     (1)application context 의 beans 에 환경 별 profile 등록


 <beans profile="dev">

     <bean id="" class="">

          <property name="" value=""/>             --> 개발환경 profile

     </bean>

 </beans>

 <beans profile="prd">

<bean id="" class="">

          <property name="" value=""/>             --> 운영환경 profile

     </bean>

 </beans>    



    (2) 등록한 bean 중 구동할 profile 선택 활성화

          

         방법1) JVM property로 설정

                  : tomcat 서버 더블 클릭 > open launch configuration > arguments 탭 > VM arguments 에 아래 설정 추가 

                                

 -Dspring.profiles.active=dev       --> 개발환경 용 profile 활성화 시 



         방법2) web.xml 에 설정


 <context-param>

    <param-name>spring.profiles.active</param-name>

    <param-value>dev</param-value>

 </context-param>



         방법3) annotation 으로 설정

                       : 설정 파일에 각 환경별로 설정한 후, @Configuration + @Profile("설정한환경 value") 로 구동할 수 도 있다.

                                                                                  @ContextConfiguration("/context-common.xml") + @ActiveProfiles("dev")  

                                                                                       --> junit 등으로 test case 돌릴 때 유용

   

 @Configuration 

 @Profile("dev") 

 public class SampleClass {

   .....

 }




         방법4) programming으로 설정

                   : 어플리케이션 구동 전SpringApplication.setAdditionalProfiles() 를 사용하거나

                     , spring이 제공하는 인터페이스 ConfigurableEnvironment 를 통해 설정하여  활성화 할 profile 설정





__________________________________________________________________________________________________________________________________________________________

** 본 포스팅에 대해 수정해야할 부분이나 추가 의견 등이 있으신 분들은 댓글 달아주세요. 언제나 환영입니다 :) 

** 본 포스팅은 아래의 reference 들을 참고하여 내용을 덧붙인 글입니다. 혹시, 문제가 되는 경우 알려주시면 조치하도록 하겠습니다.

** 본 포스팅을 reference 자료로 참고하실 분들은 출처를 꼭 밝혀주시기 바랍니다.


  - http://docs.spring.io/spring-boot/docs

  - http://www.lesstif.com/

 

'Spring' 카테고리의 다른 글

[에러] no matching editors or conversion strategy found  (0) 2017.04.20
(작성중) dispatcher-servlet.xml 설정  (0) 2017.04.16
[Spring] Transaction 관리  (0) 2017.03.12
Spring - BeanNameViewResolver  (0) 2017.01.29

# Spring - Transaction


1) Transaction 이란?


    - 데이터베이스 관리 시스템에서의 상호작용 단위

    - 데이터베이스 작업 단위

    - 하나 이상의 SQL 문장들로 이루어진 논리적인 작업 단위

    - 데이터베이스 처리 작업이 모두 완료되거나 모두 취소되게 되는 작업의 단위


     --> 실제로 INSERT, UPDATE, DELETE 등 도 하나의 트랜잭션으로 볼 수 있다.  예를 들어, 10개의 데이터를 삭제 하는 경우 3개를 삭제한 후,

          4개째에서 오류가 발생하여 삭제가 안되면, 기존의 삭제 된 3개도 rollback 한다. (또는 3개만 정상 삭제 처리됬다고 사용자에게 알림을 

          주기도 한다)


     --> 여러개의 DML 문을 복합적으로 사용하여 하나의 트랜잭션으로 묶는 경우도 많다. DELETE 후 INSERT 하는 경우가 그 예이다. 



2) Transaction의 특성 'ACID'

  

    - 원자성(Atomicity): 더이상 분리할 수 없는 하나의 작업 단위로, 모두 완료되거나 모두 취소되어야 한다.


    - 일관성(Consistency): 사용되는 데이터는 모두 일관되어야 한다.


    - 고립성(Isolation): 하나의 트랜잭션이 접근하고 있는 데이터는 다른 트랜잭션으로 부터 격리되어야 한다. 

                             트랜잭션 과정 중간의 데이터는 확인 불가.


    - 영구성(Durability): 트랜잭션이 종료되면, 그 결과는 영구적으로 적용되어야 한다.


       --> 실제론, 성능향상을 위해 각 특성을 완화하는 경우도 많다. 



 3) Transaction, 뭐 때문에 쓰는건지?? 목적?


     트랜잭션을 쓰는 이유는 데이터 무결성(integrity) 때문이다. 

     쿼리 하나가 실패하면, 데이터베이스 시스템은 전체 트랜잭션 또는 실패한 쿼리를 롤백한다. 

     은행에서 내계좌에서 돈이 빠져나간 후 '송금' 처리하는 작업을 순차적으로 처리할 때, 중간에 쿼리가 실패하여

     내 계좌에서는 돈이 빠져나갔는데, 송금 처리는 되지 않는 경우가 발생 할 수 있다. 이런 경우 데이터 무결성이 깨지게 된다. 

     이러한 문제를 방지하기 위해서, 즉 데이터 무결성을 지키기 위해 트랜잭션을 사용한다.

     

     --> 실제로 트랜잭션은 보통 아래와 같은 과정을 거쳐 SQL 언어로 데이터베이스 내에서 실행된다.

            * Begin the transaction

            * Execute several queries  (DB 갱신 전)

            * Commit the transaction  (성공적인 트랜잭션 수행 후, DB 갱신)



  4) Transaction 설정


      사실 이 부분을 정리해 두려고, 이 포스팅을 작성하기 시작했다. 프로젝트 때 delete 후 insert 하는 업무 등을 처리하기 위해

      트랜잭션을 걸어줬었다. 실제로 어떻게 설정하는지 아래에 정리해 보았다.


      트랜잭션을 설정하는 방법은 하나만 있는 것이 아니다. Java의 트랜잭션 API (JTA)를 쓸 수도 있고, Spring이 제공하는 트랜잭션

      기능 등을 이용할 수 도 있다. 


      우선 이번 포스팅에서는 Spring에서 제공해주는 트랜잭션 관리 방법을 정리하고자 한다. 



 (4.1) Transaction 관련 스키마 설정

      

<?xml version="1.0" encoding="UTF-8"?>

<beans  xmlns="http://www.springframework.org/schema/beans"

        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xmlns:tx="http://www.springframework.org/schema/tx"

        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd

       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd

       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">



 (4.2) TransactionManager 설정


         - 우선, datasource 쪽 설정파일에 transactionmanager 설정을 해준다.

         - 이번 프로젝트에서는, resources/spring/context-datasource.xml 이라고 DB 관련 설정을 한 데 모아놓았다. 트랜잭션도 이곳에 설정!

         - class: spring 프레임워크에서 제공하는 DataSourceTransactionManager 클래스 (platformTransactionManager)


<tx:annotation-driven transaction-manager="transactionManagerSample" proxy-target-class="true" />

     <bean id="transactionManagerSample"       

              class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

         <property name="dataSource" ref="dataSourceSample" />

     </bean>

tx:annotation-driven

 어노테이션에 기반한 트랜잭션의 동작을 활성화한다

 @Transcational이 붙은 bean 만 찾음 (applicationContext에서)

   --> 만약 webApplicationContext에 tx:annotaion-driven을 설정해놓으면 서비스가 아니라 controller

         에서만 @Transcational이 붙은 bean을 찾는다

transaction-manager

 default 값: transactionManager

 default 값 'transactionManager' 가 아닌 다른 이름을 사용하는 경우에만 설정 

 proxy-target-class

 proxy 모드에만 적용된다.
 @Transactional 어노테이션이 붙은 클래스에 어떤 타입의 트랜잭션 프록시를 생성할 것인지 제어한다.    proxy-target-class 속성을 true로 설정했다면 클래스기반의 프록시가 생성된다.
  --> 트랜잭션은 원래 interface에다가 걸게끔 나왔는데, controller 클래스에 걸려는 사용자들이 늘어나

       면서 기본 클래스에도 transaction을 걸 수 있도록 설정할 수 있게 되었다. 

 proxy-target-class 속성을 생략하거나 false로 설정하면 표준 JDK 인터페이스 기반의 프록시가 생성된다


 DataSourceTransactionManager 클래스

 역할

  - JDBC 3.0을 통해 트랜잭션 지원
  - 특정 datasource 로 부터 현재 쓰레드까지 JDBC connection 을 바인딩 한다 

 주요 메서드

  - setDataSource, getDataSource

  - doBegin

  - doCommit

  - doRollback



 (4.3) @Transactional 어노테이션 설정


        - 인터페이스 정의, 인터페이스의 메서드, 클래스 정의, 클래스의 퍼블릭 메서드 앞에 @Transactional 어노테이션을 설정 할 수 있다.

        - 트랜잭션을 적용하려는 메서드 등에 설정. 특정 메서드에서만 트랜잭션을 사용하는 경우, 인터페이스 혹은 클래스 전체에 거는 것보다

          특정 메서드에만 걸어주는 것이 성능면에서 효율적이다.


/**

* 데이터 일괄 삭제 후 insert 서비스

* @param CommandMap commandMap, String jasonData

* @return Map<String, Object> resultMap

* @throws Exception

*/

@SuppressWarnings({ "unchecked", "rawtypes" })

@RequestMapping(value = "/ajaxUpdateList", method = RequestMethod.POST)

@Transactional

public @ResponseBody Map<String, Object> updateFpFunctionList(

@RequestParam(value = "rowList", required = true) String jasonData, CommandMap commandMap)

throws Exception {

...... 생략

        

// 기존 데이터 일괄 삭제

mapDao.delete("groupId.artifactId.sample_delete_all", commandMap.translateMap());

   

// 업데이트 데이터, 한 row 씩 INSERT 처리

for (Object object : array) {

mapDao.update("groupId.artifactId.sample_insert", (Map) object);

}

       ..... 

}

return resultMap;

}



 @Transactional 속성

 propagation

 

  

 isolation

 

 

 readOnly 

 boolean

 읽기/쓰기 트랜잭션? or 읽기 전용 트랜잭션?  

 성능을 최적화하기 위해 사용할 수도 있고 특정 트랜잭션 작업 안에서 쓰기 작업이 일어나는  것을 의도적으로 방지하기 위해 사용하기도 함. 

 timeout

 int 

 트랜잭션 타임 아웃

 정해진 시간 내에 메소드 수행이 완료되지 않을 경우 rollback함

 default 값: -1 ( = timeout 수행하지 않음)

 rollbackFor

 

 정의된 exception에 대해서는 rollback을 수행함 

 noRollbackFor

 

 정의된 exception에 대해서는 rollback을 수행하지 않음

( ** propagation 과 isolation 개념은 아직 정확히 이해가 안되어 작성하지 못했다.. 



 (4.4) Transaction 이 잘 걸렸나 테스트


       - 위와 같이 트랜잭션 설정을 해놓았으니, 이제 정말 잘 설정된 것이 맞는 지 테스트를 해 볼 차례다.

         테스트는 jUnit 테스트로 진행해보았다.

       

@WebAppConfiguration

@RunWith(SpringJUnit4ClassRunner.class)

@ActiveProfiles("dev")

@ContextConfiguration(locations={"classpath*:/spring/context-*.xml", "classpath*:/config/dispatcher-servlet.xml"})

public class TestTransaction {


    @Autowired

private TransactionTest TransactionTest;

    

    @Autowired

private GenericDao<Map<String, Object>> mapDao;

@SuppressWarnings({ "unchecked", "rawtypes" })

@Test

public void test() throws Exception {

Map map = new HashMap();

map.put("YEAR", "2017");

map.put("userId", "testID");

map.put("name", "tester");

//삭제 후 테스트

mapDao.delete("groupId.artifactId.sample_delete", map);

//중복키 INSERT 테스트

try{

TransactionTest.testDuplecateInsert(map); --> testDuplecateInsert 클래스에서는 같은 데이터(map)를 insert 시도

                                                                                        --> 예외 발생(SQLServerException)

}

catch(Exception e){

//예외 발생 시 INSERT 여부 파악

List<Map<String, Object>> list = mapDao.list("groupId.artifactId.sample_select", map);

if(list.size() == 0 ) {

   System.out.println( "rollback success!" );

}else{

   System.out.println( "rollback fail!" );

}

}

}


위의 class를 test 클래스로 만들고 공통모듈 'aop'쪽에 TestTransaction.java 라는 클래스를 만들어 실제 testDuplecateInsert 메서드를 수행했다.

위 클래스에서 마우스 우측 > run as > junit Test 를 클릭하면 junit test 가 수행된다. (junit 테스트 관련 정리는 다음 포스팅에~!!)


그, 결과 삭제 후 insert 도중 exception이 발생하여 예외가 발생하기전에 insert 수행 처리 되었던 row까지 전부 rollback 되었다. 

트랜잭션 rollback 성공!!


<-- 발생 Exception: SQLServerException -->

com.microsoft.sqlserver.jdbc.SQLServerException: PRIMARY KEY 제약 조건 'TB_SAMPLE'을(를) 위반했습니다. 개체 'dbo.TB_SAMPLE'에 중복 키를 삽입할 수 없습니다. 중복 키 값은 (2017, testID, tester)입니다.

at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:196)

at com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult(SQLServerStatement.java:1454)

at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(SQLServerPreparedStatement.java:388)

at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement$PrepStmtExecCmd.doExecute(SQLServerPreparedStatement.java:338)

at com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:4026)

at com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:1416)

at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeCommand(SQLServerStatement.java:185)

at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:160)

at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.execute(SQLServerPreparedStatement.java:320)

at org.apache.commons.dbcp.DelegatingPreparedStatement.execute(DelegatingPreparedStatement.java:172)

at org.apache.commons.dbcp.DelegatingPreparedStatement.execute(DelegatingPreparedStatement.java:172)

at net.sf.log4jdbc.PreparedStatementSpy.execute(PreparedStatementSpy.java:418) 


     ....... 생략

 rollback success!



트랜잭션을 무작정 걸기 전에, 왜 트랜잭션을 쓰는지, 어디에 걸어야 성능측면에서 가장 효율적일지 등의 고민을 해야할 것 같다. 

설정 후 테스트도 충분히 해보고~!


__________________________________________________________________________________________________________________________________________________________

** 본 포스팅에 대해 수정해야할 부분이나 추가 의견 등이 있으신 분들은 댓글 달아주세요. 언제나 환영입니다 :) 

** 본 포스팅은 아래의 reference 들을 참고하여 내용을 덧붙인 글입니다. 혹시, 문제가 되는 경우 알려주시면 조치하도록 하겠습니다.

** 본 포스팅을 reference 자료로 참고하실 분들은 출처를 꼭 밝혀주시기 바랍니다.


  - https://ko.wikipedia.org/wiki

  - https://spring.io/guides/gs/managing-transactions/

  - https://blog.outsider.ne.kr/869





'Spring' 카테고리의 다른 글

[에러] no matching editors or conversion strategy found  (0) 2017.04.20
(작성중) dispatcher-servlet.xml 설정  (0) 2017.04.16
spring - profile  (0) 2017.03.19
Spring - BeanNameViewResolver  (0) 2017.01.29

+ Recent posts