こんにちは!新人IT担当者の皆さん、日々のインフラ管理や開発、本当にお疲れ様です。「セキュリティ」という言葉を聞くだけで、なんだか難しそうな専門用語の壁にぶつかって頭が痛くなっていませんか?
今回は、工場のプラントやビルの空調などを裏で支える「OT(制御システム)/SCADA(スカダ)」の世界と、仮想通貨などで耳にする「ブロックチェーン(分散型台帳技術)」を組み合わせた、ちょっと最先端でワクワクするセキュリティのお話です。
難しそうに聞こえるかもしれませんが、身近な「家の鍵と防犯カメラ」に例えて一歩ずつ優しく紐解いていきますので、ぜひリラックスして読んでいってくださいね!
—
1. そもそもSCADAってなに? なぜログの「改ざん」が怖いの?
皆さんが普段使っているパソコンやスマホのセキュリティは「データの機密性(見られないこと)」が重視されがちですが、工場やインフラを動かすOT(Operational Technology)の世界では、何よりも「安全性と可用性(システムが止まらないこと)」が命です。
ここで登場するのが SCADA(Supervisory Control and Data Acquisition) です。これは、巨大なダムの水門を開け閉めしたり、発電所のタービンをコントロールしたりする「現場の司令塔システム」のこと。
家の鍵に例えてみましょう
想像してみてください。あなたの家の玄関には頑丈なスマートロック(SCADAシステム)がついていて、誰がいつ出入りしたかが「デジタル鍵の履歴帳(イベントログ)」に記録されますよね。
もし、泥棒(サイバー攻撃者)がこっそり家に侵入して、この「履歴帳」のページをビリッと破ったり、自分の都合のいいように「誰も入っていません」と書き換えてしまったらどうでしょう?
警察を呼んでフォレンジック(原因究明のための鑑識作業)をしようにも、「あれ? 誰も来ていないことになっている……」となってしまい、事件の真相が闇に葬られてしまいます。
OTの現場でサイバー攻撃や不正アクセスがあった場合、この「ログ(履歴)が本物であること」が証明できないと、原因追究ができず、再発防止策も立てられなくなってしまうのです。
—
2. 従来のログ管理の弱点と、ブロックチェーンによる解決
従来のシステムでは、SCADAが吐き出すイベントログは、現地のサーバーや専用のデータベース(DB)に保存されていました。
しかし、ここに大きな弱点があります。
もし、システムに侵入した悪意ある攻撃者(あるいは不正を企む内部の人間)が、そのサーバーの管理者権限まで奪ってしまったらどうなるでしょうか? DBのデータを直接書き換えて、自分たちの足跡をきれいさっぱり消し去ることは、実は技術的にそれほど難しくありません。これでは「ログの信頼性」が揺らいでしまいますよね。
そこで登場するのが「ブロックチェーン」です!
ブロックチェーンと聞くと「ビットコイン?」と身構えてしまうかもしれませんが、要するに「みんなで同じ日記帳を分散して持ち合い、一度書いたページは絶対に後から書き換えられない(改ざんしようとすると全員に見破られる)魔法のノート」だと思ってください。
SCADAが検知した重要なイベント(例:「A系統のバルブが強制的に閉じられました」など)を、このブロックチェーンの仕組みを使って記録しておけば、たとえシステムの管理者が不正をしようとしても、過去の履歴を書き換えることは絶対に不可能になります。これこそが、今回お伝えしたい「DLT(分散型台帳技術)による監査ログの不変性確保」です。
—
3. 【実践】SCADAログをブロックチェーン風に保護するコード例
それでは、百聞は一見にしかず。新人エンジニアの皆さんが現場でイメージしやすいように、Pythonを使って「ログの改ざんを検知できるシンプルなチェーン構造(ブロックチェーンの仕組みのミニチュア版)」を書いてみましょう。
ブロックチェーンのキモは、前のデータのハッシュ値(暗号技術で作る指紋のようなもの)を次のデータに含めることです。途中で1文字でもログを書き換えると、それ以降の指紋がすべて一致しなくなるため、一発で改ざんが見破れます。
import hashlib
import json
from datetime import datetime
class ScadaLogBlock:
"""SCADAの1つのイベントログを表すブロッククラス"""
def __init__(self, index, timestamp, device_id, event_message, previous_hash):
self.index = index # ブロックの番号
self.timestamp = timestamp # 発生時刻
self.device_id = device_id # 対象のOTデバイスID (例: VALVE_01)
self.event_message = event_message # イベント内容
self.previous_hash = previous_hash # 一つ前のブロックのハッシュ値(鎖の役割)
self.hash = self.calculate_hash() # 現在のブロックのハッシュ値
def calculate_hash(self):
"""ブロック内のデータから一意のハッシュ値(指紋)を計算する関数"""
block_string = json.dumps(
{
"index": self.index,
"timestamp": str(self.timestamp),
"device_id": self.device_id,
"event_message": self.event_message,
"previous_hash": self.previous_hash,
},
sort_keys=True,
)
# SHA-256という強力な暗号アルゴリズムを使用します
return hashlib.sha256(block_string.encode()).hexdigest()
class ScadaAuditBlockchain:
"""監査ログをチェーン状につなげて改ざんを防ぐ簡易ブロックチェーン"""
def __init__(self):
self.chain = [self.create_genesis_block()]
def create_genesis_block(self):
"""最初の一番最初のブロック(ジェネシスブロック)を作る"""
return ScadaLogBlock(
0, datetime.now(), "SYSTEM", "Genesis Block", "0" * 64
)
def get_latest_block(self):
"""チェーンの最後尾にあるブロックを取得する"""
return self.chain[-1]
def add_log_event(self, device_id, event_message):
"""新しいSCADAのイベントログをブロックとして追加する"""
previous_block = self.get_latest_block()
new_block = ScadaLogBlock(
index=previous_block.index + 1,
timestamp=datetime.now(),
device_id=device_id,
event_message=event_message,
previous_hash=previous_block.hash,
)
self.chain.append(new_block)
print(
f"[INFO] ログ追加成功: ブロック #{new_block.index} ({device_id}: {event_message})"
)
def is_chain_valid(self):
"""チェーン全体を検証し、ログが改ざんされていないかチェックする"""
for i in range(1, len(self.chain)):
current_block = self.chain[i]
previous_block = self.chain[i - 1]
# 1. 現在のブロックのハッシュが正しいか再計算してチェック
if current_block.hash != current_block.calculate_hash():
print(
f"[ALERT] 改ざん検知!ブロック #{current_block.index} のデータが書き換えられています!"
)
return False
# 2. 前のブロックのハッシュと正しく繋がっているかチェック
if current_block.previous_hash != previous_block.hash:
print(
f"[ALERT] 整合性エラー!ブロック #{current_block.index} のチェーンが切断されています!"
)
return False
print("[OK] 監査ログの整合性チェック完了: 改ざんは検出されませんでした。")
return True
# --- 実際に動かしてみるシミュレーション ---
if __name__ == "__main__":
# 監査システムを起動
audit_trail = ScadaAuditBlockchain()
# OT環境でイベントが発生したと仮定してログを記録
audit_trail.add_log_event("VALVE_A01", "緊急停止バルブが作動しました")
audit_trail.add_log_event(
"TURBINE_B02", "回転数が許容値を超過しました (警告)"
)
# 正常性の確認
print("\n--- 改ざんチェック(正常時) ---")
audit_trail.is_chain_valid()
# --- 【攻撃シミュレーション】 悪意ある攻撃者が過去のログをこっそり書き換えた場合 ---
print(
"\n--- [攻撃シミュレーション] 攻撃者が過去のログをこっそり書き換える ---"
)
audit_trail.chain[1].event_message = (
"バルブは正常に稼働していました(偽装工作)"
)
# 再度、整合性をチェック
print("\n--- 改ざんチェック(異常検知後) ---")
audit_trail.is_chain_valid()
このコードを実行してみるとわかりますが、途中のログを書き換えた瞬間に、Pythonの is_chain_valid() メソッドが鮮やかに [ALERT] を発報します。ブロックチェーンの根幹は、まさにこの「過去との繋がりを数式でガチガチに固める」というシンプルなアイディアから成り立っているのです。
—
4. 現場で導入する際のリアルな課題と現実解
「なるほど、ブロックチェーンを使えばログの改ざんが防げるのか!じゃあ明日の朝から全部のSCADAに導入しよう!」……と意気込みたいところですが、そこはシビアなOT・IoTの世界。現場特有のハードルが存在します。
1. レイテンシ(処理遅延)の問題
- パブリックなブロックチェーン(Ethereumなど)は、合意形成(コンセンサス)に数秒〜数分かかることがあります。ミリ秒単位のリアルタイム性が求められる制御システムにおいて、この遅延は致命的になり得ます。
2. デバイスのスペック不足
- 工場の現場で何十年も動いている古いPLC(プログラマブルロジックコントローラー)や末端のIoTセンサーには、重たい暗号処理やブロックチェーンのノードを動かすパワーがありません。
現実的なアプローチ(一歩ずつ進めるための知見)
そのため、実際の現場では以下のような工夫が取られます。
- 末端のデバイスで直接ブロックチェーンを動かすのではなく、エッジサーバーやセキュアなゲートウェイ集約層でログをバッチ処理し、プライベート(許可型)ブロックチェーンや、軽量なDLT(Hyperledger FabricやQuorumなど)に書き出す。
- 全てのデータをブロックチェーンに入れるのではなく、「重大なアラートや設定変更の監査証跡」といった、いざという時に法的・セキュリティ的な証明が必要になるクリティカルなログに絞ってハッシュをアンカー(固定)する。
—
5. おわりに:セキュリティの第一歩を踏み出したあなたへ
いかがでしたでしょうか?
「OT環境における分散型台帳技術(DLT)による監査ログの不変性確保」という、一見すると呪文のように難しそうなテーマも、「絶対に破られないデジタルな鍵付きの履歴帳」という例えと、実際のコードの仕組みを紐解いていけば、本質はとてもシンプルで理にかなっていることが分かっていただけたかと思います。
セキュリティの世界は広大で、覚えることも次から次へと出てきますが、焦る必要は全くありません。一つひとつの技術の「なぜそれが必要なのか(背景)」と「どうやって守るのか(仕組み)」をこうして噛み砕いていけば、必ず頼れるIT・セキュリティエンジニアになれます。
一歩ずつ、着実に、一緒に学んでいきましょう!次の記事でも、現場で役立つ実践的な知識を分かりやすくお届けしますね。
コメント