ラック・セキュリティごった煮ブログ

セキュリティエンジニアがエンジニアの方に向けて、 セキュリティやIT技術に関する情報を発信していくアカウントです。

【お知らせ】2021年5月10日~リニューアルオープン!今後はこちらで新しい記事を公開します。

株式会社ラックのセキュリティエンジニアが、 エンジニアの方向けにセキュリティやIT技術に関する情報を発信するブログです。(編集:株式会社ラック・デジタルペンテスト部)
当ウェブサイトをご利用の際には、こちらの「サイトのご利用条件」をご確認ください。

デジタルペンテスト部提供サービス:ペネトレーションテスト

プーチン大統領の所有船「GRACEFUL」に関する航行データの改ざんはいかにして行われたのか?AIS情報の改ざんを考える

f:id:lac_devblog:20220301165631p:plain

ペネトレーションテスターのしゅーとです。

先日、匿名ハッカーによる航行データの改ざんにより、プーチン大統領の所有するヨットの位置がウクライナ領土のスネーク島に座礁したように見せかける事件が発生しました。

本記事では世界で広く用いられているAIS(Automatic Identification System:船舶自動識別装置)の原理とセキュリティ上のリスクについて、実際に船舶に対してペネトレーションテストを行った私の知見をもとに解説します。

攻撃の内容について

数日前から本攻撃に関する情報が出ていたようですが、Ryan Gallagher氏のツイートによって世界中にこの情報が拡散されました。

ツイートには船上交通情報サービス「MarineTraffic」上での船舶「GRACEFUL」の航行情報が表示されています。航行情報ではGRACEFULの現在位置がウクライナ領のスネーク島となっており、目的地が「HELL」(地獄)に設定されています。ここで注目されたのがGRACEFULの所有者。このヨットは、プーチン大統領の所有船なのです

では実際にこのヨットはスネーク島で座礁しているのでしょうか。確実にこれを確認するためには目視、あるいはリアルタイムの衛星画像などでGRACEFULの位置を特定する必要があります。ただ現実的に考えればこの状況下でGRACEFULがスネーク島に座礁することは考えにくいため、偽情報と断定しても良さそうです。

この事件はロシアによるウクライナ侵攻に関連したサイバー攻撃のひとつと考えられますが、今回送出された偽情報では何かしらの安全を損なわせることはできないため、愉快犯または政治犯による犯行と思われます。今回は愉快犯として片づけられる影響しかないのですが、笑いごとで済ませられるものではありません。船舶の自動運転技術が現実となっていくなかで、このような攻撃は船舶事故に繋がる恐れがあります。

それでは手元で同じ偽情報を作ることで、この攻撃の脅威を実感しましょう。

AIS

MarineTrafficは、世界中のボランティアが沿岸に設置したAIS機器が受信したデータをもとに世界地図にマッピングするというサービスです。そこでの航行データの改ざんは情報ソースであるAISの仕組みを悪用するため、まずはAISについて説明します。
AISはVHF帯の電波を利用した、船舶を識別するための規格です。主に船舶間の衝突予防や遭難時の人命救助を目的として世界中の船舶に搭載されており、国際条約(SOLAS74)に基づき日本でも要件を満たす船舶への搭載が法律で義務付けられています。

f:id:lac_devblog:20220301152221j:plain https://www.kaiho.mlit.go.jp/soshiki/koutsuu/ais-info.html海上保安庁より引用)

海上保安庁の解説でもあるとおり、AISは船舶だけでなく陸上施設に設置されている場合があります。陸上施設は他の陸上局と協力しあい、世界中の船舶・航路情報、気象情報を船舶に送信し、また個別に船舶から航路情報などを受け取り、他の陸上局に共有します。

ここで重要になるのは情報の信頼性です。このAIS、気軽に情報を送受信できるかわりに、誰がその情報を送ったか、その情報は正しいか、信頼性を裏付けるものが何もないのです。

AISは先述した通りVHF帯を用います。VHF帯の電波を発生させる装置はソフトウェア無線(SDR)が発達した現代では数万円もあれば調達可能です。

