メモリ攻撃を回避するため、米国家安全保証局はRust、C#、Go、Java、Ruby、Swiftを推奨し、CとC++は脇に置く

メモリ攻撃を回避するため、米国家安全保証局はRust、C#、Go、Java、Ruby、Swiftを推奨し、CとC++は脇に置く

多くの開発者にとって、これはC#、Go、Java、Ruby、Rust、Swiftへの移行を意味する可能性がある。

最終更新 2022/11/16 7:31
沙漠尽头的狼
読了目安 9 分
カテゴリ
シェア
タグ
.NET C# Java Go セキュリティ

最初に米国国家安全保障局の記事を紹介します:NSA、ソフトウェアメモリ安全性問題に対する保護方法に関するガイダンスを公開

本稿は2つの記事の翻訳です。1つ目は米国国家安全保障局が「ソフトウェアメモリ安全性」に関するサイバーセキュリティ情報表の解説、2つ目はメモリ安全性とは何か、なぜ重要なのかを解説します。

第1部 メモリ攻撃を避けるため、米国国家安全保障局はRust、C#、Go、Java、Ruby、Swiftを推奨、CとC++は対象外に

本記事は翻訳(Google翻訳使用)です。

原文著者:Liam Tung

原文タイトル:NSA to developers: Think about switching from C and C++ to a memory safe programming language

原文リンク:https://www.zdnet.com/article/nsa-to-developers-think-about-switching-from-c-and-cpp-to-a-memory-safe-programming-language/

画像: Getty Images/iStockphoto

多くの開発者にとって、これはC#、Go、Java、Ruby、Rust、Swiftへの移行を意味するかもしれません。

