지도를 묻는 질의어가 그대로 SQL 명령이 되어버린 자리

지도를 묻는 질의어가 그대로 SQL 명령이 되어버린 자리

분류: CVE · 웹·서버 · SQLi [정보성] · CVE-2023-25157

덱. 중국 보안 기업 Knownsec의 404 Team이 오픈소스 지리정보 서버 GeoServer에서 SQL 인젝션 취약점 CVE-2023-25157(및 자매 취약점 CVE-2023-25158)을 분석했습니다. 지리 데이터 조회 표준인 OGC 필터 언어를 실제 데이터베이스 질의문으로 바꾸는 계층에서, 사용자가 넣은 값이 이스케이프 없이 SQL 문자열에 그대로 이어붙었습니다. 공식 패치는 이미 배포돼 있습니다.

리드

표준 질의 언어를 시스템 내부 언어로 “번역”하는 계층은 어디에나 있습니다. GraphQL을 내부 REST 호출로 바꾸는 계층, ORM이 객체 조건을 SQL로 바꾸는 계층, 그리고 이번 사례처럼 OGC(Open Geospatial Consortium, 지리정보 국제 표준 기구) 필터 언어를 SQL로 바꾸는 계층이 그렇습니다. 이런 번역 계층은 두 언어 사이를 잇는 역할을 하다 보니, “여긴 이미 상위 파서가 걸러줬겠지”라는 가정이 쌓이기 쉽고, 정작 최종 SQL 문자열을 조립하는 지점에서 이스케이프 책임이 비어버리는 경우가 반복됩니다. 이번 GeoServer 사례는 그 번역 계층의 빈틈을 코드 레벨로 보여주는 사례입니다.

핵심 사실 요약

  • GeoServer는 자바로 작성된 오픈소스 지리공간 데이터 서버로, Spring Framework 위에서 동작하며 지리 데이터 처리에 GeoTools 라이브러리를 씁니다. GeoServer는 Web Feature Service(WFS)·Web Map Service(WMS) 프로토콜의 일부로 OGC Filter 표현언어와 OGC 공통질의언어(CQL, Common Query Language)를 지원하며, Web Coverage Service(WCS)를 통한 이미지 모자이크(ImageMosaic) 조회에서도 CQL을 지원합니다.
  • CVE-2023-25157과 자매 취약점 CVE-2023-25158은 모두 이 OGC 질의 기능에서 발생하는 SQL 인젝션입니다. 근본 원인은 여러 필터·함수(PropertyIsLike, strEndsWith, strStartsWith, FeatureId, jsonArrayContains, DWithin 등)가 사용자가 넣은 조건 값을 SQL 질의문에 이스케이프 없이 그대로 이어붙이는 지점이 있다는 것입니다. 조건은 필터·함수마다 다르게 걸립니다 — 예를 들어 PropertyIsLike 필터는 String(문자열) 필드에 대해 관계형 데이터베이스 기반 스토어와 함께 쓰이거나, encode 함수가 켜진 PostGIS DataStore, 또는 인덱스를 관계형 DB에 저장하는 이미지 모자이크와 함께 쓰일 때 문제가 됩니다. GeoTools 라이브러리 자체의 PropertyIsLike 처리는 원문에 “완화책 없음(no mitigation)“으로 명시돼 있습니다.
  • 영향받는 버전은 GeoServer 2.21.4 미만, 그리고 2.22.0 이상 2.22.2 미만입니다(NVD 등록 정보 기준). GeoTools는 28.2·27.4·26.7·25.7·24.7 각각 미만입니다. 공식 패치는 두 프로젝트 모두 배포됐습니다.
  • 인증 요구 여부와 CVSS 점수는 원문 분석 글에는 명시돼 있지 않지만, NVD 등록 정보로 확인됩니다 — CVSS v3.1 기준점수 9.8(Critical), 벡터 AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H이며 인증 없이(PR:N) 원격에서 실행 가능합니다.
  • 원문이 디버거로 직접 추적한 호출 경로에 따르면, org.geotools.jdbcgetReaderInternal() 함수가 사용자 질의 입력을 처리해 selectSQL을 호출하여 SQL 질의문을 만듭니다. 이때 CQL_FILTER 조건이 있으면 FilterToSQL이 이 조건을 encodeToString(Filter)으로 SQL 문자열로 바꾸고, 그 결과가 이미 만들어진 SQL의 WHERE 절 뒤에 그대로 이어붙습니다. 최종적으로 JDBCFeatureReader가 이 문자열을 그대로 실행하면서 인젝션이 완성됩니다.
  • 패치는 두 갈래로 나갑니다. GeoTools 쪽 패치는 FilterToSQL.javaEscapeSql 모듈과 escapeBackslash 필드를 추가해 SQL 인젝션을 방어합니다. GeoServer 쪽 패치는 jdbcconfig 모듈(ConfigDatabase.java, OracleDialect.java)의 속성 필드·삽입 구문을 조정합니다.

짧은 논평

이 사례에서 눈여겨볼 대목은 취약점이 한 곳이 아니라는 점입니다. PropertyIsLike 외에도 strEndsWith·strStartsWith·FeatureId·jsonArrayContains·DWithin까지, 데이터베이스 종류(PostGIS·Oracle 등)와 설정 조합에 따라 조건은 다르지만 뿌리는 같습니다 — OGC 필터를 SQL로 옮기는 지점에서 이스케이프 처리가 중앙집중되어 있지 않았다는 것입니다. 필터·함수 하나씩 패치하는 대신 FilterToSQL이라는 공통 변환 지점에 EscapeSql 모듈을 심은 것도 그래서일 것입니다. 서로 다른 진입점 여러 개가 같은 시점에 함께 드러났다는 건, 개별 버그라기보다 번역 계층 설계 자체의 구조적 빈틈이었다는 신호로 읽힙니다. 저희가 다른 인젝션 계열 사례에서도 반복해서 보는 패턴입니다 — 입력을 다른 언어로 옮겨 적는 계층은, 그 계층 하나에서 이스케이프를 책임지지 않으면 진입점 수만큼 구멍이 납니다.

References / 참고자료

  1. Knownsec 404 Team, “GeoServer SQL Injection Vulnerability Analysis (CVE-2023-25157)” — 이 글이 재구성한 원 분석. 디버거로 추적한 호출 경로와 GeoServer·GeoTools 양쪽 패치 내용을 다룸. https://medium.com/@knownsec404team/geoserver-sql-injection-vulnerability-analysis-cve-2023-25157-413c1f9818c3

이 글은 위 원 분석을 우리 관점에서 다시 쓰고 짧은 논평을 더한 정보성 초안입니다. 특정 문장·코드·스크린샷을 그대로 옮기지 않았으며, 작동하는 재현 절차나 완성형 SQL 페이로드는 싣지 않았습니다. ⚠️미확인 표시 항목은 발행 전 독립 팩트체크에서 확증·정정되어야 합니다.