- 2021.11.09
- KISA 개발보안 점검에서 properties 중요구문 암호화처리가 나옴.
개발환경
- STS 4
- JAVA 1.8
- jasypt-spring-boot-starter v 3.0.3
- application.properties
질병관리본부 프로젝트 운영 오픈전에 외부로 오픈되는 웹 프로젝트의 개발 소스에 대해서 여러가지 보안 점검을 진행하였다.
최종적으로 KISA의 Fortify툴을 사용하여 보안 점검을 하였는데, application.properties에 비밀번호에 해당되는 중요 정보가 암호화 되지 않았다는 점검 결과를 받았다.
Spring Boot framework로 데이터베이스 연동시 흔히 디비 접속 정보를 application 외부 프로퍼티로 설정해 두기 때문에, 개발당시 전혀 염두하지 못한 부분이였다. 하지만 충분히 외부 프로퍼티를 통해 접속정보를 탈취한 해커로 부터 공격을 당할 수 있는 부분이기 때문에 이 부분은 중요한 사항이였다.
1. Password Management: Password in Configuration File
KISA Fortify 점검 내역은 아래와 같다.
KISA49: 암호화 되지 않은 중요정보 (Password Management: Password in Configuration File)
Abstract : 일반 텍스트 암호를 구성 파일에 저장하면 시스템 침해가 발생할 수 있습니다.
Explation : 일반 텍스트 암호를 구성 파일에 저장하면 파일을 읽을 수 있는 사용자면 누구나 암호로 보호되는 리소스에 접근할 수 있습니다. 때때로 개발자가 설정에 대한 접근 권한이 있는 사람에게서 응용 프로그램을 방어할 수 없다고 생각하 는 경우가 있는데 이런 태도가 공격자에게 유리하게 작용합니다. 훌륭한 password management 지침은 암호를 절 대 일반 텍스트로 저장하지 않도록 요구합니다.
Recommendations: 암호를 일반 텍스트로 저장해서는 안 됩니다. 시스템이 시작될 때 관리자에게 암호를 입력하도록 요구해야 합니다. 이 방법을 사용할 수 없을 때 안전성은 떨어지지만 비교적 타당한 솔루션은 암호를 난독 처리하고 시스템에 난독 처 리 해제 요소를 분산시켜, 공격자가 여러 시스템 리소스를 확보하여 정확하게 조합해야만 암호를 해독할 수 있게 만 드는 것입니다
결론적으로, 나는 외부 프로퍼티에 중요정보를 암호화 처리해야했고, Spring Boot에서 프로퍼티 정보를 읽을 때 복호화하여 읽도록 설정을 해야했다.
구글링을 통해 위 기능을 지원해 주는 jasypt 라이브러리를 알게되었다.
2. jasypt (Java Simplified Encryption)
jasypt는 무엇인가?
Jasypt is a java library which allows the developer to add basic encryption capabilities to his/her projects with minimum effort, and without the need of having deep knowledge on how cryptography works.
jasypt는 최소한의 노력으로 기본 암호화 기능을 제공하는 자바 라이브러리이다.
jasypt 특징
- 단방향 및 양방향 암호화 기술로 높은 보안을 제공해준다.
- 비밀번호, 텍스트, 숫자, 바이너리 등을 암호화 할 수 있다.
- Spring Security와 Hibernate와도 연동이 가능하다.
- 스레드로 부터 안전하기 때문에 Spring과 같은 싱글톤 지향 환경에서 동기화 걱정 없이 사용할 수 있다.
jasypt가 properties를 복호화하는 방식
- Spring 프로젝트가 빌드되고 서버에 올라가면서 context가 생성된다.
- 생성되는 타이밍에 jasypt가 암호화된 context를 복호화한다.
- 복호화할 때 키가 필요한데, 이 키는 암호화할 때 사용한 키와 동일하다.
- 키는 구동 서버의 환경변수로 존재한다.
3. jasypt 사용방법
Spring boot 환경에서는 jasypt-spring-boot-starter 라이브러리를 사용할 수 있다.
jasypt-spring-boot-starter
Jasypt (Java Simplified Encryption) Spring Boot provides utilites for encrypting property sources in Boot applications.
jasypt-spring-boot-starter는 Spring Boot application에서 프로퍼티 소스를 암호화하기 위한 유틸리티를 제공한다.
1. maven dependency 추가
jasypt-spring-boot-starter를 사용하기 위해서 의존성을 추가한다.
<!-- jasypt -->
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
2. Configuration 작성
암호화된 context를 jasypt가 복호화하기 위한 설정을 한다. 클래스명은 JasyConfig로 하였다.
import org.jasypt.encryption.StringEncryptor;
import org.jasypt.encryption.pbe.PooledPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class JasyptConfig
{
private final static String KEY = "암복호화에 사용할 키";
private final static String ALGORITHM = "PBEWithMD5AndDES";
private final static String CNT = "1000";
private final static String POOl_SIZE = "1";
private final static String BASE64 = "base64";
@Bean(name="jasyptStringEncryptor")
public StringEncryptor stringEncryptor()
{
SimpleStringPBEConfig config = new SimpleStringPBEConfig();
config.setPassword(KEY); // 암호화할 때 사용하는 키
config.setAlgorithm(ALGORITHM); // 암호화 알고리즘
config.setKeyObtentionIterations(CNT); // 반복할 해싱 회수
config.setPoolSize(POOl_SIZE); // 암호화 인스턴스 pool
config.setStringOutputType(BASE64); //인코딩 방식
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
encryptor.setConfig(config);
return encryptor;
}
}
Spring boot에 JasyptConfig를 jasypt의 복호화 설정하는 Bean으로 주입하기 위해 "jayptStringEncryptor"이름의 Bean으로 생성하였다.
- setPassword(KEY) : jasypt가 암/복호화 할 대 사용할 키 값 이다.
- setAlgorithm(ALGORITHM) : jasypt가 암/복호화 할 때 사용할 알고리즘이다. 기본 값은 PBEWITHHMACSHA512ANDAES_256이다.
- setKeyObthentionInterations(CNT) : 암호화 키를 얻기 위해 적용되는 해싱 반속 횟수를 설정한다.
- setPoolSize(POOL_SIZE) : 생성할 암호기 풀의 크기를 설정한다. 설정하지 않은 경우 null값이 반환된다.
SimpleStringPBEConfig의 기본 값은 아래 github에서 확인 할 수 있다.
https://github.com/ulisesbocchio/jasypt-spring-boot
3. Bean 주입
application.properties에 "jasyptStringEncryptor" Bean을 주입시킨다.
jasypt.encryptor.bean=jasyptStringEncryptor
4. properties에 암호화 값 세팅
먼저 콘솔 또는 java로 암호화 된 값을 구한다.
public static void main(String[] args) {
SimpleStringPBEConfig config = new SimpleStringPBEConfig();
config.setPassword(KEY); // 암호화할 때 사용하는 키
config.setAlgorithm(ALGORITHM); // 암호화 알고리즘
config.setKeyObtentionIterations(CNT); // 반복할 해싱 회수
config.setPoolSize(POOl_SIZE); // 암호화 인스턴스 pool
config.setStringOutputType(BASE64); //인코딩 방식
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
encryptor.setConfig(config);
System.out.println("hello > " + encryptor.encrypt("hello"));
// result : hello > PUvf3DxlcyW9+neub7eXqA==
}
JasyptConfig의 값과 동일하게 설정 한 후 원하는 텍스트 문구를 암호화시켰다. 암호화 된 문구를 application.properties에 적으면 된다.
단. 적을 때 주의 할 점은 ENC() 메소드로 감싸서 기입해야, jasypt가 복호화 대상으로 인식한다.
spring.datasource.password=ENC(PUvf3DxlcyW9+neub7eXqA==)
이후 프로젝트를 실행하면 전과 동일하게 암호화 된 텍스트로 데이터베이스 연동이 된다.
4. 마치면서
어딜가나 비밀번호 보안이 당연히 우선순위인 것은 알았다. 하지만 정작 프로젝트를 진행하면서 외부로 노출될 수 있는 프로퍼티에는 아무렇지 않게 비밀번호를 그대로 기재하였다.
실제로 특정 프로젝트의 데이터베이스 접속정보를 모를 때 프로퍼티에 적혀있는 정보로 알아가고는 하였다. 나는 개발할 때 접속정보를 잠깐 잊어 알기 위해서였다지만, 이는 분명히 비밀번호가 노출될수 있는 보안에 취약한 것이였다.
내가 분명히 간과하였던 부분이였다.
Spring boot 프로젝트 뿐 아니라, 외부 프로퍼티로 중요정보를 세팅하는 경우 암호화처리는 필수라는 것을 염두해 두어야 겠다.
https://www.baeldung.com/spring-boot-jasypt
'Framework & Library > Spring & String boot' 카테고리의 다른 글
Spring과 Spring Boot란? (0) | 2024.03.10 |
---|---|
[Spring] RestTemplate - Java에서 HTTP 통신 (0) | 2021.12.19 |
[Spring] Running code after Spring Boot Run (0) | 2021.06.21 |
[Spring] SSH 터널링(Port Forwarding) - gradle (0) | 2021.01.28 |
[Spring] ModelAndView로 파일 다운로드 (@Component, Bean 등록) (0) | 2020.12.30 |