プリンキピア

第14章サイバー資源の品質とサイバーコンピューティングのガバナンス

Software Solutions Assurance Methodologiesソフトウェアソリューションの保証手法
As discussed earlier, software security can be compromised as a result of memory safety attacks that include the following:
先に述べたように、ソフトウェアの安全性は、次のようなメモリー安全性への攻撃によって損なわれうる。
• buffer overflows, which may be used to read/write data on stack/heap or to inject code (ultimately via a root shell);
• バッファーオーバーフロー:スタックやヒープ上のデータの読み書き、またはコード注入に使われる。最終的にはrootシェルを通じて行う。
• format string errors, used to read/write stack data;
• 書式文字列エラー:スタックのデータの読み書きに使う。
• integer overflow errors, used to change programs’ control flow; and
• 整数オーバーフローエラー:プログラムの制御フローを変えるために使う。
• TOCTOU problems, used to raise privileges.
• TOCTOU問題:権限を高めるために使う。
Various methodologies and associated approaches that may be used as part of the software development life cycle to prevent these attacks are described in the following sections.
次の各項では、これらの攻撃を防ぐため、ソフトウェア開発ライフサイクルの一部として使える、さまざまな手法と関連する取り組みを説明する。
Defensive Programming
防御的プログラミング
If you think of defensive driving as an analogy, it is about avoiding dependence on anyone but yourself. Minimizing trust makes it possible to better react to unexpected events (e.g., avoid a crash, or worse). Defensive programming pretty much works in the same way. Each software module is responsible for checking the validity of all inputs it receives and throwing exceptions or exiting rather than running malicious code and/or trusting inputs, even when they come from callers you know.
英語のヒント
防衛運転をたとえに考えると、自分以外の誰にも依存しないようにすることだ。信頼を最小限にすれば、衝突やそれ以上の事態を避けるなど、予期せぬ出来事へうまく対応できる。防御的プログラミングも、ほぼ同じように働く。各ソフトウェアモジュールは、受け取るすべての入力の妥当性を確認し、悪意あるコードを実行したり入力を信用したりする代わりに、例外を投げるか終了する責任を持つ。知っている呼び出し元から来た入力であっても同じである。
Defensive programming requires code reviews. While real or imagined, these reviews force programmers to organize their code and focus on code correctness to address issues that could raise flags. One approach to defensive programming is to provide developers with better languages and libraries that render code less prone to mistakes. For example, Java Runtime checks bounds automatically, and C++ comes with a safe std::string class. Secure coding relies on practices and rules, as illustrated in the following code.
英語のヒント
防御的プログラミングには、コードレビューが必要である。実際に行うにせよ想像上で行うにせよ、レビューはプログラマーにコードを整理させ、問題視されうる点へ対処するため、正しさへ注意を向けさせる。一つの方法は、間違いを起こしにくくする、よりよい言語やライブラリーを開発者に与えることだ。たとえばJavaの実行環境は自動で境界を確認し、C++には安全なstd::stringクラスがある。安全なコーディングは、次のコードに示すような実践と規則に基づく。
• Practice: Analyze all inputs, whatever they are26 :
• 実践:どのような入力も、すべて分析する。26
The code cited in original footnote 26 is omitted because reusable rights for the third-party material could not be verified.原著の脚注26に対応するコードは、第三者の素材の再利用条件を確認できないため、権利の関係で割愛しています。
◦ Think about all potential inputs, no matter how peculiar27 :
◦ どれほど奇妙でも、可能性のあるすべての入力を考える。27
The code cited in original footnote 27 is omitted because reusable rights for the third-party material could not be verified.原著の脚注27に対応するコードは、第三者の素材の再利用条件を確認できないため、権利の関係で割愛しています。
◦ Enforce rule compliance at runtime.
◦ 実行時に、規則を守らせる。
• Rule: Make use of safe string functions or libraries. String library routines typically included in libraries assume target buffers have sufficient length28 :
• 規則:安全な文字列関数やライブラリーを使う。一般的な文字列ライブラリールーチンは、宛先バッファーに十分な長さがあると仮定する。28
The code cited in original footnote 28 is omitted because reusable rights for the third-party material could not be verified.原著の脚注28に対応するコードは、第三者の素材の再利用条件を確認できないため、権利の関係で割愛しています。
Safe versions: check the destination length29 :
安全な版:宛先の長さを確認する。29
The code cited in original footnote 29 is omitted because reusable rights for the third-party material could not be verified.原著の脚注29に対応するコードは、第三者の素材の再利用条件を確認できないため、権利の関係で割愛しています。
27 Code reproduced with permission from Dave Levin 26 Code reproduced with permission from Dave Levin
27 コードはDave Levinの許可を得て転載。26 コードはDave Levinの許可を得て転載。
Again, you must know your system’s and language’s semantics. Note that strncpy/strncat do not null-terminate if they run up against the size limit; therefore, it is better to use strlcpy/strlcat. These functions are not “insecure,” but they are commonly misused. It is actually even better to use safe string libraries as they are designed to ensure that strings are used safely. The following code illustrates the use of the very secure FTP (vsftp) string library30 :
英語のヒント
繰り返すが、システムと言語の意味論を知っていなければならない。strncpy/strncatは、大きさの上限に達するとヌル終端しないため、strlcpy/strlcatを使う方がよい。これらの関数は「安全でない」のではなく、よく誤用されるのである。実際には、安全な文字列ライブラリーの利用がさらによい。文字列を安全に使えるよう設計されているからだ。次のコードは、very secure FTP(vsftp)の文字列ライブラリーの使い方を示す。30
The code cited in original footnote 30 is omitted because reusable rights for the third-party material could not be verified.原著の脚注30に対応するコードは、第三者の素材の再利用条件を確認できないため、権利の関係で割愛しています。
• Rule: Understand pointer arithmetic.
• 規則:ポインター演算を理解する。
Image omitted because its reuse rights could not be verified.権利の確認ができないため画像を割愛。
(attribution: Copyright Rice University, OpenStax, under CC BY 4.0 license; credit: reproduced with permission from Dave Levin)
(帰属表示:著作権 Rice University、OpenStax。CC BY 4.0ライセンス。出典:Dave Levinの許可を得て転載。)
The command sizeof() returns a number of bytes, but pointer arithmetic multiplies by the size of the type31 :
sizeof()はバイト数を返すが、ポインター演算では、型の大きさが掛けられる。31
The code cited in original footnote 31 is omitted because reusable rights for the third-party material could not be verified.原著の脚注31に対応するコードは、第三者の素材の再利用条件を確認できないため、権利の関係で割愛しています。
• Practice: Defend against dangling pointers.
• 実践:ダングリングポインターから防御する。
28 Code reproduced with permission from Dave Levin 29 Code reproduced with permission from Dave Levin 30 Code reproduced with permission from Dave Levin 31 Code reproduced with permission from Dave Levin
28 コードはDave Levinの許可を得て転載。29 コードはDave Levinの許可を得て転載。30 コードはDave Levinの許可を得て転載。31 コードはDave Levinの許可を得て転載。
Image omitted because its reuse rights could not be verified.権利の確認ができないため画像を割愛。
(attribution: Copyright Rice University, OpenStax, under CC BY 4.0 license; credit: reproduced with permission from Dave Levin)
(帰属表示:著作権 Rice University、OpenStax。CC BY 4.0ライセンス。出典:Dave Levinの許可を得て転載。)
• Rule: Use NULL after free
• 規則:freeの後はNULLを使う。
Image omitted because its reuse rights could not be verified.権利の確認ができないため画像を割愛。
(attribution: Copyright Rice University, OpenStax, under CC BY 4.0 license; credit: reproduced with permission from Dave Levin)
(帰属表示:著作権 Rice University、OpenStax。CC BY 4.0ライセンス。出典:Dave Levinの許可を得て転載。)
• Practice: Manage memory properly. Some programmers commonly use goto chains in C to avoid duplicating or missing code. This approach is similar to using a try/finally clause in Java. A good coding practice is to always review and confirm the logic correctness32 .
• 実践:メモリーを適切に管理する。Cでgotoの連鎖を使い、コードの重複や抜けを避けるプログラマーもいる。Javaのtry/finally節の利用に似た方法である。論理の正しさを常にレビューして確かめることが、よいコーディングの実践となる。32
The code cited in original footnote 32 is omitted because reusable rights for the third-party material could not be verified.原著の脚注32に対応するコードは、第三者の素材の再利用条件を確認できないため、権利の関係で割愛しています。
• Rule: Always use a safe allocator. ASLR makes the base address of libraries unpredictable to defeat exploits. Using the same thinking and at the cost of reduced performance, addresses returned by calls to malloc should be made unpredictable to avoid heap-based overflows.
英語のヒント
• 規則:安全なアロケーターを常に使う。ASLRは、ライブラリーの基準アドレスを予測不能にし、攻撃を防ぐ。同じ考え方により、性能の低下と引き換えに、mallocの返すアドレスを予測不能にして、ヒープのオーバーフローを防ぐべきである。
• Rule: Favor safe libraries. Libraries encapsulate well-thought-out design, so take advantage of them. For example, smart pointers libraries (part of C++11 standard) limit pointers to only safe operations and manage lifetimes appropriately. Networking libraries such as Google protocol buffers and Apache Thrift are good for dealing with network-transmitted data: they are both efficient and also ensure inputs are handled securely (e.g., validation, parsing).
英語のヒント
• 規則:安全なライブラリーを優先する。ライブラリーは十分に考えられた設計を包み込んでいるので、活用すべきである。たとえばC++11標準の一部であるスマートポインターのライブラリーは、ポインターを安全な操作に限定し、寿命を適切に管理する。Google Protocol BuffersやApache Thriftのようなネットワーク用ライブラリーは、ネットワーク経由のデータの処理に向いている。効率がよく、検証や構文解析などの入力処理の安全性も確保する。
Secure Software Implementation
安全なソフトウェア実装
The trusted computer base (TCB) of every system may include the monitor, compiler, OS, CPU, memory, keyboard, and other peripherals. Basic security assumes a correct, complete, and secure TCB. A good TCB is small and separates privileges. Using a small and simple TCB ensures that fewer components must work correctly to ensure security and are less susceptible to compromises. As security software in the TCB grows and becomes more complex (e.g., operating systems kernels used to enforce security often include a large amount of code), it becomes vulnerable and may be bypassed. Rather than compromising a device driver’s security, it is best to reduce the size of the operating system kernel by creating microkernels that leverage device drivers located outside the kernel. The least privilege, a privilege separation approach, should also be applied to keep privileged operations modules as small as possible. It is important to only give the right level of privilege to a task. There is no reason to give more privileges than needed to a task. For example, it is not necessary for a web server daemon to allow root to bind to port 80. Doing so will enable the web server to run as root. Similarly, email editors should not make it possible to access a shell. You need to remember that trust is transitive, trusting something means that you trust what it trusts, which can lead to trouble.
英語のヒント
システムの信頼できるコンピューター基盤(TCB)には、モニター、コンパイラー、OS、CPU、メモリー、キーボード、その他の周辺機器が含まれうる。基本的なセキュリティーは、TCBが正しく、完全で、安全であると仮定する。よいTCBは小さく、権限を分離する。小さく単純にすれば、安全性のために正しく動く必要がある構成要素が少なくなり、侵害されにくい。TCB内のセキュリティーソフトウェアが大きく複雑になると、脆弱になり、迂回される可能性がある。たとえば、安全性を強制するOSカーネルは、しばしば大量のコードを含む。デバイスドライバーの安全性を損なうより、カーネル外のドライバーを使うマイクロカーネルを作り、OSカーネルを小さくするのがよい。特権操作のモジュールをできるだけ小さく保つため、権限分離の方法である最小権限の原則も適用すべきである。タスクには適切な水準の権限だけを与えることが重要であり、必要以上の権限を与える理由はない。たとえばウェブサーバーのデーモンが、rootによるポート80へのバインドを認める必要はない。認めると、ウェブサーバーをrootで実行できるようになる。同様に、メールエディターからシェルへアクセスできるようにすべきではない。信頼には推移性があることを忘れてはならない。あるものを信頼するとは、それが信頼するものも信頼することであり、問題につながりうる。
Thinking about code safety is critical to ensure code safety and correctness. Code modularity is important as it helps to gain confidence in code function by function and module by module. It is necessary to verify that pre-and post-conditions hold before and after a function is called, respectively. This helps define contracts for using modules (e.g., a given statement’s post-condition needs to correspond to another statement’s pre-condition). Pre- and post-conditions help document code and facilitate reasoning about code. Invariants help set conditions that are always true within parts of a function. All the aforementioned defensive programming techniques make it possible to verify functions based on code and associated annotations every time the code is invoked. Defensive programming allows reasoning about functions’ safety each time they are called, and pre-conditions act as constraints that users must follow each time they use functions.
英語のヒント
コードの安全性と正しさを確保するには、安全性について考えることが不可欠である。関数ごと、モジュールごとにコードへの確信を得るのに役立つため、モジュール性は重要である。関数呼び出しの前には事前条件、後には事後条件が成り立つことを、それぞれ確認しなければならない。これにより、モジュールを使う契約を定められる。たとえば、ある文の事後条件は、別の文の事前条件に対応する必要がある。事前・事後条件はコードの文書化を助け、コードについての推論を容易にする。不変条件は、関数のある部分で常に真となる条件を定めるのに役立つ。前述の防御的プログラミングの技法すべてにより、呼び出しのたびに、コードとその注記に基づいて関数を検証できる。防御的プログラミングでは、呼び出すたびに関数の安全性を推論できる。事前条件は、利用者が関数を使うたびに従わなければならない制約として働く。
The following code illustrates the preconditions that are required to ensure safety. The approach consists of identifying each memory access and annotating them with the preconditions they require and propagate the requirements up.
次のコードは、安全性を確保するために必要な事前条件を示す。各メモリーアクセスを特定し、必要な事前条件を注記し、その要求を上へ伝えていく方法である。
32 Code reproduced with permission from Dave Levin
32 コードはDave Levinの許可を得て転載。
Image omitted because its reuse rights could not be verified.権利の確認ができないため画像を割愛。
(attribution: Copyright Rice University, OpenStax, under CC BY 4.0 license; credit: reproduced with permission from Dave Levin)
(帰属表示:著作権 Rice University、OpenStax。CC BY 4.0ライセンス。出典:Dave Levinの許可を得て転載。)
In this example, the memory access led to the following annotations33 :
この例では、メモリーアクセスから次の注記が導かれる。33
The code cited in original footnote 33 is omitted because reusable rights for the third-party material could not be verified.原著の脚注33に対応するコードは、第三者の素材の再利用条件を確認できないため、権利の関係で割愛しています。
The second annotation is taken care of by size_t i, which ensures that 0 <= i always holds. The two other annotations were not guaranteed by this function code so they were moved up as preconditions to ensure that n <= size(a).
二つ目の注記はsize_t iによって満たされ、0 <= iが常に成り立つ。残る二つの注記は、この関数のコードでは保証されないため、n <= size(a)を確実にする事前条件として、上へ移される。
Here is another example of the pre- and post-condition checks that are needed when using or creating pointer respectively to ensure safety34 :
次は、安全性を確保するため、ポインターを使うときと作るときに、それぞれ必要となる事前条件・事後条件の確認の別例である。34
The code cited in original footnote 34 is omitted because reusable rights for the third-party material could not be verified.原著の脚注34に対応するコードは、第三者の素材の再利用条件を確認できないため、権利の関係で割愛しています。
Testing
テスト
The goal of testing software quality is to ensure that the specification and implementation of programs match. Furthermore, testing assumes that the specification is correct but it does not necessarily assume that implementation is correct.
英語のヒント
ソフトウェア品質のテストの目標は、プログラムの仕様と実装の一致を確かめることである。テストは、仕様が正しいとは仮定するが、実装が正しいとは必ずしも仮定しない。
Developers should not be end-to-end testers. A developer should focus on the implementation and unit testing while a tester focuses on the specification, which avoids related mistakes at both levels.
英語のヒント
開発者は、端から端までを確認するテストの担当者になるべきではない。開発者は実装と単体テストに、テスト担当者は仕様に集中すべきである。そうすることで、両方の水準で関連する間違いが起こるのを避けられる。
Testing approaches may be classified as illustrated in Figure 14.33.
テストの方法は、図14.33のように分類できる。
33 Code reproduced with permission from Dave Levin 34 Code reproduced with permission from Dave Levin
33 コードはDave Levinの許可を得て転載。34 コードはDave Levinの許可を得て転載。
Figure 14.33