下の動画は、廉価なソフトウェア無線機器とフリーソフトを用いて、AIS無線局から受信したAIS情報をマッピングしている様子です。

www.youtube.com

AISのメッセージフォーマットはITU-R M.1371で定義されています。もちろんソフトウェア無線を用いて偽のAISデータを送出してもいいのですが、直接ビットストリームを操作するのは手間です。そこで登場するのがテキストフォーマットのNMEA。多くのAIS機器および周辺ソフトウェアでは、シリアル通信やTCP/IP通信を用いたNMEA形式(NMEA 0183またはNMEA 2000)での入出力がサポートされています。そのためAIS機器にNMEAデータを入力することで、VHF電波を通じて他のAIS無線局に対してAIS情報を送信可能です。

次の項ではNMEAを用いたAISのなりすまし手法を説明していきます。

NMEA (NMEA 0183)

NMEAはASCII printableなテキストフォーマットで、AISのほかにもGPS装置とのやりとりにおいても広く使われます。以下にNMEAデータの例を示します。

!AIVDM,1,1,,A,13RhLp801;QjL>0DD38:t?w@2D7k,0*3E

NMEA規格はプロプライエタリであるものの仕様は広く知られており、特にgpsdのドキュメントが非常に参考になります。

gpsd.gitlab.io

NMEAには複数のメッセージフォーマットが存在しますが、中でも船舶に関するメッセージはAIVDO/AIVDMフォーマットに該当します(自船情報はAIVDOメッセージ、他船情報はAIVDMメッセージと呼ばれる)。

さらにAIVDMにも様々なメッセージタイプがあります。中でも今回のような偽情報で使われるものはタイプ1とタイプ5です。

  • タイプ1 - Position Report Class A
    船舶の状態を示します。メッセージには当該船舶の状態(停泊中/移動中)、座標、速度、角度などが含まれます。

  • タイプ5 - Static and Voyage Related Data
    船舶の情報を示します。メッセージには当該船舶の名前、船舶タイプ、船体の大きさ、目的地などが含まれます。

タイプ1に似たものとしてタイプ2、タイプ3があります。しかし状況によって異なる使われ方をされるだけでほぼ同じなので今回は省略します。

どちらのタイプにおいても共通となるのはMMSI(海上移動業務識別コード)です。MMSIは電話番号のようなものであり、船舶・陸上局1つ1つに固有です。AISはMMSIをIDとして扱い、複数タイプのデータを1つの船舶に紐づけます。

偽のAIVDMメッセージを作成し送信する

それでは上記の仕様を参考にAIVDMメッセージを作成しAISに送信してみます。といっても実際のAIS機器に偽の通信を発するのは国内では電波法違反なので、あくまでシミュレーションとしてPC上で動作する、AISを解釈可能なナビゲータに送信することにします。

!不正な電波の送信は絶対にしないでください!

今回利用するナビゲータはOpenCPNです。OpenCPNはTCPサーバを待ち受け、ネットワーク上のホストからNMEAデータを受信することで画面上の地図に受信したAIS情報をプロットすることができます。

opencpn.org

f:id:lac_devblog:20220301151528p:plain
OpenCPNの画面

起動すると簡素な世界地図が表示されます。デフォルトでは詳細な地図(海図)が搭載されていないので、細かい地図を表示したい場合は地図情報をインターネット上から入手してインポートできます。

次にAIVDMメッセージを作成する環境の準備です。NMEAは各種情報を6bitエンコードする必要があります。幸いにもaislibというPython製のエンコードツールが公開されているので簡単に作成できます。

github.com

テストコードを参考に、適当なパラメータでNMEAデータが作れるか確認します。

