2022-04-04-TIL
Today I Learned
Spring4Shell 제로데이 취약점
2022년 3월 말 공개된 Spring Framework의 원격 코드 실행 취약점(CVE-2022-22965)으로, Log4Shell에 빗대 Spring4Shell이라고 불렸다. Spring 공식 공지에 따르면 영향받는 조건은 다음과 같다.
- JDK 9 이상에서 실행
spring-webmvc또는spring-webflux의존- Spring Framework 5.3.0~5.3.17, 5.2.0~5.2.19 및 그 이전 버전
- 보고된 공격 시나리오는 전통적인 WAR로 패키징해 독립 서블릿 컨테이너(Tomcat 등)에 배포한 경우
원인은 요청 파라미터를 객체에 채우는 데이터 바인딩에서 ClassLoader에 접근할 수 있었던 것이다. 공격자가 바인딩 경로로 톰캣의 로그 설정을 바꿔 웹셸 파일을 쓰게 만드는 방식이 알려졌다. 기본 배포 방식인 Spring Boot 실행 가능한 JAR는 보고된 공격에는 해당하지 않지만, 공지는 취약점의 성격상 다른 공격 경로가 있을 수 있다고 덧붙인다. 해결책은 수정 버전인 Spring Framework 5.3.18/5.2.20, 이를 쓰는 Spring Boot 2.6.6/2.5.12로 올리는 것이다.
- https://m.blog.naver.com/skinfosec2000/221282525919
- https://www.lunasec.io/docs/blog/spring-rce-vulnerabilities/
- https://svrforum.com/itnews/222674
기본키 전략, 자연키 vs 인조키
자연 키(natural key)는 주민등록번호, 이메일, 상품 코드처럼 비즈니스에서 원래 의미를 가진 값을 기본 키로 쓰는 것이고, 인조 키(surrogate key)는 자동 증가 숫자나 UUID처럼 의미 없이 식별만을 위해 만든 값이다.
| 자연 키 | 인조 키 | |
|---|---|---|
| 장점 | 별도 컬럼이 필요 없고, 값 자체로 중복을 막는다 | 값이 바뀌지 않고, 짧고 단순해 조인과 인덱스에 유리하다 |
| 단점 | 비즈니스 규칙이 바뀌면 키가 바뀌고, 참조하는 모든 테이블을 수정해야 한다 | 비즈니스상 유일성을 따로 보장해야 한다 |
링크된 글들의 결론은 대체로 기본 키는 인조 키로 두고, 자연 키 후보에는 UNIQUE 제약을 거는 것이다. 영원히 바뀌지 않을 것 같던 값도 정책이나 법 때문에 바뀌거나 개인정보로 분류되어 저장할 수 없게 되는 경우가 있기 때문이다. JPA 관점에서도 Long 타입 인조 키와 @GeneratedValue 조합이 가장 다루기 쉽다.
- https://stackoverflow.com/questions/590442/deciding-between-an-artificial-primary-key-and-a-natural-key-for-a-products-tabl
- https://sqlstudies.com/2016/08/29/natural-vs-artificial-primary-keys/
- https://rampart81.github.io/post/surrogate_key_vs_natural_key/
- https://www.databasejournal.com/ms-sql/sql-server-natural-key-verses-surrogate-key/
- https://www.mssqltips.com/sqlservertip/5431/surrogate-key-vs-natural-key-differences-and-when-to-use-in-sql-server/
- https://ncucu.me/26
- https://multifrontgarden.tistory.com/180
- https://bunhere.tistory.com/45
Spring Boot YAML
Spring Boot는 application.properties와 함께 application.yml을 지원한다. YAML은 계층 구조를 들여쓰기로 표현하므로 같은 접두어가 반복되는 설정이 짧아진다. 리스트는 -로, 맵은 들여쓴 키로 쓰고, @ConfigurationProperties로 List나 Map 타입 필드에 바인딩할 수 있다.
1
2
3
4
5
6
7
app:
servers:
- dev.example.com
- prod.example.com
timeout:
connect: 3s
read: 10s
주의할 점은 YAML 파일을 @PropertySource로는 불러올 수 없다는 것과, 들여쓰기에 탭을 쓸 수 없다는 것이다. 같은 키를 properties와 yml에 모두 두면 properties가 우선한다.
- https://www.baeldung.com/spring-yaml
- https://www.baeldung.com/spring-boot-yaml-vs-properties
- https://www.amitph.com/spring-boot-yaml-to-list/
- https://www.baeldung.com/spring-boot-yaml-list
- https://docs.spring.io/spring-boot/docs/current/reference/html/application-properties.html
- https://kwonnam.pe.kr/wiki/springframework/springboot/properties
- https://herdin.github.io/2020/02/04/spring-property
- https://galid1.tistory.com/664
Spring Boot Multiple Profiles
application.properties에서는 파일을 분리하는게 더 자연스러운 방법이지만, application.yml에서는 그냥 ---으로 구분하는 것이 가장 자연스러운 방법인 것 같다. 파일로 분리해서 인식시키는 방법도 존재하나 기본값은 아니므로 별도의 설정이 필요하다. YAML설정이 아무리 길어지더라도 그냥 ---으로 구분하자.
Spring Boot 2.4부터 이 방식에 변화가 있었다. Spring 블로그에 따르면 문서 블록이 어느 프로파일에서 활성화될지 지정하는 키가 spring.profiles에서 spring.config.activate.on-profile로 바뀌었고, .properties 파일에서도 #---로 한 파일 안에 여러 문서를 둘 수 있게 되었다. 또 문서는 파일에 적힌 순서대로 처리되어 뒤의 문서가 앞의 값을 덮어쓴다.
1
2
3
4
5
6
7
8
9
server:
port: 8080
---
spring:
config:
activate:
on-profile: prod
server:
port: 80
참고로 application-{profile}.yml로 파일을 나누는 방식은 Spring Boot가 별도 설정 없이 기본으로 인식한다. 프로파일별 설정이 길어지면 파일을 나누는 편이 읽기 쉬울 수 있다.
- https://mkyong.com/spring-boot/spring-boot-profile-based-properties-and-yaml-example/
- https://stackoverflow.com/questions/52627023/how-can-i-create-profiles-with-spring-boot-yaml
- https://stackoverflow.com/questions/34063678/loading-multiple-yaml-files-using-configurationproperties
- https://1minute-before6pm.tistory.com/12
- https://www.oreilly.com/library/view/mastering-spring-boot/9781787127562/47bb7db6-fb7d-4d09-9bcc-7c1149f4f9e7.xhtml
- https://blog.yevgnenll.me/posts/multiple-profiles-inside-a-single-yaml-file
- https://stackoverflow.com/questions/23134869/spring-boot-how-to-use-multiple-yml-files
댓글
아직 댓글이 없습니다