知らずのうちにやっていそうな危ないSSH,SFTPの使い方を平易にお知らせします。本稿は、システム設計・保守者へのセキュリティ注意喚起です。SFTP、SSH、SCPというキーワードにピンときた方は読んでみてください。
この記事は、Cyber-sec+ Advent Calendar 2024 の 9 日目の記事です。
はじめに
サイバーディフェンス研究所の安井です。長年制御システムを開発してきた経験から制御システムセキュリティ向上に取り組んでいます。
制御システム業界も徐々にセキュリティ意識が高まっており、ftpやtelnet等の平文のプロトコルは減り、代替として、SFTPやSSH等の暗号化したプロトコルへの移行が進んでいる気がします。 良いことだと思いますが、暗号化したから安心と思っていませんか?
今回は、「正しい使い方をできていなければ、逆にセキュリティを弱くしている可能性すらある。」そんなお話しです。
セキュリティの基本概念である相手が本物かを確認する「真正性の確認」が、実装や運用では見落とされている事が多いのでないかと思い本ブログを書きました。 特に、単純なパスワード認証処理でSFTPを実装している方は危険かも知れません。
対象読者
- サイバーセキュリティに関心がある方。
- システム設計・保守に関わる方。
- 特に、制御システムでSFTPを使おうとしている設計・保守者。
FTPとSFTP
FTP(File Transfer Protocol)は、平文のファイル転送プロトコルであり、ユーザとパスワードが通信パケット上に平文で書かれています。従って、パケットを盗聴されてしまうとユーザとパスワードがばれてしまいます。転送ファイル内容もばれます。
SFTP(SSH File Transfer Protocol)は、暗号化したSSH(Secure Shell)を基盤としたファイル転送プロトコルです。適切に暗号化されていれば安全です。
telnetとSSH
telnet は、平文のリモートでShell操作を行うプロトコルであり、ユーザとパスワードが通信パケット上に平文で書かれています。従って、パケットを盗聴されてしまうとユーザとパスワードがばれてしまいます。Shell操作内容もばれます。
SSH(Secure Shell)は、暗号化したリモートでShell操作を行うプロトコルです。適切に暗号化されていれば安全です。
本当か?
さて、上記のSFTP, SSHの説明は本当でしょうか? 暗号化についてだけ説明されていますが、これだけの理解でSFTP,SSHを使用しているとしたら危険かもしれません。
なぜでしょうか? 何かが足りないのです。
通信が暗号化されているのは本当です。従って通信パケットを盗聴されても適切に暗号化されていれば解読困難で現実的に安全といえるでしょう。 しかし、通信相手が偽装されていたらどうでしょう?偽装された相手を正規な相手と思い込み、ユーザ・パスワードを知らせてしまったら危険であることは明白ではないでしょうか?
偽装相手と接続する事など無いと思うかも知れませんが、身の回りを確認してみてください。攻撃されてしまうと、簡単に、偽装相手にユーザ・パスワードを提供してしまうSFTP実装やSSH運用が見つかるのでは無いでしょうか?
どれだけ危険か
何かが足りないとどれだけ危険か、中間者攻撃で説明します。 中間者攻撃とは、通信の途中に攻撃者が介入し、正規のサーバになりすます攻撃です。この攻撃により、クライアントは気づかずに偽のサーバと通信してしまい、重要な情報を攻撃者に渡してしまう可能性があります。
例えば: [ クライアント → (攻撃端末) → サーバ ]
このような状況では、クライアントは正規のサーバと通信していると思っていますが、実際は攻撃端末と通信しています。
以下のネットワークに中間者攻撃を行う例で説明します。
何かが足りないSFTPクライアントが、Firewallと物理警備の弱いネットワークを介してSFTPサーバとパスワード認証でSFTP通信をしていたとします。 物理警備の弱いネットワークを発見した攻撃者が、攻撃端末を設置し、SFTPクライアントからのSFTP通信を攻撃端末上の偽装SFTPサーバで受信する中間者攻撃を仕掛けたとします。
すると、以下のようにSFTPクライアントからSFTPサーバ宛のSFTP通信は、攻撃端末の偽装SFTPサーバに対して送られ、ユーザとパスワードが攻撃者に知られてしまいます。
次に攻撃者は、一般にSFTPサーバとSSHサーバは共用されていることを利用し、下図のように 取得したユーザとパスワードを用いてSFTPサーバにSSHでログインします。この際、送信元IPアドレスを偽装することでFirewallをすり抜けます。
攻撃者はSSHでサーバのShell操作が可能になるため、更なる攻撃が可能となります。
何が足りなかったか 真正性確認
何が足りなかったのでしょうか?
SSH, SFTP通信を安全に行うためには暗号化が重要ですが、それだけでは不十分です。通信相手が本当に正しい相手なのかを確認する「真正性確認」を行うことも同様に重要です。これは、「あなたは本当に私が通信したいと思っている相手ですか?」と確認するプロセスです。
真正性確認は、オンラインでの「身分証明書の確認」のようなものです。暗号化だけでは、誰かになりすました偽の相手と安全に会話しているだけかもしれません。真正性確認により、通信相手が本物であることを確認することで、安心して情報をやり取りすることができるのです。
ユーザ・パスワード認証は、サーバがクライアントの真正性を確認する仕組みです。ユーザ・パスワードに変わる公開鍵認証も同様にサーバがクライアントの真正性を確認する仕組みです。一方で、クライアントがサーバの正しさを確認する仕組みがホストキーによる真正性確認です。
クライアントの真正性確認(ユーザ・パスワード認証や公開鍵認証)は誰もが気にするところですが、それほどには、サーバの真正性確認(ホストキー)は気にされていない気がします。
このホストキーによる真正性の確認が足りなかったのです。 本稿は、このホストキーによる真正性確認の実施を当たり前と思う人が増えていただきたく注意喚起するものです。
SSHでの危険なホストキーの使い方例
SSHを使ったことがある方なら、初めてサーバにアクセスしたときに、下図のように接続を続けていいかyes/noで聞かれることをご存知だと思います。
$ ssh user@192.168.1.101
---
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])?
これはサーバのホストキーのハッシュ値であるfingerprintを信じて良いか質問しています。 このとき、yesを入力した場合、 信用できる正しいサーバとして~/.ssh/known_hostsにホストキーが保存されます。 以降、同じサーバに接続する場合は、~/.ssh/known_hostsに登録されたホストキーをもとに自動でサーバの真正性確認が行われます。
以上のことを知っているという方も多いと思います。その方は、 以下のメッセージも見たことがあるのではないでしょうか?
$ ssh user@192.168.1.101
---
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
これは、以前192.168.1.101に接続したことがある場合、192.168.1.101が前回とは違うサーバに変わっていた時に出るメッセージであり、丁寧にも「誰かが盗聴しているかもしれない!中間者攻撃!」と注意喚起してくれています。 上記のメッセージが出て即座に接続失敗してしまいます。
このメッセージを見た時、無条件にknown_hostsから当該IPアドレスのホストキーを削除して、再度ssh接続する習慣がある人もいるのではないでしょうか? 特にシステム開発・保守者で、複数システム環境において同一ネットワーク体系でSSHを繰り返す人には、日常的な行為になっているのではないでしょうか?
ほとんどの場合は問題ないのでしょうが、もしかすると今回は、注意喚起のとおり、中間者攻撃を受けているかもしれません。その場合、パスワード入力してしまうと、ユーザ・パスワードを取得されてしまいます。
対策は、注意喚起メッセージが表示したら、無条件にknown_hosts削除して再度ssh接続するのでなく怪しく無いか確認するということです。
ちなみに、
$ ssh -o StrictHostkeyChecking=no user@192.168.1.101
とすることでホストキーのチェックをスルーすることが可能です。サーバが中間者攻撃を受けた偽装サーバでもスルーしてしまうので、無条件に使っているとすると危ないかも知れません。
補足として、sftp, scpコマンドはsshと同じ認証の仕組みのため同様な注意が必要です。
もし常にチェックするのが非現実的だとしても、さすがに実運用中のシステム環境ぐらいは、ホストキーをチェックする運用とすることはできるのではないでしょうか?
ここまでは、人間が運用する際に注意すれば良い話しです。
SFTPでの危険なホストキーの使い方例
ここからは、運用ではなくプログラミングの注意です。
SFTPは、SSH File Transfer Protocolという名前のとおり、SSHをもとにしているため認証の仕組みはSSHと同じです。このためSSHでの解説と同じリスクがあります。 しかし、筆者はSFTPの方が更にリスクが大きいのはないかと考えています。それには2つの理由があります。
理由1 簡易なプログラムで自動実行されていることが多い
SFTPはシステムのファイル転送機能で使われます。このため、プログラミングされた処理から自動実行されることが多いです。
プログラマーが、接続の簡便さを優先するあまり、以下例のようにサーバの身元確認であるホストキーのチェックをスルーしていることがあります。
XXXXXX.set_missing_host_key_policy(paramiko.AutoAddPolicy())
これは、pythonのコード例ですが、ホストキーのチェックをスルーするコードとなっています。世の中にはサンプルコードで溢れていますが、初心者向けで最低限の接続ができればよくセキュリティの考慮までしていないサンプルには、このようなコードを見かけるので注意が必要です。
このコードで、かつパスワード認証をしている場合、中間者攻撃を受けて偽装サーバと接続してしまった場合、ユーザ・パスワードを取得されてしまいます。 ここでは、pythonの例を挙げましたが、他のプログラム言語でもホストキーのチェックをスルーするコーディングは可能です。
理由2 FTP時代のセキュリティ対策が継承されていない可能性がある
FTP時代には、平文であるが故にほとんどの人が盗聴のリスクを知っていました。そのため、盗聴されても致命的な問題とならないような様々な対策がとられていました。 クローズドなネットワークでしか使わないことが代表的な対策であり、その他にも、最小権限のFTP専用ユーザを使うなどの対策もとられていたのではないでしょうか? これら対策が適切に取られていた場合、万一通信盗聴されユーザ・パスワードを取得されたとしても、Shellの操作までには至らず被害は最小限に抑えられます。
FTPからSFTPに移行する際に、これらの設計思想が引き継がれていればよいのですが、暗号化だからと安心してしまって引き継いでいないとすると、ユーザ・パスワードを取得されてしまった時のリスクが高くなってしまっているかもしれません。 LinuxやWindowsのSFTPのユーザ・パスワードは、デフォルト設定ではSSHのユーザ・パスワードと共用されているものです。SFTPのユーザ・パスワードが窃取された場合、SSHでのShell操作を可能となるため、更なる攻撃につながる可能性が高いです。
対策
-
教育 暗号化だけで安心せずサーバの真正性確認も重要であることを周知する。
-
保守・運用 サーバの真正性確認で警告が表示した場合は、本物のサーバか疑う。
-
設計 無条件でホストキーを信用するコーディングはせず、ホストキーでの真正性確認は必ず行うコードとする。
補足として、パスワード認証の代わりに公開鍵認証を使用することで、さらにセキュリティを高めることができます。公開鍵認証は、鍵のペアを使用して認証を行うため、今回紹介した攻撃を受けてもパスワードは漏洩しません。鍵を取得されないよう対策しておけば、ホストキーによるサーバの確認と組み合わせることで、より強固なセキュリティを実現します。
まとめ
SFTPとSSHの真正性確認としてホストキーの重要性を説明しました。
SFTPの実装について注意喚起のよびかけを行いました。
対策として、真正性確認の重要性を伝え、公開鍵認証方式の優位性を補足しました。
最後に
本稿は、SFTP,SSHを例に、相手が本物か相互に確認するというセキュリティの基本事項をとりあげました。 基本事項であっても実際に皆が使いこなせているかは別の話しだと思います。
暗号化された通信を使用するだけでは十分ではありません。サーバの身元を確認することが、安全を確保する上で非常に重要です。ホストキーによる確認は、この安全確保の重要な一歩なのです。
今後ますますFTPから暗号化ファイル転送に移行する制御システムは増えていくと思われます。
本稿が、そのような人の目にとまることで、攻撃を受ける前に対策が打てる手助けになれば幸いです。
なお、他の通信プロトコルにおいてもサーバの真正性確認を行わない実装となっていれば、偽装サーバと接続されてしまう可能性があります。
通信の暗号化、認証というセキュリティ対策の実装において、サーバの真正性確認もチェックするのがあたりまえという認識が広まればいいなと思います。
補足 公開鍵認証とするだけでいいのか? 2024.12.11追記
寄せらたコメントから「公開鍵認証」とだけすればいいのだと誤解釈する方が一定数いそうな懸念がありそうなため補足します。 気づくきっかけ提供いただきありがとうございました。
本文にも記載したとおり、ユーザ・パスワード認証、公開鍵認証ともに、あくまで サーバがクライアントの真正性を確認する仕組みであり、クライアントがサーバの真正性を確認する仕組みではありません。 したがって、公開鍵認証としてもサーバの真正性を確認していなければ、本稿に記載の攻撃手順で偽装サーバに接続されてしまいます。
パスワードを取得されなければよいというだけであれば、公開鍵認証とするだけでよいのですが、それだけでサーバの真正性を確認していなければ、本稿で説明したサイバー攻撃により偽装サーバに接続されてしまいます。その場合、どのようなリスクがあるのか、2つの例で紹介します。
-
SFTPでファイルをPUTする処理を行なっていた場合、情報漏洩につながるリスク 人間によるSFTP PUT操作であれば、偽装サーバに接続したら、操作中に、何かおかしいな?と気づきやすいとは思います。しかし、プログラムで自動実行していると、気づかぬまま偽装サーバにファイルを送ってしまうことが考えられます。たとえば、定期的な機密情報転送やシステム一括のバックアップファイル転送を行なっていたら危険そうだということが想像できるのではないでしょうか?
-
SFTPでファイルをGETする処理を行なっていた場合、クライアント上のファイルを不正な内容で書き換えられるリスク 人間によるSFTP GETの操作であれば、偽装サーバに接続したら、操作中に、何かおかしいな?と気づきやすいとは思います。しかし、プログラムで自動実行していると、気づかぬまま偽装サーバから攻撃者が用意した任意の内容のファイルを取得して、クライアント上のファイルを書き換えられてしまうリスクがあります。 詳細な手口は記載しませんが、攻撃者からすると、任意の内容のファイルを送り込めることがわかれば、そこを糸口に、更なる攻撃を試行することになります。クライアントに脆弱性があれば侵入され任意のコマンド実行をされることもあります。
実際に攻撃がおこなわれているシーンを想像したとき、偽装サーバを用意して中間者攻撃を行なっている時点で、一定の攻撃ノウハウを持った攻撃者であることが想定されるため、上記のような攻撃が試行されることも想像できます。そのように考えると「公開鍵認証」とするだけでは当人が思ったような防御効果には至らない可能性があると思い、補足を追記しました。