$ python3
Python 3.8.10 (default, Sep 28 2021, 16:10:42)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import aislib
>>> aismsg = aislib.AISPositionReportMessage(
...     mmsi = 237772000,
...     status = 8,
...     sog = 75,
...     pa = 1,
...     lon = (25*60+00)*10000,
...     lat = (35*60+30)*10000,
...     cog = 2800,
...     ts = 40,
...     raim = 1,
...     comm_state = 82419
... )
>>> ais = aislib.AIS(aismsg)
>>> payload = ais.build_payload(False)
>>> print(payload)
!AIVDM,1,1,,A,13RhLp801;QjL>0DD38:t?w@2D7k,0*3E

簡単に作れました。メッセージ作成時の引数や意味についてはツールのソースコードやgpsdのドキュメントを参照してください。

最後に必要なのは攻撃対象であるGRACEFULの船舶情報。なりすましのためには正しいMMSIとIMO(船舶番号)が必要です。これは国際機関であるITUの登録情報を参照することで正確な情報が得られます。

Ship Station Description

これで準備はできました。今回送信するメッセージは今回の事件とほぼ同じ情報に設定しますが、少しオリジナリティを出して船舶ステータスを釣り状態にしましょう。以下は送信するメッセージに含めるパラメータの抜粋で、太字となっているものが偽の情報です。

  • タイプ1

    • MMSI: 273294110
    • ステータス: 釣り
    • 緯度/経度: 45°58.020 / 31°40.800 (スネーク島)
    • 速度: 100ノット(190km/h)
  • タイプ5

    • MMSI: 273294110
    • IMO: 1011551
    • コールサイン: FCKPTN
    • 船舶名: GRACEFUL
    • 船舶タイプ: 軍用艦船
    • 目的地: HELL

パラメータをもとにNMEAデータを送信

エンコードツールを用いて偽データを作成します。実行した結果、以下のデータが作成されました。

  • タイプ1
    !AIVDM,1,1,,A,144`S7W0?`R(略)JCFM:t?wp0D7k,0*47`

  • タイプ5
    !AIVDM,1,1,,A,544`S7P0?KmtH<e1@p0M84<(略)2R1C300000000000000000,2*7B

この2つのNMEAデータをAISを模したナビゲータに送信すると・・・

f:id:lac_devblog:20220301152852p:plain
偽情報を受信したときのAIS機器の表示

表示のとおり、GRACEFULが今回の偽情報と同じスネーク島に位置し、状態が「漁ろう中」となっていることを確認できました。

今回は実際の電波としては送信しておらず、あくまでシミュレーション上のものでしたが、仮に送信した場合は他のAIS機器の画面でスネーク島にGRACEFULが表示されます。

今回の攻撃の経路について

冒頭ツイートで紹介されているMarineTrafficは、世界中のボランティアが沿岸に設置したAIS機器が受信したデータを世界地図にマッピングするというサービスです。

現在のMarineTrafficでのGRACEFULの航行情報は、「1087 RA2FG」というAIS機器が受信したものをソースとしています。

f:id:lac_devblog:20220301153042p:plain
2022/03/01当時の航行情報

この機器の詳細ページを確認すると、当該AIS機器はロシアのカリーニングラードに存在することがわかります。

f:id:lac_devblog:20220301152130p:plain
AIS機器の所在

攻撃当時に表示されているAISソースがこの機器だったかは不明ですが、仮にそうだった場合、攻撃者はこのAISに対して不正な電波を送信した可能性があります。

まとめ

検証の結果、AISはプロトコル上、誰でもなりすましが可能であることを示しました。今回はMarineTrafficのような比較的影響の小さいサービスを狙ったものでしたが、この攻撃が実際の船に行われた場合の影響は甚大です。実際、AISのなりすましは貿易制裁逃れのための船舶情報の隠蔽や、軍事的な作戦(他国を偽情報で惑わせる)のために世界中で何度も行われており、船舶セキュリティの大きな問題となっています。

実証実験中の自動運航船はAIS以外の様々なセンサーで安全を担保するようなのであまり大きな心配はしていませんが、これからの航行システムは攻撃を前提とした設計をすべきでしょう。 またMarineTrafficのようなボランティアの設置したAISの情報を無条件に信頼してマッピングするサービスは、偽情報が蔓延っていると考えたほうが良さそうです。