티스토리 뷰
개요
오늘도 어김없이 출근해서 한 주 동안 쌓인 보안장비 로그들을 확인했다.
평소보다 WAF 장비에 이벤트가 2천 건 정도 증가해있었는데,
공격자 IP 대역이 사내 서버로 확인되었고, URL도 모두 동일했다.
특이점이 있는 것 같아 해당 URL과 이벤트 특성을 공부해보기로 했다.
차단된 이벤트
사내 서버 출발지의 이벤트였고, 목적지 또한 사내 서버였다.
공격자 IP로 확인되는 출발지 IP는 Zabbix 서버로,
Zabbix는 대강 자산의 모니터링을 편리하게 수행할 수 있는 오픈소스 플랫폼이구나~정도 알고 있었다.
(예전에 자빅스라는 발음을 듣고 철자를 Jabbix로 여러 번 작성했는데 그걸 틀린 게 왜 부끄러웠는지 모르겠다.)
🔥 특징 1
보통 1분 간격으로 차단 이벤트가 발생했다.
🔥 특징 2
/actuator/health라는 엔드포인트만 호출하고 있다.
차단 원인
숙련된 담당자들이라면 1초만에 간파할 수 있는 내용이겠지만...
위와 같은 내용으로 미루어 보았을 때, 다음과 같은 결론을 간단하게 내릴 수 있다.
"내부 Zabbix 서버가 자산을 모니터링하기 위해서 /actuator/health 엔드포인트를 호출했지만,
WAF의 특정 룰에 의해 관련 호출이 차단되었다는 것"이다.
궁금증
내부 IP 구나! 차단에서 예외해야겠다! 라고 생각하면
참 마음이 편하겠지만 내 뇌는 아래와 같은 내용들을 너무나 궁금해했다.
아래 3가지의 내용을 가벼운 지식 정도로 조사해서 정리해두려 한다.
🔸 Q1. /actuator/health란?
해당 엔드포인트는 Zabbix에서만 쓰는(호출하는) 것인가?
🔹 A1. Spring Boot 제공 기능
일단 Zabbix actuator health 같이 검색을 해보면 게시물이 많으므로 Zabbix에서 자주 사용하는 방법은 맞다.
아래와 같이 Zabbix에서 사용 가능한 템플릿도 있다.
- 템플릿
https://github.com/mjp91/zabbix-spring-boot-actuator/blob/master/zbx_spring_boot_actuator_template.xml - 사용법
https://www.zabbix.com/documentation/4.0/en/manual/xml_export_import/templates
알아보던 도중 Spring Boot Actuator라는 용어가 눈에 들어오고,
Spring Boot을 통해 만들어진 애플리케이션에서 제공하는 Actuator 기능이라는 점을 알 수 있다.
그 중 /actuator/health 엔드포인트를 통해 애플리케이션의 상태 체크가 가능하고,
모니터링 시스템과 주로 연동시켜 정상/장애 여부를 손쉽게 모니터링하게 해준다고 한다.
아래처럼 gradle에 추가해주면 된다고 함
# build.gradle 예시
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-actuator'
}
🔸 Q2. /actuator, 왜 차단해뒀을까?
Actuator는 모니터링 편의성을 위한 엔드포인트인데,
어떤 취약/위험성이 존재하기에 해당 엔드포인트는 WAF에 차단 룰로 등록되어 있을까?
🔹 A2-1. env - 환경변수 중요정보 노출
DB 접속 정보, API 키 등의 정보는 보통 소스코드에 하드코딩 하지 않는다.
Spring Boot는 application.yml 또는 application.properties 파일을 통해 ${}로 환경변수를 참조하는데,
보통 아래처럼 환경변수를 통해 직접적으로 소스코드를 통해 중요정보가 노출되지 않도록 한다.
spring:
datasource:
url: jdbc:mysql://localhost:3306/mydb
username: ${DB_USER}
password: ${DB_PASSWORD}
하지만 /actuator/env 호출을 통해 위와 같은 환경변수에 대한 값을 얻을 수 있어
외부로 노출 시 아래 캡처와 같이 중요정보가 노출될 수 있다.
$ curl 'http://localhost:8080/actuator/env/com.example.cache.max-size' -i -X GET
🔹 A2-2. shutdown - 웹서비스 강제 중지
shutdown 엔드포인트를 활성화하고 접근제어 없이 오픈되어 있다면,
웹 애플리케이션을 강제 중지시킬 수 있어 가용성에 심각한 침해가 발생할 수 있다.
대부분 비활성화 되어있는 엔드포인트로, 발생하기 드문 케이스이기는 하다.
$ curl 'http://localhost:8080/actuator/shutdown' -i -X POST
🔹 A2-3. health - 리소스 정보 제공
application.yml 또는 application.properties 파일에 misconfiguration이 발생하면,
공격자는 /actuator/health를 통해 많은 정보를 얻을 수 있다.
misconfiguration이 발생한다는 것은 무조건 잘못되었다는 것은 아니며,
위에서 작성했듯 별다른 보안조치 없이 여러 설정을 오픈했을 때이다.
특히 application 설정 파일에서는 show-details를 ALWAYS로 설정하는 경우가 그러하다.
# application.yml
management:
endpoint:
health:
show-details: always # detailed 모드 (상세 정보 항상 표시)
endpoints:
web:
exposure:
include: health
# application.properties
management.endpoint.health.show-details=always
management.endpoints.web.exposure.include=health
DB 설정이 되어있는 경우 DB 종류도 노출될 수 있으며
디스크의 남은 공간 및 경로, 특정 서비스의 UP/DOWN 여부도 알 수 있다.
특정 구성요소가 DOWN 상태인 경우를 노려 공격을 수행할 수도 있으며,
남은 공간이 별로 없는 것을 확인하고 리소스 소모 공격, DDoS 공격 등을 수행할 수 있다.
🔸 Q3. Actuator 안전하게 사용하기
내부 모니터링을 위한 서버에서는 /actuator/health를 사용하면서,
외부 공격자로부터의 접근은 막는 방법에는 무엇이 있을까?
🔹 A3-1. 화이트리스트 방식 endpoint 운영
web 방식에서 health 엔드포인트는 기본적으로 expose되어 있다.
JMX 방식은 모두 expose되어 있으므로 불필요한 엔드포인트를 비활성화해야 한다.
여기서 JMX 방식이란 웹 방식처럼 HTTP를 통해 시스템 상태를 모니터링하는 것이 아니라
Java 내부 프로토콜을 통해 모니터링을 수행하는 방식이다.
# application.yml
management:
endpoints:
enabled-by-default: false # 모든 엔드포인트 비활성화
web:
exposure:
include: [] # 웹에서 노출되는 엔드포인트 없음
jmx:
exposure:
exclude: ["*"] # JMX로 노출되는 엔드포인트 없음
endpoint:
health:
enabled: true # health 엔드포인트 활성화
env:
enabled: true # env 엔드포인트 활성화
# application.properties
management.endpoints.enabled-by-default=false # 기본 설정을 비활성화 (모두 disable)
management.endpoint.[endpoint_name].enabled=true # [endpoint_name] 엔드포인트만 활성화
management.endpoints.web.exposure.include=env,health # env, health 엔드포인트를 웹에서 노출 (include)
management.endpoints.jmx.exposure.exclude=* # 모든 엔드포인트를 제외 (exclude)
▪ exposure vs enabled 주의점
- 예시1. exposure(include)를 []로 비워두고 enabled를 true로 활성화하면,
내부 코드에서 actuator를 통해 모니터링이 가능하다. - 예시2. exposure(include)를 ["health"]로 지정하고 enabled를 false로 비활성화하면,
웹 노출로 지정되었지만 엔드포인트 자체가 비활성화되어 404 Not Found가 발생한다.
🔹 A3-2. /actuator 경로명 및 포트 변경
/actuator가 노출될 가능성을 낮추기 위해 경로명과 포트를 변경할 수도 있다.
# application.yml
management:
server:
port: 포트번호
endpoints:
web:
base-path: "monitor" # /actuator가 아닌 /monitor로 변경
# application.properties
management.endpoints.web.base-path=/monitor # /actuator가 아닌 /monitor로 변경
management.endpoints.web.base-path=/
management.endpoints.web.path-mapping.health=monitor # /health만 /monitor로 변경 (나머지는 /[endpoint_name])
management.server.port=포트번호 # Actuator의 사용 포트번호 변경
여기서 특히 web.base-path=/와 web.path-mapping.health=monitor로 변경하는 경우
web.base-path=monitor로 설정하는 것(/actuator -> /monitor)과는 다른 결과가 나온다는 것을 인지해야 한다.
예시는 아래와 같다.
🔹 A3-3. WAF 등 보안 시스템을 활용
Actuator로의 접근에 모니터링 시스템의 IP만 제외하고 모두 차단하는 방법도 있기는 하다.
(내일 출근해서 적용할 방법..ㅎㅎ)
가능하다면 하나의 방법만을 고수하기 보다는
소스코드 단 설정과 보안정책을 함께 적용해서 다층으로 보안성을 가져가면 좋을 것 같다.
참고자료
- [토스테크, Spring Boot Actuator의 헬스체크 살펴보기] https://toss.tech/article/how-to-work-health-check-in-spring-boot-actuator
- [우아한 기술 블로그, Actuator 안전하게 사용하기] https://techblog.woowahan.com/9232/
- [Spring docs, env] https://docs.spring.io/spring-boot/api/rest/actuator/env.html#env.entire
- [Spring docs, shutdown] https://docs.spring.io/spring-boot/api/rest/actuator/shutdown.html#shutdown
- Thanks for comming.
- 오늘은
- 명이 방문했어요
- 어제는
- 명이 방문했어요