attribution: Copyright Rice University, OpenStax, under CC BY 4.0 license · CC BY 4.0 · Source出典

Figure 14.33 Testing approaches can be either manual or automated and test software using black-box or white-box techniques. (attribution: Copyright Rice University, OpenStax, under CC BY 4.0 license)
図14.33 テストは手動でも自動でも行え、ブラックボックスまたはホワイトボックスの技法でソフトウェアをテストする。(帰属表示:著作権 Rice University、OpenStax。CC BY 4.0ライセンス。)
As illustrated, there are various ways to conduct testing. Automated testing involves writing scripts or using testing frameworks to simulate user interactions with a software application (e.g., clicking buttons, entering data, and verifying outcomes). It enhances efficiency by automating repetitive testing tasks, which results in saving valuable time and resources. Automated testing also improves accuracy by minimizing human errors, and it enhances test coverage by enabling regression testing and continuous testing and delivery via CI/CD pipelines. Manual testing assumes the creation of efficient test suites to provide optimal test coverage and may struggle to achieve comprehensive coverage and scalability due to time and resource constraints. Black-box testing does not require analyzing code, which works well for code that cannot be modified or is in a format that makes it difficult to analyze (e.g., obfuscated, managed, or binary code). White-box testing assumes an efficient test suite to provide the detailed tests evaluating the source code.
英語のヒント
図のように、テストにはさまざまな方法がある。自動テストは、スクリプトやテスト用の枠組みを使い、ボタンのクリック、データ入力、結果の検証など、利用者とソフトウェアのやり取りを模擬する。繰り返す作業を自動化して効率を高め、貴重な時間と資源を節約する。人為的な誤りを最小化して精度も高める。回帰テストと、CI/CDパイプラインによる継続的なテスト・提供を可能にし、テストの網羅性も改善する。手動テストでは、最適な網羅性を得るため、効率のよいテスト群を作ると想定する。時間と資源の制約から、包括的な網羅性や拡張性の実現には苦労する場合がある。ブラックボックステストはコードの分析を必要とせず、改変できないコードや、難読化済みコード、マネージドコード、バイナリーコードなど、分析しにくい形式に適する。ホワイトボックステストは、ソースコードを評価する詳細なテストを提供する、効率のよいテスト群を想定する。
Test suites must be sized properly. Small numbers of tests cannot identify all the defects and large numbers of tests will slow down testing and make it harder to maintain tests due to bloating and redundancy. For example, the SQLite library (version 3.20.0) included approximately 125.4 thousand source lines of code (KSLOC) as compared to a project using it that had 730 times as much test code and scripts (i.e., 91616.0 KSLOC). It should be noted that KSLOC lines of code exclude blank lines and comments.
英語のヒント
テスト群は、適切な規模にしなければならない。少なければすべての欠陥を見つけられず、多すぎればテストが遅くなり、肥大化と重複で保守も難しくなる。たとえばSQLiteライブラリーのバージョン3.20.0は、約125.4千ソースコード行(KSLOC)を含む。一方、それを使うプロジェクトのテストコードとスクリプトは、その730倍の91,616.0 KSLOCあった。KSLOCには空行とコメントを含めない。
Code coverage is a metric used to quantify the extent of program code testing when using a given test suite. Function testing coverage focuses on which functions are called. Statement testing coverage focuses on which statements are executed, and branch testing coverage focuses on which branches are executed. Testing coverage is computed as a percentage of a program’s testing aspects covered by a given test suite. Practically, testing 100% of the code in a program is impossible. Cyclomatic complexity refers to the number of paths that exist in a program and should, in theory, be tested. That said, some code may not be accessible, and even if full testing were possible, it could take an infinite amount of time. Safety-critical applications do require 100% coverage. SQLite, as an example, has 100% branch coverage.
英語のヒント
コードカバレッジは、あるテスト群がプログラムのコードをどの程度テストするか、数量化する指標である。関数の網羅率は、どの関数を呼んだかに注目する。文の網羅率は、どの文を実行したか、分岐の網羅率は、どの分岐を実行したかに注目する。テスト群でカバーした、プログラムのテスト対象側面の割合として計算する。実際には、プログラムのコードを100%テストすることは不可能である。循環的複雑度は、プログラム内に存在し、理論上テストすべき経路の数を指す。しかし、一部のコードには到達できない場合があり、すべてのテストが可能でも、無限の時間がかかりうる。安全性が極めて重要なアプリケーションでは、100%の網羅性が必要とされる。たとえばSQLiteは、分岐を100%網羅する。
In manual white-box testing, tests are written by hand using full knowledge of the source code/deployment/ infrastructure. They can be automated (e.g., run on all saves or commits).
手作業のホワイトボックステストでは、ソースコード、配備、基盤に関する知識をすべて使って、テストを手で書く。保存やコミットのたびに実行するなど、自動化もできる。
In manual black-box testing, the tester interacts with the system in a black-box fashion and crafts ill-formed inputs, tests them, and records how the system reacts.
手作業のブラックボックステストでは、テスト担当者がシステムをブラックボックスとして扱い、不正な形式の入力を作って試し、反応を記録する。
Automated testing techniques include:
自動テストの技法には、次がある。
• Code analysis
• コード分析
◦ Static: Evaluating the source code can identify many of the bugs we have discussed.
◦ 静的:ソースコードを評価し、これまで述べた多くのバグを見つけられる。
◦ Dynamic: Run in a VM and look for invalid writes (Valgrind).
◦ 動的:仮想マシン内で実行し、不正な書き込みを探す。Valgrindが例である。
• Fuzz testing
• ファズテスト
◦ Generate many random inputs and see if the program fails.
◦ 多数のランダムな入力を生成し、プログラムが失敗するか調べる。
◦ Typically, it involves many inputs.
◦ 通常、多数の入力を使う。
◦ There are various possible kinds of fuzzing:
◦ ファジングには、さまざまな種類がある。
▪ Black-box: The tool knows nothing about the program or its input; it is easy to use and get started, but it will explore only shallow states unless it gets lucky.
英語のヒント
▪ ブラックボックス型:ツールはプログラムやその入力を何も知らない。使い始めるのは容易だが、幸運に恵まれなければ浅い状態しか探索できない。
▪ Grammar-based: The tool generates input informed by grammar; more work is required to use it and to produce the grammar, but it can go deeper into the state space.
▪ 文法ベース:文法に基づいて入力を生成する。利用と文法の作成には手間がかかるが、状態空間のより深い部分へ進める。
▪ White-box: The tool generates new inputs at least partially informed by the code of the program being fuzzed; it is often easy to use but computationally expensive.
英語のヒント
▪ ホワイトボックス型:対象プログラムのコードを少なくとも一部は参考にし、新しい入力を生成する。使いやすいことが多いが、計算コストが高い。
◦ Fuzzing inputs may be provided in different ways:
◦ ファジングへの入力には、異なる与え方がある。
▪ Mutation: Take a legal input and mutate it, using that as input; the legal input might be human-produced or automated (e.g., from a grammar or SMT solver query); mutation might also be forced to adhere to grammar.
▪ 変異型:正しい入力を取り、変異させて入力に使う。正しい入力は、人が作っても、文法やSMTソルバーへの問い合わせなどで自動生成してもよい。変異も文法に従わせる場合がある。
▪ Generational: Generate input from scratch (e.g., from a grammar).
▪ 生成型:文法などから、入力を一から生成する。
▪ Combinations: Generate initial input, mutate, generate new inputs, and generate mutations according to grammar.
▪ 組み合わせ型:初期入力を生成し、変異させ、新たな入力を生成し、文法に従って変異を作る。
◦ File-based fuzzing mutates or generates inputs and then runs the target program with them to see what happens; an example is Radamsa,35 a mutation-based, black-box fuzzer, which mutates inputs that are given and passes them along36 :
英語のヒント
◦ ファイルベースのファジングは、入力を変異または生成し、その入力で対象プログラムを動かして、何が起きるか調べる。例はRadamsaである。35 変異型のブラックボックスファザーで、与えられた入力を変異させ、その先へ渡す。36
The code cited in original footnote 36 is omitted because reusable rights for the third-party material could not be verified.原著の脚注36に対応するコードは、第三者の素材の再利用条件を確認できないため、権利の関係で割愛しています。
Another example is Blab, which generates inputs according to grammar (i.e., it is grammar-based), specified as regexps and CFGs37 :
別の例はBlabで、正規表現と文脈自由文法(CFG)で指定された文法に従い、入力を生成する。つまり、文法ベースである。37
The code cited in original footnote 37 is omitted because reusable rights for the third-party material could not be verified.原著の脚注37に対応するコードは、第三者の素材の再利用条件を確認できないため、権利の関係で割愛しています。
◦ Network-based fuzzing can act as half of a communicating pair; inputs could be produced by replaying previously recorded interaction, and altering it, or producing it from scratch (e.g., from a protocol grammar). It can also act as a “man-in-the-middle” by mutating inputs exchanged between parties (perhaps informed by grammar).
◦ ネットワークベースのファジングは、通信する一組の片側として働ける。記録済みのやり取りを再生して変更したり、プロトコル文法などから一から作ったりして、入力を生成できる。また、当事者間で交換する入力を、必要なら文法を参考に変異させ、「中間者」として働くこともできる。
◦ There are many fuzzers out there, such as American Fuzzy Lop (mutation-based white-box buzzer), SPIKE (library for creating network-based fuzzers), Burp Intruder (automates customized attacks against web apps), BFF, and Sulley. Fuzzers help find the root cause of a crash by answering questions such as: Is there a smaller input that crashes in the same spot (makes it easier to understand)? Are there multiple crashes that point back to the same bug? Can you determine if a crash represents an exploitable vulnerability (in particular, is there a buffer overrun)?
英語のヒント
◦ American Fuzzy Lop(変異型ホワイトボックスファザー)、SPIKE(ネットワーク型ファザーを作るライブラリー)、Burp Intruder(ウェブアプリへの個別に調整した攻撃を自動化する)、BFF、Sulleyなど、多数のファザーがある。ファザーは、次の問いに答えることで、クラッシュの根本原因の発見を助ける。同じ場所でクラッシュする、より小さい入力はあるか。あれば理解しやすくなる。同じバグを示す複数のクラッシュはあるか。クラッシュが悪用可能な脆弱性、特にバッファーの範囲外への書き込みを表すか、判断できるか。
◦ Fuzzing may help find memory errors: First, compile the program with AddressSanitizer (ASan), which instruments accesses to arrays to check for overflows, and use-after-free errors, then fuzz it and check if the program crashed with an ASan-signaled error. If that is the case, worry about exploitability; similarly, you can compile with other sorts of error checkers for testing (e.g., Valgrind memcheck).
英語のヒント
◦ ファジングは、メモリーエラーの発見に役立つ。まず、配列へのアクセスを計測し、オーバーフローと解放後の利用の誤りを確認するAddressSanitizer(ASan)付きでコンパイルする。次にファジングを行い、ASanが示すエラーでクラッシュしたか調べる。そうなら、悪用可能性を検討する。同様に、Valgrind memcheckなど、別種のエラーチェッカーを付けてコンパイルし、テストできる。
• Automated black-box testing uses fuzzing components as explained to generate test cases, execute the applications, and perform detection and logging.
• 自動ブラックボックステストは、説明したファジングの要素を使い、テストケースを生成し、アプリケーションを実行して、検知と記録を行う。
35 See https://gitlab.com/akihe/radamsa 36 Code reproduced with permission from Dave Levin 37 Code reproduced with permission from Dave Levin
35 https://gitlab.com/akihe/radamsa を参照。36 コードはDave Levinの許可を得て転載。37 コードはDave Levinの許可を得て転載。
• In automated white-box testing, tests are created automatically/dynamically. Tools exist to perform this type of testing and may record a trace of the tested program on well-formed inputs and perform symbolic execution to capture constraints on inputs. Automated testing may then negate a constraint or use a constraint solver to derive a new input and run on that input. When using American fuzzy lop, compile-time instrumentation is provided, and the instrumentation guides genetic algorithms.
英語のヒント
• 自動ホワイトボックステストでは、テストを自動的・動的に作る。専用ツールは、正しい形式の入力で対象プログラムの実行記録を取り、記号実行によって入力の制約を捉えることができる。その後、制約を否定したり、制約ソルバーで新しい入力を導いたりして、その入力で実行する。American Fuzzy Lopでは、コンパイル時に計測処理を追加し、その計測で遺伝的アルゴリズムを導く。
• Penetration testing Another testing technique is penetration (pen) testing. Fuzz testing is a form of pen testing. Pen testing assesses security by actively trying to find exploitable vulnerabilities, which is useful for both attackers and defenders. Pen testing is useful at many different levels (e.g., for testing programs, testing applications, testing a network, testing a server).
英語のヒント
• 侵入テスト:別のテスト技法は、ペネトレーション(ペン)テストである。ファズテストもその一種だ。悪用できる脆弱性を積極的に探し、安全性を評価するため、攻撃側にも防御側にも役立つ。プログラム、アプリケーション、ネットワーク、サーバーなど、さまざまな水準のテストに有用である。
Reverse Engineering
リバースエンジニアリング
Reverse engineering (RE) is the process of discovering the technological principles of a program through analysis of its structure, function, and operation. It corresponds to the solution development life cycle run backward. Reverse engineering is useful for malware analysis, vulnerability or exploit research, copyright/ patent violations check, interoperability assessment (e.g. understanding a file or protocol format), and copy protection removal. The legality of RE is a gray area and usually breaches the end-user license agreement (EULA) software contract. Additionally, the Digital Millennium Contract Act (DMCA) governs reverse engineering in the United States. You “may circumvent a technological measure . . . solely for the purpose of enabling interoperability of an independently created computer program.”
英語のヒント
リバースエンジニアリング(RE)は、プログラムの構造・機能・動作の分析から、技術的原理を発見する過程である。ソリューション開発のライフサイクルを逆向きにたどることに相当する。マルウェア分析、脆弱性や攻撃方法の研究、著作権・特許侵害の確認、ファイル形式やプロトコル形式の理解などの相互運用性の評価、コピープロテクトの除去に役立つ。REの合法性は曖昧な領域であり、通常はソフトウェアのエンドユーザーライセンス契約(EULA)に違反する。また、米国ではDigital Millennium Contract Act(DMCA)がREを規律する。「独立に作成されたコンピュータープログラムの相互運用を可能にする目的に限り、技術的手段を回避してもよい」とされる。
There are two techniques used for RE, and a combination of the two works best in general:
リバースエンジニアリングには二つの技法があり、一般には両方を組み合わせるのが最もよい。
• Static code analysis focuses on the code structure and uses a disassembler.
• 静的コード分析は、コードの構造に注目し、逆アセンブラーを使う。
• Dynamic code analysis focuses on the code operation and uses tracing, hooking, and debuggers.
• 動的コード分析は、コードの動作に注目し、トレース、フック、デバッガーを使う。
Disassembling code is difficult and often imperfect due to benign optimizations (e.g., constant folding, dead code elimination, inline expansion) and intentional obfuscation (e.g., packing, no-op instructions). Malware uses a lot of packing; overall, 90% of the code is packed.
英語のヒント
コードの逆アセンブルは難しく、しばしば不完全になる。定数畳み込み、不要コードの除去、インライン展開などの無害な最適化と、パッキング、何もしない命令などの意図的な難読化が原因である。マルウェアはパッキングを多用し、全体ではコードの90%がパックされている。
Dynamic analysis takes advantage of debuggers’ features (e.g., trace every instruction a program executes via single stepping; let the program execute normally until an exception; at every step or exception, observe/ modify instructions/stack/heap/register set; inject exceptions at arbitrary code locations; use INT3 instruction to generate a breakpoint exception). Debugging has many benefits as it is sometimes easier to see what the code does or allow unpacking to let the code unpack itself and debug as normal. Most debuggers have built-in disassemblers anyway. It is always possible to combine static and dynamic analysis. However, it is possible to run into difficulties with debugging when executing potentially malicious code (using an isolated virtual machine). The attacker may have used anti-debugging methods to detect the debugger and changed the program behavior so that it runs differently than when not being debugged (e.g., used IsDebuggerPresent(), INT3 scanning, timing, VM-detection, pop ss trick). Anti-anti-debugging can be tedious.
英語のヒント
動的解析は、デバッガーの機能を活用する。単一ステップで全命令を追跡する、例外まで通常実行する、各ステップや例外で命令・スタック・ヒープ・レジスターを観察または変更する、任意のコード位置へ例外を注入する、INT3命令でブレークポイント例外を生む、といった機能である。デバッグには多くの利点がある。コードの動作を見る方が簡単なこともあり、コード自身にパックを展開させてから通常どおりデバッグすることもできる。そもそも、大半のデバッガーには逆アセンブラーが組み込まれている。静的解析と動的解析は、常に組み合わせられる。しかし、隔離した仮想マシンで悪意ある可能性のあるコードを実行すると、デバッグが難しくなる場合がある。攻撃者はアンチデバッグ手法でデバッガーを検出し、デバッグされていないときと異なる動作へ変えているかもしれない。IsDebuggerPresent()、INT3の走査、タイミング、仮想マシン検出、pop ssの仕掛けなどを使う。アンチデバッグへの対抗は、手間がかかる場合がある。
A common way of evasion is to detect evidence of monitoring systems (e.g., fingerprint a machine/look for fingerprints) or hide real malicious intents if necessary as follows:
一般的な回避法は、監視システムの証拠を検出すること、たとえば機械の特徴を特定したり、その特徴を探したりすることである。必要なら、次のように本当の悪意ある目的を隠す。
IF VM_PRESENT() or DEBUGGER_PRESENT()     Terminate()        // hide real intents ELSE
    Malicious_Behavior()    //real intent
The general taxonomy of malware evasion is illustrated in Table 14.5.
マルウェアの回避の一般的な分類を、表14.5に示す。
Difficulty
難易度
Layer of Abstraction
抽象化の層
Examples
例
Easiest
最も容易
Application
アプリケーション
Installation, execution
インストール、実行
Easy
容易
Hardware
ハードウェア
Device name, driver
装置名、ドライバー
Somewhat difficult
やや難しい
Environment
環境
Memory, execution artifacts
メモリー、実行の痕跡
More difficult
より難しい
Behavior
振る舞い
Timing
タイミング
Table 14.5 Malware Evasion Taxonomy
表14.5 マルウェアの回避の分類
In general, there is a prevalence of evasion, and 40% of malware samples exhibit fewer malicious events with a debugger attached.
回避は一般に広く行われており、マルウェアのサンプルの40%は、デバッガーを接続すると悪意ある事象が減る。