
ICS/SCADA용 고상호작용 OPC UA 허니팟 — 다중 프로파일(석유 및 가스, 수도, 전력망), 실시간 프로세스 시뮬레이션, 세션별 위협 점수 산정, SIEM 통합(syslog/CEF/webhooks/Elasticsearch)을 제공합니다. .NET 8과 LibUA 기반으로 구축되었습니다.
ICS/SCADA 환경을 위한 고상호작용 OPC UA 허니팟입니다. 프로토콜 에뮬레이터가 아닌 완전한 OPC UA 바이너리 스택인 LibUA를 기반으로 구축되었습니다. 실시간 프로세스 값, 포괄적인 위협 탐지, SIEM 연동 로깅을 통해 여러 산업 프로필에 걸쳐 현실적인 산업 제어 시스템을 시뮬레이션합니다.
0xAJStrike가 제작했습니다.
📄 발표: Read the Plant like a Blueprint — 이 도구가 개발된 SecTor 2026 발표 자료입니다 (OPC UA 공격 표면, 허니팟 설계, 라이브 데모).
대부분의 ICS 허니팟(Conpot, GRFICSv2)은 부분적인 프로토콜 에뮬레이션만 제공합니다. OpcUaTrap은 보안 채널 협상, 세션 수명 주기, 구독, 히스토리, 그리고 모든 서비스 집합을 포함한 완전한 OPC UA 바이너리 프로토콜을 구현합니다. 실제 익스플로잇 도구와 스캐너(OpalOPC, Nmap OPC UA 스크립트)는 프로덕션 시스템과 마찬가지로 이 허니팟과 상호작용합니다.
| 낮음 | 중간 | OpcUaTrap | |
|---|---|---|---|
| 프로토콜 | 배너만 | 부분 에뮬레이션 | 완전한 실제 스택 |
| 세션 상태 | 없음 | 기본 | 전체 수명 주기 |
| 주소 공간 | 정적 / 비어 있음 | 소수의 노드 | 100–130개의 현실적인 노드 |
| 구독 | 아니오 | 아니오 | 예 — 실시간 데이터 푸시 |
| 익스플로잇 복원력 | 충돌 | 부분적 | 전체 프레임워크에서도 견딤 |
docker run -d --name opcuatrap -p 4840:4840 \
-e OPCUATRAP_PROFILE=oil-gas \
-v opcuatrap-data:/data \
ghcr.io/0xajstrike/opcuatrap:latest
이제 허니팟은 opc.tcp://<host>:4840에서 실행됩니다. -e OPCUATRAP_PROFILE=water-treatment(또는 power-grid)로 시설을 전환하세요. 이미지는 멀티 아키텍처(amd64 + arm64이므로 Raspberry Pi에서도 실행됨)이며, 비루트로 동작하고, 인증서와 NDJSON 로그를 opcuatrap-data 볼륨에 영속화합니다. 전체 Docker 세부 사항(Compose, 모든 환경 변수)은 배포 → Docker에 있습니다.
.NET 9.0 SDK 이상 — 번들된 LibUA가 최대 net9.0까지 멀티 타기팅하므로 소스에서 빌드하는 데 필요합니다. 허니팟 자체는 .NET 8 런타임에서 실행됩니다. (Docker를 사용하는 경우 필요하지 않습니다 — 이미지가 내부적으로 모든 것을 빌드합니다.)
LibUA — OPC UA 스택입니다. OpcUaTrap은 여러 OPC UA CVE에 대한 심층 방어 제한과 선택적 허니팟 기만 응답을 추가한 약간 수정된 포크(0xAJStrike/LibUA, nauful/LibUA의 포크)를 대상으로 빌드됩니다.
두 저장소를 공통 상위 디렉터리 아래에 나란히 클론하세요:
git clone https://github.com/0xAJStrike/OpcUaTrap.git
git clone https://github.com/0xAJStrike/LibUA.git
예상 레이아웃 (OpcUaTrap은 프로젝트 파일 기준으로 ../../../LibUA/NET-Core/LibUA/LibUA.csproj를 참조하며, 즉 LibUA는 OpcUaTrap 옆에 위치함):
parent/
├── OpcUaTrap/ # this repo
└── LibUA/ # the fork, cloned as a sibling
dotnet build src/OpcUaTrap/OpcUaTrap.csproj
# Oil & gas profile (default, port 4840)
dotnet run --project src/OpcUaTrap
# Water treatment profile
dotnet run --project src/OpcUaTrap -- --profile water-treatment
# Power grid profile
dotnet run --project src/OpcUaTrap -- --profile power-grid
# Custom port
dotnet run --project src/OpcUaTrap -- --port 7718
# Custom log directory
dotnet run --project src/OpcUaTrap -- --log-dir /var/log/opcuatrap
서버는 약 400ms 만에 시작되며 즉시 프로세스 값을 시뮬레이션하기 시작합니다.
프로필은 src/OpcUaTrap/Profiles/에 있는 JSON 파일입니다. 각 파일은 시설 정체성, 전체 주소 공간, 태그 분류, 시뮬레이션 규칙 및 강화 구성을 정의합니다.
| 프로필 | --profile | 시설 | 노드 | 벤더 식별 정보 |
|---|---|---|---|---|
oil-gas | (기본값) | PetroVista 중앙 처리 시설 | ~120 | Schneider Electric SCADAPack 57x |
water-treatment | water-treatment | Cascade 시립 정수 처리장 | ~100 | Rockwell Automation ControlLogix |
power-grid | power-grid | Ridgeline 138kV 송전 변전소 | ~130 | ABB RTU560 |
PetroVista Central Processing Facility/
Site_Information/
Wellheads/ WH_101 – WH_104 (pressure, temp, flow, choke position)
Separators/ SEP_HP_201, SEP_LP_202 (pressure, level, setpoints)
TankFarm/ TK_OIL_301, TK_OIL_302 (level, alarms, inlet/outlet valves)
PumpStations/ PMP_XFER_401 (speed, discharge pressure, start/stop commands)
CompressorStation/ COMP_501 (RPM, vibration, discharge temp, load %)
Pipelines/ PL_EXPORT_601 (pressure, flow, block valve)
SafetySystems/ ESD (status, shutdown valves, trigger/reset methods)
FireAndGas (gas detectors %LEL, flame detectors)
Utilities/ Instrument air, fuel gas, power generation
Cascade Municipal Water Treatment Plant/
Site_Information/
RawWaterIntake/ Flow, turbidity, pH, temp, intake pumps, isolation valve
Coagulation/ Rapid mix, alum dose rate and setpoint
Flocculation/ Slow mixer, polymer feed rate and setpoint
Sedimentation/ Basin levels, turbidity, sludge blanket, scrapers
Filtration/ 4 filters — differential pressure, turbidity, backwash status
Disinfection/ Primary/secondary chlorination, ammonia feed (chloramine)
ClearWell/ Finished water storage — level, turbidity, pH, Cl2 residual
Distribution/ High-service pumps, pressure zones, elevated tank level
SafetySystems/ ESD, chlorine/ammonia leak detectors and isolation valves
Utilities/ Power, backup generator, SCADA system status
Ridgeline 138kV Transmission Substation/
Site_Information/
HV_Bus (138kV)/ Phase voltages, line voltage, frequency, MW/MVAR/PF
CB-101 main breaker, CB-102 bus tie (status, SF6, trip/close)
Transformers/ T1 & T2, 50 MVA each — voltage, current, oil temp, winding temp,
LTC tap position (1–17), loading %, tap raise/lower commands
LV_Bus (13.8kV)/ Bus voltage, frequency, total MW/MVAR/PF
Feeders/ F1 Residential, F2 Industrial, F3 Commercial, F4 Hospital/Critical
(current, MW, MVAR, recloser ops, trip/close commands)
CapacitorBanks/ CAP-1 (energized), CAP-2 (standby) — 5 MVAR each
ProtectionRelays/ SEL-351S overcurrent, SEL-387 differential, SEL-421 distance
All have _ENABLED flag — disabling them is a critical attack target
DC_System/ 125VDC station battery — voltage, SOC, charger status, ground fault
SafetySystems/ 86 Lockout relay (trip-all-breakers), ESD
SCADA_RTU/ ABB RTU560 status, EMS comm link, historian connection
| # | 정책 | 모드 |
|---|---|---|
| 1 | None | None |
| 2 | Basic256Sha256 | Sign |
| 3 | Basic256Sha256 | SignAndEncrypt |
| 4 | Aes128_Sha256_RsaOaep | SignAndEncrypt |
프로필은 hardening.authentication.allowedSecurityPolicies 설정을 통해 제공되는 정책을 제한할 수 있습니다.
사용 시 경고를 트리거하는 미리 심어둔 취약한 자격 증명입니다. appsettings.json에 정의되어 있습니다.
| 사용자 이름 | 비밀번호 | 경고 수준 |
|---|---|---|
operator | op3rator! | HIGH |
admin | admin123 | CRITICAL |
engineer | Welcome1 | CRITICAL |
readonly | readonly | MEDIUM |
svc_historian | h1st0rian | HIGH |
인증 동작은 프로필에 따라 다릅니다 — oil-gas는 selective 모드(알 수 없는 자격 증명 거부)를 사용하고, water-treatment는 accept-all을 사용합니다.
| 작업 | 응답 | 로깅 |
|---|---|---|
| Browse | 전체 주소 공간 반환 | 100회 초과 작업 시 열거 탐지 |
| Read | 실시간 시뮬레이션 값 반환 | 대량(20개 초과 노드) 또는 중요 태그가 아닌 한 조용히 처리 |
| Write | Good 반환 — 값은 1초 후 되돌려짐 | 로깅 + 태그 분류에 따라 위협 점수 산정 |
| Call (ESD/Lockout 메서드) | Good 반환 — 아무 일도 일어나지 않음 | CRITICAL 경고, 위협 점수 +30 |
| History Read | 30일간의 사인파 데이터 반환 | 1000개 초과 포인트 대량 유출 탐지 |
| Subscribe (중요 태그) | 실제 구독 반환 | CRITICAL 경고, 위협 점수 +20 |
| 허니토큰 로그인 | 세션 수락됨 | HIGH/CRITICAL 경고 |
| 익명 인증 | 프로필에 따라 수락 또는 거부 | 로깅됨 |
태그는 프로필별로 분류됩니다. 분류는 쓰기 위협 점수를 결정합니다.