ESPILON-CTF-2026-Writeups/OT/Tachibana_SCADA/solve/solve.md
Eun0us 6a0877384d [+] Writeups v2 — sync solves, real points, scoreboard stats, cleanup
- Remove undeployed challenges: Phantom_Byte, Cr4cK_w1f1, Lain_Br34kC0r3 V1,
  Lain_VS_Knights, Lets_All_Love_UART, AETHER_NET, Last_Train_451, Web3/
- Sync 24 solve/ files from main CTF-Espilon repo
- Update all READMEs with real CTFd final scores at freeze
- Add git-header.png banner
- Rewrite README: scoreboard top 10, edition stats (1410 users, 264 boards,
  1344 solves), correct freeze date March 26 2026
2026-03-27 21:27:45 +01:00

2.5 KiB

Tachibana SCADA -- Solution

Overview

OPC-UA server simulating Tachibana General Laboratories' SCADA system. The server allows anonymous connections (SecurityPolicy None) and contains a hidden namespace with Eiri Masami's backdoor methods.

Steps

1. Connect Anonymously

Connect to opc.tcp://HOST:4840/tachibana/ without credentials. The server accepts anonymous connections -- a common OT misconfiguration.

from asyncua import Client
client = Client("opc.tcp://HOST:4840/tachibana/")
await client.connect()

2. Discover Namespaces

Read the Server.NamespaceArray to discover all registered namespaces:

  • ns=0: OPC-UA standard
  • ns=1: Server internal
  • ns=2: urn:tachibana:scada (public SCADA data)
  • ns=3: urn:tachibana:eiri:kids (hidden!)
ns_array = await client.get_namespace_array()

3. Browse Public Namespace (ns=2)

Standard SCADA data: power distribution, cooling systems, Wired Interface Array. Note Resonance_Hz = 7.83 (Schumann resonance breadcrumb).

4. Browse Hidden Namespace (ns=3)

Navigate to EiriMasami folder:

  • KIDS_Project/ contains variables: SubjectCount=0, Protocol7_Version="7.0.0-alpha", Activation_Key="????????"
  • Backdoor/ contains two methods: Authenticate and ExtractResearchData

5. Analyze Method Signatures

Read the InputArguments property of each method:

  • Authenticate(username: String, key_hash: ByteString) -> session_token: String
  • ExtractResearchData(session_token: String, project_id: UInt32) -> data: String

The key_hash description says: "16-byte truncated SHA-256 of the project name"

6. Derive Credentials

  • username: eiri (from namespace URI urn:tachibana:eiri:kids)
  • key_hash: SHA256("KIDS")[:16] (KIDS = project name from the namespace)
import hashlib
key_hash = hashlib.sha256(b"KIDS").digest()[:16]

7. Authenticate

Call the Authenticate method with the derived credentials. Returns a hex session token valid for 5 minutes.

8. Extract Protocol Seven

Call ExtractResearchData with the session token and project_id=7 (from Protocol7_Version = "7.0.0-alpha" -- project number 7).

Returns the flag.

Key Insights

  • The namespace URI urn:tachibana:eiri:kids directly contains the username ("eiri") and hash source ("kids")
  • Protocol7_Version = "7.0.0-alpha" hints that project_id = 7
  • Anonymous OPC-UA access is a real-world ICS misconfiguration
  • Method argument descriptions provide hints about the expected input format

Flag

ESPILON{31r1_k1ds_pr0t0c0l_s3v3n}

Author

Eun0us