티스토리 뷰

반응형

개요

오늘도 어김없이 출근해서 한 주 동안 쌓인 보안장비 로그들을 확인했다.
평소보다 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에서 사용 가능한 템플릿도 있다.

알아보던 도중 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만 제외하고 모두 차단하는 방법도 있기는 하다.
(내일 출근해서 적용할 방법..ㅎㅎ)
가능하다면 하나의 방법만을 고수하기 보다는
소스코드 단 설정과 보안정책을 함께 적용해서 다층으로 보안성을 가져가면 좋을 것 같다.



참고자료

반응형
댓글
반응형
Recent Post.
Recent Reply.
Thanks for comming.
오늘은
명이 방문했어요
어제는
명이 방문했어요