米国国家安全保障局(NSA)は、開発者に対し、メモリ安全言語(C#、Go、Java、Ruby、Rust、Swiftなど)への移行を促し、コードをリモートコード実行やその他のハッキングから保護するよう求めています。

上記の言語の中で、JavaはエンタープライズおよびAndroidアプリケーション開発で最も広く使用されている言語であり、SwiftはiOSアプリ開発によりトップ10言語に入っています。システムプログラミングでは、RustがCおよびC++の代替として注目されています。

「NSAは、組織に対して、可能であれば、メモリ保護をほとんどまたはまったく提供しないプログラミング言語(C/C++など)からメモリ安全言語への戦略的移行を検討するよう推奨します。メモリ安全言語の例としては、C#、Go、Java、Ruby、Swiftがあります」とNSAは述べています。

同諜報機関は、GoogleとMicrosoftの最近の調査を引用し、Chrome とWindowsでそれぞれ、70%のセキュリティ問題がメモリに関連しており、その多くがCおよびC++の使用によるもので、メモリベースの脆弱性が発生しやすいとしています。

なお:サイバーセキュリティ、クラウド、コーディング:2023年に需要をリードするこれら3つのスキル

NSAは「ソフトウェアメモリ安全性」サイバーセキュリティ情報表で次のように述べています。「悪意のあるサイバー行為者は、これらの脆弱性を利用してリモートコード実行やその他の悪影響を引き起こす可能性があり、通常はデバイスを危険にさらし、大規模なネットワーク侵入の第一歩となります。」

「CやC++といった一般的な言語は、メモリ管理において大きな自由度と柔軟性を提供する一方で、プログラマーがメモリ参照に必要なチェックを実行することに大きく依存しています。」

そのため、同機関は、アプリケーション開発でもシステムプログラミングでも、可能な限りメモリ安全言語を使用するよう推奨しています。

「NSAは、可能な限りメモリ安全言語を使用することを推奨します」と指摘しています。

多くの情報セキュリティ専門家はこのメモリ安全言語に関する議論に精通していますが、すべての開発者が精通しているわけではないかもしれません。しかし、これは何十年も存在する問題であることを考えると、おそらく彼らはそうすべきであり、Javaの創始者James Goslingが最近の議論で指摘したように、Javaがどのようにしてなぜ作られたかについても同様です。

もしあれば、NSAの文書は開発者に対して、メモリ安全言語への移行の背後にある技術的理由を明確でわかりやすい言葉で説明しています。メモリ安全性に関して最も議論されている言語はおそらくRustであり、CとC++の「代替」として主要な候補です。

Androidオープンソースプロジェクトに続き、Linuxカーネルは最近、RustをCに次ぐ第二言語として導入しました。これらのプロジェクトは古いC/C++コードを置き換えるものではありませんが、新しいコードではRustを好んで使用します。さらに、Microsoft Azure CTO Mark Russinovichは最近、すべての開発者に対し、新しいプロジェクトではCやC++ではなくRustを使用するよう呼びかけました

「これらのタイプのメモリ問題を利用することで、ソフトウェアの通常の使用では想定されていない制約を受けない悪意のある行為者は、プログラムに異常な入力を与え、予期しない方法でメモリにアクセス、書き込み、割り当て、解放する可能性があります」とNSAは説明しています。

しかし、RustとC/C++の議論で専門家が指摘しているように、単にメモリ安全言語を使用するだけでは、ソフトウェアにメモリエラーが導入されることをデフォルトで排除できません。さらに、言語は通常、メモリ安全言語で書かれていないライブラリを許可します。

「メモリ安全言語を使用しても、メモリ管理が完全にメモリ安全であるわけではありません。ほとんどのメモリ安全言語は、特定のタスクを実行するために、ソフトウェアが時々安全でないメモリ管理機能を実行する必要があることを認識しています。そのため、メモリ安全ではないと見なされる機能を使用でき、プログラマーが安全でない可能性のあるメモリ管理タスクを実行できるようにするものもあります」とNSAは述べています。

「一部の言語では、メモリ安全でないものはすべて明示的に注釈を付ける必要があり、プログラマーとプログラムのレビュアーにそれが安全でないことを認識させます。メモリ安全言語は、メモリ安全でない言語で書かれたライブラリも使用できるため、安全でないメモリ機能を含む可能性があります。これらのメモリ安全でないメカニズムを含める方法は、固有のメモリ安全性を覆しますが、メモリ問題が存在する可能性のある場所を特定するのに役立ち、これらのコード部分に対する追加のレビューを可能にします。

なお: サイバーセキュリティ:2023年に懸念すべき新しいこと

NSAは、一部のメモリ安全言語はパフォーマンスコストを伴う可能性があり、開発者は新しい言語を学ぶ必要があると指摘しています。また、開発者が非メモリ安全言語を強化するために取れる対策もあると述べています。例えば、GoogleのChromeチームは、C++を強化する複数の方法を模索していますが、これらもパフォーマンスオーバーヘッドを伴います。当面の間、C++はChromeのコードベースに残るでしょう。

NSAは、メモリ問題を発見するために静的および動的アプリケーションセキュリティテストを推奨しています。また、コードの実行場所を制限するControl Flow Guard (CFG) などのメモリ強化方法の探索も推奨しています。同様に、アドレス空間レイアウトランダム化 (ASLR) とデータ実行防止 (DEP) の使用も推奨しています。

第2部 メモリ安全性とは何か、なぜ重要なのか?

本記事は翻訳(Google翻訳使用)です。

出典:https://www.memorysafety.org

原文タイトル:What is memory safety and why does it matter?

原文リンク:https://www.memorysafety.org/docs/memory-safety/

メモリ安全性は、一部のプログラミング言語が持つ特性であり、メモリの使用方法に関連する特定の種類のエラーをプログラマーが導入するのを防ぎます。メモリ安全性の脆弱性は多くの場合セキュリティ問題であるため、メモリ安全言語は非メモリ安全言語よりも安全です。

メモリ安全言語には、Rust、Go、C#、Java、Swift、Python、JavaScriptが含まれます。メモリ安全でない言語には、C、C++、アセンブリ言語が含まれます。

メモリ安全性の脆弱性の種類

メモリ安全性の脆弱性を理解するために、多数のユーザーのToDoリストを管理するアプリケーションの例を考えます。メモリ安全でないプログラムで発生する可能性のある、最も一般的なメモリ安全エラーのいくつかの種類を見ていきます。

範囲外の読み取りと書き込み

10項目のToDoリストがあり、11番目の項目を要求するとどうなるでしょうか?明らかに何らかのエラーを受け取るべきです。負の最初の項目を要求した場合も、エラーを受け取るべきです。

これらの場合、メモリ安全でない言語では、リストの有効な内容の直前または直後に存在するメモリ内容をプログラマーが読み取ることを許可する可能性があります。これは範囲外読み取りと呼ばれます。リストの最初の項目の前のメモリは、他の誰かのリストの最後の項目である可能性があります。リストの最後の項目の後のメモリは、他の誰かのリストの最初の項目である可能性があります。このメモリにアクセスすることは、深刻なセキュリティ脆弱性になります!プログラマーは、要求する項目のインデックスをリストの長さと慎重にチェックすることで範囲外読み取りを防ぐことができますが、プログラマーは間違いを犯します。デフォルトでこのようなエラーからユーザーを保護するメモリ安全言語を使用する方が良いでしょう。

メモリ安全言語では、コンパイル時にエラーが発生するか、実行時にクラッシュします。プログラムのクラッシュは深刻に見えますが、ユーザーがお互いのデータを盗めるようにするよりはましです!

密接に関連する脆弱性は範囲外書き込みです。この場合、ToDoリストの11番目の項目または負の最初の項目を変更しようとするとします。今度は他の人のToDoリストを変更していることになります!

解放後使用

ToDoリストを削除し、そのリストの最初の項目を要求すると想像してください。明らかにエラーを受け取るべきです。すでに使わなくなったメモリから項目を取得できるべきではありません。メモリ安全でない言語では、プログラムがすでに完了したメモリを取得し、他の目的に使用できるようにします。メモリ内の位置には現在、他の人のToDoリストが含まれている可能性があります!これは解放後使用の脆弱性と呼ばれます。

メモリ安全性の脆弱性はどの程度一般的か?

非常に一般的です。最近の研究によると、iOSとmacOSの脆弱性の60〜70%はメモリ安全性の脆弱性です。Microsoftは、過去10年間に自社製品の全脆弱性の70%がメモリ安全性の問題であると推定しています。Googleは、Androidの脆弱性の90%がメモリ安全性の問題であると推定しています。広く悪用されている0-dayの分析では、悪用された脆弱性の80%以上がメモリ安全性の問題であることが判明しました1。

2003年のSlammerワーム(これはソフトウェア脆弱性の特別な測定方法であり、資格情報フィッシングなどの非常に一般的なものを含みません)はバッファオーバーフロー(範囲外書き込み)でした。WannaCryも同様です(範囲外書き込み)。iPhoneを狙ったTrident脆弱性は3つの異なるメモリ安全性の脆弱性(2つの解放後使用と1つの範囲外読み取り)を悪用しました。HeartBleedはメモリ安全性の問題(範囲外読み取り)です。AndroidのStagefrightも同様です(範囲外書き込み)。glibcのGhost脆弱性?その通りです(範囲外書き込み)。

CとCはメモリ安全ではないため、これらの脆弱性やその他の脆弱性が悪用されることが可能になります。CとCを多用する組織は、メモリ安全性の欠如に直接起因する多数の脆弱性を必然的に生み出します。これらの弱点は悪用され、病院反体制派衛生政策専門家に危険をもたらします。CとC++の使用は社会に不利であり、あなたの評判に不利であり、あなたの顧客に不利です。

メモリ安全でない言語に関連するその他の問題は?

メモリ安全でない言語は、安定性、開発者の生産性、アプリケーションのパフォーマンスにも悪影響を及ぼします。

メモリ安全でない言語はエラーやクラッシュが発生しやすい傾向があり、アプリケーションの安定性に大きく影響します。クラッシュがセキュリティに関係しない場合でも、ユーザーにとっては非常に悪い体験です。

さらに悪いことに、開発者はこれらのエラーを追跡するのが困難です。メモリ破壊は、エラーの実際の発生場所から遠く離れた場所でクラッシュを引き起こすことがよくあります。マルチスレッドが関与する場合、スレッドの実行時間のわずかな違いが他のエラーを引き起こし、エラーの再現がさらに困難になります。結果として、開発者はクラッシュレポートを何時間も見つめてメモリ破壊エラーの原因を特定する必要があります。これらのエラーは数か月間修正されない可能性があり、開発者はエラーが存在することを完全に確信しているものの、その原因と修正を見つける方法がわからないままになります。

最後に、パフォーマンスがあります。過去数十年間、CPUは1〜2年ごとに高速化すると期待できました。これはもはやそうではありません。代わりに、CPUはより多くのコアを搭載するようになりました。追加のコアを活用するには、開発者はマルチスレッドコードを記述する必要があります。

残念ながら、マルチスレッドはメモリ安全性の欠如に関連する問題を悪化させるため、CおよびCでマルチコアCPUを活用する取り組みは、しばしば困難です。例えば、Mozillaは最終的に(成功して)マルチスレッドのRustでシステムを書き換えるまで、FirefoxのC CSSサブシステムにマルチスレッドを導入しようと何度も試みましたが、いずれも失敗しました。

正しい前進の道は何か?

メモリ安全言語を使用しましょう!素晴らしい選択肢がたくさんあります。OSカーネルやWebブラウザを書いていますか?Rustを検討してください!iOSやmacOS向けの構築?Swiftが適しています。Webサーバー?Goは良い選択です。これらはほんの一例であり、他にも多くの優れたメモリ安全言語があります(そして他にも多くの素晴らしいユースケースの組み合わせがあります!)。

組織が使用するプログラミング言語を変更することは容易ではありません。それは採用時に求めるスキルを変えることを意味し、従業員の再教育を意味し、大量のコードの書き換えを意味します。それでも、長期的には必要であると信じているため、新しいプログラミング言語を採用する代わりの方法が成功していない理由を説明したいと思います。

安全でない言語を使用するとある程度の脆弱性が発生すると当然考えた場合、私たちが問いたい質問は次のとおりです。完全にプログラミング言語を変えることを強制されずに、このリスクを軽減するための技術はあるのか?答えは「はい」です。安全でない言語で書かれたプロジェクトがすべて同様に安全で信頼性が低いわけではありません。

安全でない言語の使用リスクを軽減できるいくつかのプラクティス:

  • 現代のC++イディオムを使用すると、より安全で信頼性の高いコードの生成に役立ちます
  • ファザーサニタイザーを使用して、エラーが本番環境に移る前にエラーを見つけるのに役立ちます
  • 脆弱性の悪用を困難にするエクスプロイト緩和技術を使用する
  • 権限分離により、脆弱性が悪用されても爆発半径が小さくなる

これらのプラクティスは、安全でない言語の使用リスクを意味のある形で軽減します。もし私たちが言語の変更を説得できず、CやC++を書き続けるつもりなら、これらのプラクティスの採用は必須です。残念ながら、それらもまた不十分です。

ブラウザやOSの開発者は、現代のC++イディオム、ファザーサニタイザー、エクスプロイト緩和技術、権限分離技術の最前線にいます。これは、冒頭でメモリ安全性問題の普遍性に関する統計を通じて強調したグループです。これらのチームはこれらの技術に投資しているにもかかわらず、安全でない言語を使用することで足かせをはめられています。大規模ハッキングコンテストpwn2ownでは、2019年にこれらの製品で悪用された脆弱性の半数以上がメモリ安全性の欠如によるものであり、1つの例外を除いて、すべての成功した攻撃は少なくとも1つのメモリ安全性脆弱性を悪用していました。

CとC++を放棄することは本当に可能か?

ここまでで、CやC++のような安全でない言語が私たちの製品における多くの安全性の根本原因であり、リスクを軽減するための対策をいくつか取れるものの、それを排除することには到底近づけないことをご理解いただけたと思います。これらすべてが、使用するプログラミング言語を変更し、数百万行のコードを生成することが圧倒的に大きなタスクであると感じさせるかもしれません。管理可能な部分に分割することで、進捗を始めることができます。私たちの目標は、大爆発的に世界を書き換えることではなく、リスクを軽減する上で進捗を達成することです。

まずは全く新しいプロジェクトです。これらの場合、メモリ安全言語を使用することを単に選択できます。これらのプロジェクトのリスクは最も低く、コードの書き換えから始める必要はありませんが、このようなプロジェクトでは通常、新しいプログラミング言語をサポートするためにテストやデプロイメントインフラの改善が必要です。これはChromeOSのCrosVM(OSの全く新しいコンポーネント)で採用されたアプローチです。

新しいプロジェクトがない場合、メモリ安全言語を使用する次の機会は、既存プロジェクトの新しいコンポーネントです。一部のメモリ安全言語は、CおよびC++コードベースとの相互運用(RustやSwiftなど)に対する一流のサポートを提供します。これには、ビルドシステムへの統合、および2つの言語間の境界を越えて渡す必要があるオブジェクトやデータの抽象化の構築が必要となるため、やや高い初期投資が必要です。WebAuthnがFirefoxの新しいコンポーネントとして実装されたとき、およびRustでLinuxカーネルモジュールを書くプロジェクトで、この戦略がうまく使用されました。

最初の2つのアプローチに共通するのは、どちらも新しいコードを扱うことです。これには、既存コードと明確に定義された相互作用点があるという利点があり、何も書き換えずに作業を開始できます。また、止血の機会も提供します。つまり、安全でない言語を使用する新しいコンポーネントがなければ、既存のコードを段階的に処理できます。メモリ安全言語の使用を開始する新しいコンポーネントが自然にないプロジェクトでは、採用はより困難です。

その場合、安全でない言語を安全言語に書き換えるための既存コンポーネントを探す必要があります。理想的には、すでに書き換えを検討しているコンポーネントを選択することです。パフォーマンス、セキュリティ、またはコードが保守しにくいためです。初めてのメモリ安全書き換えでは、可能な限り小さいスコープのものを選択し、プロジェクトを成功させ、できるだけ早くリリースするようにしてください。これは書き換えに固有のリスクを最小限に抑えるのに役立ちます。FirefoxのCSSエンジンをRustで書き換えたStyloは、このアプローチの成功例です。

どのアプローチが組織に最も適しているかに関わらず、成功の可能性を最大化するために留意すべき点がいくつかあります。まず、社内の支持者と、多くのチームメンバーにとって新しい言語でコードレビューと指導を提供できる上級エンジニアを確保することです。その自然な延長として、新しい言語で作業するエンジニアが、書籍、トレーニング、または社内ガイドなどのリソースを利用できるようにすることです。最後に、新しい言語がビルドシステム、テスト、デプロイメント、クラッシュレポート、その他の統合など、古い言語と同じ共有インフラを持つことを確認する必要があります。

結論

新しいプログラミング言語を採用し、その移行を開始するプロセスは簡単ではありません。組織全体の計画、リソースの割り当て、そして最終的な投資が必要です。これらのことを考えずに済めば、人生ははるかに簡単でしょう。残念ながら、データの精査は、セキュリティに敏感なプロジェクトに安全でない言語を引き続き使用することを考えられないことを明確に示しています。

データは何度も、CやC++のような安全でない言語を使用すると、大量のセキュリティ脆弱性に悩まされることを証明しています。エンジニアがどれほど才能があり、権限削減やエクスプロイト緩和への投資がどれほど大きくても、メモリ安全でない言語を使用すると、単純にエラーが多くなりすぎます。これらのエラーは、セキュリティ、安定性、生産性を大幅に低下させます。

幸いなことに、現状に甘んじる必要はありません。過去数年間で、Rust、Swift、Goなど、CおよびC++の優れた代替手段が登場しました。これは、選択しない限り、メモリ破損の脆弱性を今後何年も首にぶら下げる必要がないことを意味します。多要素認証がない、または転送中のデータが暗号化されていないのと同じように、安全でない言語の使用が怠慢と見なされる日が来ることを期待しています。

Alex Gaynorへの感謝

許可を得て、この説明はAlex Gaynorのブログ記事エンジニアリング担当副社長のためのメモリ非安全性入門に基づいています。

本稿のまとめ

これらの2つの翻訳から何か得られることを願っています。

さらに探索

関連読書

その他の記事
同じタグ 2024/03/14

C#とJava

動的で進化し続けるソフトウェア開発の世界では、JavaとC#は二大巨頭であり、それぞれに独自の強み、哲学、エコシステムがあります。この記事では、JavaとC#を詳細に比較し、歴史的背景、言語機能、パフォーマンス指標、クロスプラットフォーム機能などを考察します。

続きを読む