銀行員からのRailsエンジニア

銀行員からのRailsエンジニア

銀行員から転身したサービス作りが大好きなRailsエンジニアのブログです。個人で開発したサービスをいくつか運営しており、今も新しいサービスを開発しています。転職して日々感じていること、個人開発サービス運営のことなどを等身大で書いていきます。

当ブログではアフィリエイト広告を利用しています

【技術書メモ】現場で使えるMySQL 〜毎週アウトプットチャレンジ⑧〜

毎週 1冊技術書を読んでブログでアウトプットするチャレンジの第8弾ですー!

今回は、現場で使えるMySQL を読んでまとめました。

MySQL現場で使うための知識を、分かりやすく解説している技術書です。

現場で使える MySQL (DB Magazine SELECTION)

現場で使える MySQL (DB Magazine SELECTION)

 

f:id:ysk_pro:20180908194233j:plain

Chapter1 MySQLの概要と環境構築

  • データベース領域:インスタンスと1対1に対応した、データベースの物理領域。1つのデータベース領域の中に複数のデータベースが格納される
  • 権限データベース:mysqlという名前のデータベース。インスタンスへ接続するためのユーザー情報や、各データベース、テーブルにアクセスするための権限情報が複数のテーブル内に格納されている
  • 初期パラメータファイル:インスタンスの使用メモリやサイズやファイル配置などを決めるためのファイル
  • MySQLユーザー:MySQLインスタンスに接続するためのDBアカウント
 

Chapter2 データ型とSQL

  • データや値の範囲チェックはアプリケーション側の責任であるという考え方に基づいて実装されている。例えば、どのデータ型でも、範囲を超えた値を格納しようとしてもエラーにはならず、削られたり最大値や0に変換されたりするので注意が必要
  • 文字列型で最大長を超える文字を格納しようとした場合、オーバーした部分は削られた上で正常終了する
  • ソートや文字列比較において、デフォルトでは半角英字の大文字/小文字を区別しない
  • 数値型のNUMERIC型は、NUMERIC(p,n)という形で定義され、pは全体の有効桁数、nは小数点以下の有効桁数を意味する。p,nどちらも指定しなかった場合、NUMERIC(10,0)となる
  • 日付/時刻型としては、YEAR/DATE/TIME/DATETIME/TIMESTAMPの5種類がある
  • 列挙型とは、あらかじめ復すの文字列値を定義しておいて、その中からしか選択できないようにするためのデータ型で、ENUMとSETの2種類がある。ENUM型は定義値の中から1つのみ選択できて、SET型は複数選択できる
 

Chapter3 テーブル定義

  • 主なストレージエンジンとその特徴
  • 整合性制約
    • 主キー制約:制約対象列にNULL値を入れないことと、値が重複しないことを保証する。これにより、制約対象列の値からテーブル内の行を一意に識別できる
    • 一意キー制約:制約対象列の値が重複しないことを保証する。NULL値は格納でき、NULL値同士は異なる値であると見なされる
    • 参照整合性制約(外部キー制約):子テーブルの制約対象列の値が、親テーブルの参照キーに含まれていることを保証するもので、子テーブルに定義する。利用するためには、親テーブル、子テーブルともInnoDBである必要がある
  • シーケンス:連続的な整数値を生成するオブジェクト。シーケンスから得られる数値のことをシーケンス番号、連番などと呼ぶ。一般的に、同一のシーケンスから得られるシーケンス番号は重複しないため、テーブルの主キーや一意キーとして使用されることが多い
 

Chapter4 トランザクション

  • 自動コミット機能:この機能を有効にするか無効にするかによって、トランザクションの開始/終了の方法が変化する
    • 有効にした場合:トランザクションは単一のSQL文を実行した時点で自動的に、または、START TRANSACTION文によって明示的に開始する。START TRANSACTION文を実行していない場合は、単一のSQL文が実行された時点で自動的にコミットし、ロールバックできない。一方、START TRANSACTION文を実行している場合は、単一のSQL文が終了しただけではコミットせず、COMMIT文を実行した時点ではじめてコミットする。また、ROLLBACK文を実行するとロールバックする
    • 無効にした場合:トランザクションは、SQL文の実行によって暗黙的に、またはSTART TRANSACTION文で明示的に開始する。いずれの場合も自動的にコミットしない。COMMIT文を実行した時点でコミットし、ROLLBACK文を実行した時点でロールバックする
  • デフォルトでは自動コミット機能が有効となっている
  • ロックとは、複数のトランザクション間での排他制御を実現するための仕組み。InnoDBでは、テーブルの行(レコード)単位でロックをかけられる。
  • フルスキャンはすべての行にロックがかかってしまうため、インデックス検索させるべきところにはきちんとインデックスを作成すべき
  • デッドロックは即座に検出される
 

Chapter6 日本語処理

  • クライアントとサーバーの文字コードをすべてutf8に統一できる環境ならば問題はないが、そうでなければ様々な注意事項が存在する
 

Chapter8 アーキテクチャ/ファイル構成

  • インスタンスMySQLサーバー側で動作するプロセス/スレッド群と、それらが使用するメモリの総称
  • MySQLは、複数のクライアント側プロセスと1つのサーバー側プロセス「mysqld」で構成される。多くのRDBMSがマルチプロセスで動作するのとは対照的に、MySQLのサーバー側はマルチスレッドで動作する
  • プロセスとは、UNIXコマンドで言えばcatやlsといった個々のプログラムの実行単位である。OS上の各プロセスには、それぞれの固有のメモリ空間が割り当てられる。一方スレッドとは、簡単に言えば1つのプロセス内で並行処理を行うためのものである。スレッドはプロセスの内部で生成され、プロセスのメモリ空間を共有する
  • ストレージエンジンはアプリケーション側から隠蔽されている。アプリケーション側から発行するSQL文は、インスタンス側で動作するパーサーと呼ばれるプログラムによって解析され、どのインデックスを使用するか、といった実行計画が作成された上で、はじめて対象のストレージエンジンに処理が渡る。アプリケーションから見ると、ストレージエンジンが変わったとしても、発行するSQLが変わるわけではない
 

Chapter9 ユーザ管理/セキュリティ

  • MySQLにアクセスするにはまず認証を行う。認証とは、アクセス元が本人に間違いないことを確認することで、ユーザ名・アクセス元のホスト名/IPアドレス・パスワードの3つで認証する
  • OSユーザーとは別にMySQLユーザーという概念があり、MySQLインスタンスにアクセスする際に使用する。管理者ユーザーという特別なユーザーもあり、デフォルトではrootという名前になっている。MySQLユーザーは認証や権限管理のために存在する
  • 権限は、グローバル(全体)、データベース、テーブル、列の4種類ごとに設定する
  • 発行されたすべてのSQL文をファイルに記録する機能があるため、監査機能として使うことができる
 

Chapter10 バックアップ/リカバリ(前編)

  • バックアップ方法
    • コールドバックアップ:インスタンスを停止した状態で全体バックアップを取得する方法。したがって、バックアップの最中はインスタンスに対して一切アクセスできない。tarやcpなどのOSコマンドで取得する。
    • オンラインバックアップ:インスタンスを起動した状態でバックアップを取得する方法。
  • バックアップ/リカバリの基本的な流れは、バックアップ→メディア障害発生→リストア→リカバリである。
    • メディア障害とは、ディスクの故障やオペレーションミスなどにより、MySQLの実データが失われる障害のこと
    • リストアとはバックアップの時点まで復旧すること
    • リカバリは障害直前の時点まで復旧すること
 

Chapter11 バックアップ/リカバリ(後編)

  • MySQLのオンラインバックアップでの定番は「mysqldump」。データベース領域全体でも、テーブルやデータベース単位でもバックアップでき、バックアップデータはテキスト形式で、SQL文がそのまま記述される。MySQLインスタンスに接続→バックアップ対象のすべてのテーブルに対しSELECT文を実行し、テキスト形式で出力→すべてのバックアップが終了したら接続を終了、という流れで動作する
 

Chapter12 レプリケーション

  • レプリケーションとは、テーブルなどの各種オブジェクトの複製を他のサーバー上に生成するという技術。レプリケーションによって、負荷分散と可用性の向上を実現できる
  • 1台のマスターに対して更新を行うと、複数のスレーブにも同じ更新結果が反映される。検索は基本的にスレーブに対して行えばよいので、検索の負荷分散になる
  • レプリケーションは、スレーブにバックアップ機としての役割を持たせることによって、バックアップ/リカバリの手段としても利用できる
  • マスターに障害が発生した場合は、スレーブをマスターに昇格させてサービスを継続することで、サービス停止時間を短くすることができる
 

Chapter13 パフォーマンスチューニング(前編)

  • RDBMSのチューニングは単体チューニングとシステムチューニングの2つに大別できる
  • 単体チューニングとは、個々のSQL文の実行性能を改善する作業のことで、具体的にはインデックスの作成やSQL文の修正、アプリケーションロジックの見直しによるSQL発行回数を減らすことが含まれる
  • システムチューニングとは、システム全体の観点から、MySQLの初期化パラメータやOSのカーネルパラメータの設定を行うことが含まれる
  • 単体チューニングでは下記2つの手段を組み合わせる
    • スロークエリログから、実行時間の長いSQLや非効率なフルスキャンを行なっているSQL文の特定
    • 上記SQL文の実行計画をEXPLAIN文で確認し、必要に応じた改善
 

Chapter14 パフォーマンスチューニング(後編)

  • 基本的にデータ型は使用バイト数が少ないデータ型を選ぶことを心がけると良い。そうでないと、ファイルサイズが大きくなるだけでなく、多くのI/Oが発生するため性能面でも悪影響がある
  • SELECT/UPDATE/DELETE文のWHERE句で指定する列に対しては、インデックスを定義することでフルスキャンを防ぐのが一般的である。ただし、インデックスを作ると更新時にオーバーヘッドがかかることに注意する
  • バルクINSERT文とは、1つのSQL文で複数のレコードをまとめてINSERTする構文であり、通常のINSERT文を繰り返すのに比べ、大きな性能向上が図れる
  • テーブルのレコードデータをすべて削除する場合は、「DELETE FROM テーブル名;」よりも、「TRUNCATE TABLE テーブル名;」の方がはるかに高速
 

おわりに

ここまで読んでいただきありがとうございます。

MySQL、とても奥が深いですね、、、!
現場でMySQLを使っている方には特に本書オススメですー!
現場で使える MySQL (DB Magazine SELECTION)

現場で使える MySQL (DB Magazine SELECTION)

 

次もMySQLに関する技術書を読む予定です。

来週も頑張ります!

【技術書メモ】SQL 第2版 ゼロからはじめるデータベース操作 〜毎週アウトプットチャレンジ⑦〜

毎週 1冊技術書を読んでブログでアウトプットするチャレンジの第7弾ですー!

今回は、SQL 第2版 ゼロからはじめるデータベース操作 を読みました。

データベース・SQLについて、とても分かりやすく書かれた入門書です。 

SQL 第2版 ゼロからはじめるデータベース操作

SQL 第2版 ゼロからはじめるデータベース操作

 

f:id:ysk_pro:20180902101951j:plain

第1章 データベースとSQL

  • SQLは、RDBMSに与える命令の種類により、次の3つに分類される
    • DDL(Data Definition Language):データベースやテーブルを作成、削除などをする。(CREATE、DROPなど)
    • DML(Data Manipulation Language):テーブルの行を検索、変更などをする。(SELECT、INSERTなど)
    • DCL(Data Control Language):データベースに対して行った変更を確定、取消などをする。(COMMIT、ROLLBACKなど)
  • データ型
    • CHAR型:文字列を入れる型。CHAR(10)のように、入れることの出来る最長の長さを()で指定する。CHAR型は、固定長文字列という形式でデータが格納され、文字列の長さが最大長に満たない場合は、満たない分を文字の後に半角スペースを入れて埋める。
    • VARCHAR型:CHAR型と同じく文字列を入れる型。違いは、VARCHAR型は可変長文字列という形式で、文字数が最大長に満たない場合も半角スペースで埋めない点。
 

第2章 検索の基本

  • SELECTを使った検索で結果から重複を省く場合は、SELECTの後に「DISTINCT」をつける。DISTINCTを使った場合、NULLも1種類のデータとして扱われ、複数の行にNULLがある場合は、1つにまとめられる。
  • NULLを含んだ計算の結果は、問答無用でNULLになる。NULLを0で割る場合もエラーとならずNULLとなる。
 

第3章 集約と並び替え

  • COUNT関数は基本的にNULLを除外するが、COUNT(*)とすればNULLを含めた全行を数えることができる。
  • COUNT(*)以外の集約関数はNULLを除外して算出する。(0としても扱わない)
  • WHERE句には行に対する条件を書き、HAVING句にはグループに対する条件を書く。どちらにも書くことが出来る条件をWHERE句に書くべき理由は、可読性と実行速度。
  • ORDER BYでのソートキーにNULLが含まれる場合は、先頭か末尾にまとめられる。
  • ORDER BY句はSELECT句よりも実行されるのが後なので、SELECT句でつけた別名を使用できる。
 

第4章 データの更新

  • テーブルからデータを削除する方法として、DELETE文だけでなく、「TRUNCATE」というコマンドがある。TRUNCATEは必ずテーブルを全行削除し、DELETEよりも処理が高速という特徴がある。
  • DBMSトランザクションは、ACID特性と呼ばれる4つの特性がある。
    • 原子性(Atomicity):トランザクションが終わったとき、そこに含まれていた更新処理は、全て実行される or 全て実行されない状態で終わることを保証すること。
    • 一貫性(Consistency):トランザクションに含まれる処理は、データベースにあらかじめ設定された制約を満たすこと。
    • 独立性(Isolation):トランザクション同士が互いに干渉を受けないことを保証すること。トランザクション同士は入れ子になることはない。
    • 永続性(Durability):トランザクションが終了したら、その時点でのデータの状態が保存されることを保証すること。
 

第5章 複雑な問い合わせ

  • ビューとは、テーブルと同じように扱われる。違いは、テーブルの中には実際のデータが保存され、ビューの中にはSELECT文が保存されていること。
  • ビューのメリット
    • データを保存しないため、記憶装置の容量を節約できること。
    • 頻繁に使うSELECT文を、ビューとして保存することで、使い回せること。
  • サブクエリとは使い捨てのビューであり、SELECT文の実行終了後に消去される。
  • スカラ・サブクエリとは、戻り値が単一の値になるサブクエリであり、WHERE句などで使われる。
 

第6章 関数、述語、CASE式

  • 関数
    • ||:文字列連結
    • REPLACE:文字列中のある一部分を、別の文字列に置き換える
    • CURRENT_TIMESTAMP:現在の日時(CURRENT_DATE + CURRENT_TIME)
    • EXTRACT:日付データからその一部分(年や月)を、数値型として切り出す
    • CAST:型変換を行う
    • COALESCE:可変数の引数を取り、最初にNULLでない値を返す。NULLを別の値に変えて扱いたい場合などに使われる。
  • 述語:戻り値が真理値になる関数
    • IS NULL:ある列がNULLの行を選択する場合に、=は使うことができず、IS NULLを使う必要がある。反対にNULL以外の行を選択する場合は、IS NOT NULLを使う。
    • IN:ORの便利な省略形。反対はNOT IN。INは引数にサブクエリを指定する使い方もされる。
    • EXISTS:ある条件に合致するレコードの存在有無を調べる。INによってほぼ代用できる。
  • CASE式:場合分けを記述する時に使用する。ELSE NULLは省略可能であるが、可読性の観点から省略しない方がよい。
 

第7章 集合演算

  • 集合演算子は重複行を排除する。ALLを追加すれば重複行は排除されない。
  • UNION:レコードの足し算を行う。
  • INTERSECT:2つのレコードの共通部分を選択する。
  • EXCEPT:レコードの引き算を行う。
  • 結合(JOIN)は、別のテーブルから列を持ってきて、列を増やす集合演算。UNIONがテーブル同士を行方向(縦方向)に連結するのに対し、結合は列方向(横方向)に連結する。
  • 内部結合(INNER JOIN)は2つのテーブルの両方に存在する情報だけを選択するのに対して、外部結合(OUTER JOIN)はどちらか一方のテーブル(LEFT or RIGHTで指定する)に存在しているならば、そのテーブル情報が欠けることなく出力される。
 

第8章 SQLで高度な処理を行う

  • ウィンドウ関数は、ランキング、連番生成など通常の集約関数ではできない高度な操作を行う
  • GROUPING演算子は、GROUP BY句と集約関数ではできなかった小計・合計を同時に求めることができる

 

おわりに

ここまで読んでいただきありがとうございます。

Railsから入ったりすると、DB・SQLの学習は後回しになりがちですが、大規模なDBを扱う実務ではDBの知識はめちゃくちゃ重要です。

本書は基本的なところから書かれているので、とても分かりやすくスッと読むことができ他ので、DB・SQLに自信がない方にもオススメです!

SQL 第2版 ゼロからはじめるデータベース操作

SQL 第2版 ゼロからはじめるデータベース操作

 

 次はDBについてのもう少し高度な本を読む予定です。

来週も頑張ります!

 

Railsでお買い物メモ & Amazon・楽天のランキング1位を返してくれるLINE bot作りました

みなさん、「あれ買わなきゃ!」って思った時どうしていますか?

(例:家のトイレで「あ、トイレットペーパーラスト1つやんけ、買わなきゃ」の時)

f:id:ysk_pro:20180826173319j:plain

僕はevernoteにメモったり、可能な時はその場でポチったり、今日の帰り道に買うぞって思って結局忘れちゃったりしています。

 

みなさんがどうしているか気になったので、Twitterアンケート取ってみました。

(協力いただいた方ありがとうございます)

 

みなさん同じような感じですね〜、記憶に頼ってる方が一番多い、という感じですね。

 

皆さんが常に使ってるアプリ、LINEでお買い物メモ取れたら便利じゃないですか?

 

さらにもう一つ。

買う商品ってどうやって選んでますか?

 

選ぶ時間が勿体無いので、僕はほとんどAmazonのランキング1位を何も考えずに買っちゃいます。

 

お買い物メモで、リストを表示するときにAmazon(or 楽天)の1位の商品とリンクを返してくれたら便利じゃないですか?

 

この2つを組み合わせてLINE bot作っちゃいました。

 

↓こちらの動画を見れば、使い方が分かると思います。

 

使い方はとてもシンプルです。

「買わなきゃいけないもの」を送信するとLINE botが覚えてくれます

「リスト」と送信するとそれまでに送信した買わなきゃいけないものリストとそれぞれのAmazon or 楽天のランキング1位の商品を返してくれます

Amazonor楽天と送信すると検索対象を切り替えられます

「クリア」と送信するとリストの中身を全て削除できます

 

買わなきゃいけないものをよく忘れちゃう方evernoteなどにメモしているけどちょっとめんどくさいな、と感じている方、是非一度使ってみてくださいー!

 

↓こちらのボタンから簡単にお友達追加できます!

友だち追加

 

また、作り方をまとめたチュートリアルを作成したのでご興味あればぜひご覧くださいー!

note.mu

【技術書メモ】オブジェクト指向設計実践ガイド 〜毎週アウトプットチャレンジ⑥〜

毎週 1冊技術書を読んでブログでアウトプットするチャレンジの第6弾ですー!

今回は、オブジェクト指向設計実践ガイド を読みました。

オブジェクト指向設計についてRubyで解説している名著です。

f:id:ysk_pro:20180826134302j:plain

はしがき

第1章 オブジェクト指向設計

  • オブジェクト指向設計では、世界をあらかじめ決められた手続きの集まりと考えるのではなく、オブジェクト間で受け渡されるメッセージの連続としてモデル化している
  • オブジェクト間の相互関係はオブジェクト間で受け渡されるメッセージであり、正しいメッセージを届けるには、メッセージの送り手が受け手のことを知っている必要がある。この依存関係がプログラムの変更を困難にしており、オブジェクト指向設計は依存関係を管理することでプログラムの変更を容易にしている
  • オブジェクト指向設計で最も良く知られているSOLIDという5つの原則
    • 単一責任(Single Responsibility)
    • オープン・クローズド(Open-Closed)
    • リスコフの置換(Liskov Substitution)
    • インターフェース分離(Interface Segregation)
    • 依存性逆転(Dependency Inversion)

第2章 単一責任のクラスを設計する

  • コードの変更が簡単であることの定義
    • 変更が副作用をもたらさない(見通しが良く、コード変更の影響が明白)
    • 要件の変更が小さければコードの変更も小さい
    • 既存のコードが簡単に再利用できる
  • クラスは単一の責任を持つべき:2つ以上の責任を持つクラスは簡単に再利用できない
  • クラスが単一責任かどうかを見極めるには、一文でクラスを説明してみる。「それと」や「また」が含まれていれば責任は2つ以上ある
  • メソッドも、クラスのように単一の責任を持つべきで、その理由や見極め方はクラスと同様である

第3章 依存関係を管理する

  • 一方のオブジェクトに変更を加えた時、他方のオブジェクトも変更せざるを得ないおそれがあるならば、片方に依存しているオブジェクトがある
  • オブジェクトが次のものを知っている時、オブジェクトには依存関係がある
    • 他のクラスの名前
    • メッセージが要求する引数
    • それら引数の順番
  • 依存関係の管理で鍵となるのは、依存の方向を制御すること。自分より変更されないものに依存することが問題解決の方法である

第4章 柔軟なインターフェースをつくる

  • インターフェースとは、クラス内のメソッドで、どのように何を外部に晒すかを説明するもの
  • パブリックインターフェースを作り上げるメソッドの特性
    • クラスの主要な責任を明らかにする
    • 外部から実行されることが想定される
    • 気まぐれに変更されない
    • 他者がそこに依存しても安全
    • テストで完全に文書化されている
  • プライベートインターフェースの特性
    • 実装の詳細に関わる
    • 他のオブジェクトから送られてくることは想定されていない
    • どんな理由でも変更され得る
    • 他者がそこに依存するのは危険
    • テストでは言及さえされないこともある
  • シーケンス図を使うことで、様々なオブジェクトの構成やメッセージ受け渡しの体系を簡潔に実験できる。シーケンス図は思考を明確にし、他の人と共同作業したり意思疎通したりするための手段となる

第5章 ダックタイピングでコストを削減する

  • ダックタイプはいかなる特定のクラスとも結びつかないパブリックインターフェースであり、クラスをまたぐインターフェースはアプリケーションに大きな柔軟性をもたらす
  • ダックタイプによって型付けされたオブジェクトは、そのクラスよりもその振る舞いによって定義される。ダックタイプという名前は、もしオブジェクトがダックのように鳴き、ダックのように歩くならば、そのクラスが何であれそれはダックであるという表現に由来する

第6章 継承によって振る舞いを獲得する

  • 承継とは、根本的にはメッセージの自動委譲の仕組みである。あるオブジェクトが受け取ったメッセージに応答できなければ、他のオブジェクトにそのメッセージを委譲するという関係
  • 未知のメッセージはスーパークラスの階層構造をさかのぼって委譲されていく。サブクラスとはスーパークラスのパブリックインターフェースを全て持っていると想定されるだけでなく、そのインターフェースに定義されるどのメッセージにも適切にレスポンスを返すことが求められる

第7章 モジュールでロールの振る舞いを共有する

  • オブジェクトが応答できるメッセージには次の4種類が含まれる
    • 自身が実装するメッセージ
    • 自身より上の階層のすべてのオブジェクトで実装されるメッセージ
    • 自身に追加されるすべてのモジュールで実装されるメッセージ
    • 自身より上の階層のオブジェクトに追加されるすべてのモジュールで実装されるメッセージ

第8章 コンポジションでオブジェクトを組み合わせる

  • コンポジションとは、組み合わされた全体が単なる部品の集合以上となるように、個別の部品を複雑な全体へと組み合わせること
  • コンポーズされたオブジェクトは、新たな組み合わせへと簡単に再編成できる、シンプルで分離したエンティティから構成される傾向にある

第9章 費用対効果の高いテストを設計する

  • 変更可能なコードを書くためには、価値の高いテストを書く能力が求められる。テストにより自信を持って絶えず継続的にリファクタリングができる
  • 良いテストは、コードへの変更によってテストの書き直しが強制されないように書かれている
  • テストは唯一信用できる設計の仕様書となる
  • テストはオブジェクトの境界に入ってくるか、出ていくメッセージに集中すべき。受信メッセージはその戻り値の値の状態がテストされるべきで、送信コマンドメッセージは送られたことがテストされるべきである 

おわりに

ここまで読んでいただきありがとうございます。

オブジェクト指向、難しいですね。

この本を繰り返し読んでオブジェクト指向設計を身につけていきましょう!

次からはSQLの本を読んでいく予定です。

来週も頑張ります!

【技術書メモ】なるほどUnixプロセス Rubyで学ぶUnixの基礎 〜毎週アウトプットチャレンジ⑤〜

毎週 1冊技術書を読んでブログでアウトプットするチャレンジの第5弾ですーー!
なんとか続いています、、、!習慣になってきた、、、!
 
Unixの基礎であるプロセスについてRubyで解説している本です。
 
読む前は、Unix?プロセス?? というお恥ずかしい状態だったのですが、本書を2周読み終えた今、少しずつ理解できてきました。
 
少しとっつきにくい内容かもしれませんが、知っていて損ではない内容だと思うので是非見てみてください。

f:id:ysk_pro:20180819120359j:plain

第3章 プロセスにはIDがある

  • システムで動作するすべてのプロセスは固有の識別子(プロセスID)があり、pidと呼ばれている
  • pidはプロセスにまつわる情報は何も持たずに、単に連番になっている数値のラベルである
  • pidはログファイルで有効に使われている。pidにより、ログファイルの各行がどのプロセスから出力されたものかを識別できる
 

第4章 プロセスには親がいる

  • 親プロセスはそのプロセスを起動したプロセスである
 

第5章 プロセスにはファイルディスクリプタがある

  • Unixの世界ではすべてがファイルであり、デバイスはファイルとして扱われる
  • 実行中のプロセスでリソースを開くと、ファイルディスクリプタ番号が割り当てられる
 

第6章 プロセスにはリソースの制限がある

  • カーネルによって1プロセスごとにリソースの制限が設定されている
  • 制限は設定を変更することでほぼ無限大にすることができる
 

第7章 プロセスには環境がある

  • 環境とは環境変数のことをいう
  • 環境変数はキーとバリューが対になっており、プロセスで使えるデータを保持している
  • すべてのプロセスは親プロセスから環境変数を引き継ぐ
 

第8章 プロセスには定数がある

  • RubyプロセスはARGVという特別な配列を参照できる
  • argvとは引数の配列を意味するargument vectorの略である
  • argvにはコマンドラインからプロセスに渡された引数が格納されている
  • プログラムにファイル名を渡したいケースにARGVが最もよく使われる
 

第9章 プロセスには名前がある

  • Unixプロセスにはプロセスの状態を知らせるための手段がほとんどなく、これを回避するためにログファイルを作成した
  • プロセスのレベルで情報を伝えるための仕組みは二つあり、一つはプロセス名でもう一つは終了コードである
 

第10章 プロセスには終了コードがある

  • 慣習としてプロセスは正常終了時には終了コード0を返す。それ以外の終了コードはエラーを示しており、終了コードごとに異なるエラーの種類を表す
  • raiseで送出された例外が捕捉されない場合もプロセスは終了する
 

第11章 プロセスは子プロセスを作れる

  • fork(2)で子プロセスを生成すると、実行中のプロセスの完全なコピーを生成でき、親プロセスで使われている全てのメモリのコピーを受け継ぐ
 

第12章 孤児プロセス

  • 親プロセスが死んでも子プロセスは生き続ける
  • デーモンプロセスとは意図的に孤児化されたプロセスであり、いつまでも動き続けることを狙いとしている
 

第13章 プロセスは優しい

  • fork(2)は親プロセスの完全なコピーを新しい子プロセスとして生成するが、物理的に全てのデータをコピーするのはかなりのオーバーヘッドになるため、コピー・オン・ライト(CoW)と呼ばれる仕組みを採用している
  • CoWは書き込みが必要となるまでメモリを実際にコピーしない。それまでの間、親プロセスと子プロセスとはメモリ上の同じデータを物理的に共有しており、親または子のいずれかで変更する必要が生じた時のみメモリをコピーすることで両者のプロセスの独立性を保っている
  • CoWはfork(2)で子プロセスを生成するときにリソースを節約できるのでとても便利な仕組みである
 

第14章 プロセスは待てる

  • 孤児プロセスが発生しないようにProcess.waitを使えば、子プロセスのいずれか1つが終了するまで親プロセスをブロックして待つことができる
  • 子プロセスを活用するのは、Unixプログラミングでよく使われるパターンである。こうしたパターンは子守りプロセスやマスター/ワーカー、preforkなどと呼ばれている
  • このパターンの肝は用意した1つのプロセスから並列処理のために複数の子プロセスを生成して、その後は子プロセスの面倒を見るというもの。子プロセスたちが応答するのかを確かめたり、子プロセスが終了した際には後始末をする
  • WebサーバのUnicornがこのパターンを採用している。Unicornではサーバ起動時にワーカープロセスをいくつ使うかを指定する。5つのインスタンスが必要だと指定した場合、unicornプロセスは起動後にWebリクエストをさばくための子プロセスを5つ生成する。親プロセスは子プロセスそれぞれの死活監視を行い、子プロセスがちゃんと応答できるようにする
 

第16章 プロセスはシグナルを受信できる

  • シグナルは非同期通信。プロセスはカーネル(OSの核となるプログラムで複数のプロセスを同時に実行するためのスケジュール管理やメモリの管理を行うもの)からシグナルを受けたとき、①シグナルを無視する、②特定の処理を行う、③デフォルトの処理を行う、のいずれかの処理を行う
  • シグナルはある特定のプロセスから別のプロセスへと送られるものであり、カーネルはその仲介役となっている
  • pidさえ分かれば、システム上のどのプロセスともシグナルで通信できる。シグナルはプロセス間の通信手段である
  • 現実世界でのシグナルは、サーバやデーモンといった長期間動き続けるプロセスで使われているのがほとんどである
 

第17章 プロセスは通信できる

  • プロセス間通信(IPC)で複数のプロセス間で情報をやりとりできる
  • パイプは単方向のデータの流れ。パイプを開くというのは、プロセスの片方の端を別のプロセスの片方の端につなぐことをいう。パイプを通じてデータを流すことができるようになるが、その方向は単方向に限られる。プロセスがパイプに対して書き込みではなく読み込み側となることを宣言した場合、そのパイプには書き込めない。逆も然り
  • パイプが単方向の通信手段であるのに対し、ソケットは双方向の通信手段である。親のソケットは子のソケットに読み書きできるし、逆も然り
 

第18章 デーモンプロセス

  • デーモンプロセスは、ユーザーに端末から制御されるのではなく、バックグラウンドで動作するプロセスである。デーモンプロセスのよくある例としては、Webサーバやデータベースサーバのように、リクエストをさばくためにバックグラウンドで常に動作するプロセスがある
  • デーモンプロセスはオペレーティングシステムの核でもある。さまざまなプロセスがバックグラウンドでずっと動作し続けているおかげで、システムは正常に動いている
  • プロセスを永遠に応答し続けられる状態にする必要がある場合にデーモンプロセスを用い、不要ならcronジョブなどのバックグラウンドジョブの仕組みを検討する
 

第19章 端末プロセスを作る

  • execve(2)は現在のプロセスを異なるるプロセスに置き換えられる。RubyプロセスをPhyhonや他のRubyプロセスに変えることができる
  • execve(2)によるプロセスの置き換えは元に戻すことができない
  • fork + execveの組み合わせは新しくプロセスを生成する際によく使われる。fork(2)で新しく子プロセスを生成して、それからその子プロセスを任意のプロセスに置き換えるためにexecve(2)を使う
 

第20章 おわりに

  • カーネルから見れば、どのプログラミング言語で書かれたプログラムも同じに見える。最終的には、すべてのコードはカーネルが理解可能な単純なものへコンパイルされる。そして、動作する段階ではすべてがプロセスとして同等に扱われる
  • Unixプログラミングはプログラミング言語を問わない。RubyスクリプトとCプログラムを連携させることもできる
  • シグナルを使えば、システム上のどんなプロセスも互いに情報を伝達できる。プロセスに名前を付けることで、コマンドライン上から誰でもプログラムの状況を検査できる。終了コードを使えば、呼び出し元のプロセスに成功/失敗のメッセージを伝えられる
 

付録A Resqueのプロセス管理

  • ResqueはRuby製の有名なジョブキューである
  • Resqueワーカーの仕事は、起動してアプリケーション環境を読み込んだらRedisに接続し、保留中のバックグラウンド・ジョブの実行を予約すること
  • Resqueワーカーはメモリ管理のためにfork(2)を使っている。Resqueはfork(2)を使うことで、ワーカープロセスのメモリ使用量が肥大化しないようにしている。Resqueがジョブを実行した後、メモリの使用状況は毎回ジョブの処理を行う前のきれいな状態に戻っている。メモリ解放の仕組みであるGCガベージコレクション)には課題があるため、fork(2)を使う方がメモリの使用量を抑えることができる
 

付録B Unicornのワーカープロセスの管理

  • Unicornは可能な限り仕事をカーネルに任せようとするWebサーバである
  • Unicornはパフォーマンスも信頼性も高く、GithubなどのRubyで作られた巨大なWebサイトでも数多くの採用事例がある
  • Unicornは大きく分ければpreforkサーバというカテゴリに属する。Unicornを起動する際にはワーカープロセスがいくつ必要なのかをUnicornに伝える必要がある。Unicornは起動するとまず、ネットワークソケットを初期化してアプリケーションをロードし、fork(2)を使ってワーカープロセスを生成する。
  • Unicornのマスタープロセスは、ワーカープロセスの死活監視をしたり、ワーカーがリクエストの処理に時間がかかりすぎていないかを検査する
 

付録C preforkサーバ

  • preforkは複数のプロセスを個別に生成するよりもメモリを効率的に使うことができる
  • 例えば、Unicornのワーカーを10個立ち上げるには11個のプロセスが必要になる。そのうち1つのプロセスがマスターとなり、他の10個のワーカープロセスの子守りをする。Unicornは起動時にマスタープロセスだけがRailsをロードするため、カーネルリソースの取り合いは発生しない
  • マスタープロセスはRailsをロードするのに3秒ほどかかるが、プロセスを10回フォークするのには、さほど時間はかからない。マスタープロセスはRailsを読み込むことで70MBのメモリを消費するが、コピー・オン・ライトのおかげで、子プロセスはマスタープロセスが使用しているのと同じデータについてはメモリを一切消費しなくて済む
 

おわりに

いかがでしたでしょうか。馴染みのない言葉ばかり出てくるので難しいですよね。

粘り強く読書を継続して、知識をつけていきましょう、、、!

 

引き続き、こちら(↓)の記事で紹介した本を順番にアウトプットしていく予定です。

ysk-pro.hatenablog.com

是非参考にしてみてくださいー!

来週もよろしくお願いします! 

【技術書メモ】体系的に学ぶ 安全なWebアプリケーションの作り方 第2版 〜毎週アウトプットチャレンジ④〜

毎週 1冊技術書を読んでブログでアウトプットするチャレンジの第4弾ですーー!

今回は、体系的に学ぶ 安全なWebアプリケーションの作り方 第2版 脆弱性が生まれる原理と対策の実践 を読みました。

本書はWebアプリケーションの脆弱性に関する名著であり、2018/6/20に第2版が発売されました。

少し長くなってしまいましたが、頑張ってまとめましたので是非読んでみてください。

f:id:ysk_pro:20180813150939j:plain

1 Webアプリケーションの脆弱性とは

- 脆弱性とは悪用できるバグ

- 脆弱性が生まれる理由

    - バグ

    - チェック機能の不足

 

3 Webセキュリティの基礎

3-1 HTTPとセッション管理

- 秘密情報をPOSTで送信すべき理由(GETのリスク)

    - URL上に指定されたパラメータがReferer経由で外部に漏洩する

    - URL上に指定されたパラメータがアクセスログに残る

    - パラメータ付きのURLを利用者がソーシャルネットワークなどで共有してしまう

- hiddenパラメータは利用者は書き換えることができるが、三者からの書き換えに対しては堅牢

- クッキーは少量のデータをブラウザ側で覚えておけるものだが、アプリケーションデータを保持する目的では次の理由から行われない

    - クッキーが保持できる値の個数や文字列長に制限がある

    - クッキーの値は利用者本人には参照・変更できるので、秘密情報の格納に向かない

- クッキーには整理番号としてセッションIDを格納し、実際の値はサーバー側に管理する方法がよく取られる

- セッションIDに求められる要件は次の通り

    - 第三者がセッションIDを推測できない

    - 第三者からセッションIDを強制されない

    - 第三者にセッションIDが漏洩しない

- セッションIDは自作せず、Webアプリケーション開発ツールで提供されるセッションIDを利用すべき

- Secure属性をつけたクッキーはhttps通信の場合のみサーバーに送信される

- HttpOnly属性は、JavaScriptからアクセスできないクッキーを設定するもの

 

3-2 受動的攻撃と同一オリジンポリシー

- 受動的攻撃とは、攻撃者がサーバーを直接攻撃するのではなく、Webサイトの利用者に罠を仕掛けることにより、罠を閲覧したユーザを通じてアプリケーションを攻撃する手法

- 同一オリジンポリシーとは、JavaScriptなどのクライアントスクリプトからサイトをまたがったアクセスを禁止するセキュリティ上の制限

 

4 Webアプリケーションの機能別に見るセキュリティバグ

4-1 Webアプリケーションの機能と脆弱性の対応

- 脆弱性には処理に起因するものと出力に起因するものがあり、出力に起因するものはインジェクション系脆弱性と呼ばれる

 

4-2 入力処理とセキュリティ

- Webアプリケーションの入り口では、入力の文字エンコーディング検証と変換、入力値のチェックを実施する。これらはセキュリティに対する根本的な対策ではないが、プラットフォームやアプリケーションに潜在的脆弱性があった場合のセーフティネットとして作用する 

 

4-3 表示処理に伴う問題

- XSS脆弱性の対策としては、表示の際にHTMLで特殊な意味を持つ記号文字(メタ文字)をエスケープすることが有効

- XSSに対する保険的対策

    - X-XSS-Protection レスポンスヘッダの使用:ブラウザのセキュリティ機能を有効にする

    - クッキーにHttpOnly属性を付与する

 

4-4 SQL呼び出しに伴う脆弱性

- SQLインジェクションは、データベース内の任意のデータを漏洩し、書き換えることができるので非常に危険

- SQLインジェクションの確実な対策は静的プレースホルダを利用してSQLを呼び出すこと

    - SQL文中の「?」がプレースホルダで、変数や式など可変のパラメータの場所に埋め込んでおくもの

    - 静的プレースホルダ値のバインド(? に値を割り当てること)をデータベースエンジン側で行うプレースホルダの状態でSQL文がコンパイルされるため、後からSQL文が変更される可能性はない

    - 動的プレースホルダはアプリケーション側のライブラリ内でパラメータをバインドしてデータベースエンジンに送る方式

 

4-5 重要な処理の際に混入する脆弱性

- クロスサイト・リクエストフォージェリ(CSRF)は、重要な処理の前に利用者のリクエストであることを確認する処理が抜けている場合に、罠のサイトを閲覧しただけで利用者のブラウザから勝手に重要な処理を実行されられる脆弱性

- CSRFの対策は、利用者の意図したリクエストであることの確認で、以下の方法がある

    - トーク埋め込み 〜重要な処理のページに第三者が知り得ないトークンを要求することによって利用者を識別する

    - パスワード再入力

    - Referer確認

- クリックジャッキングはiframe要素とCSSを巧妙に利用することで、透明にした攻撃対象ページと罠のサイトを重ね合わせ、利用者が気づかないうちに攻撃対象サイトでのうリックを誘導する攻撃手法

    - 主要ブラウザで採用されているX-Frame-Optionsを有効にすることで対策ができる 

 

4-6 セッション管理の不備

- セッションの固定化攻撃の対策としては、認証後にセッションIDを変更する方法がある 

 

4-7 リダイレクト処理にまつわる脆弱性

- パラメータにより指定した任意のドメインにリダイレクトできる脆弱性をオープンリダイレクト脆弱性と呼び、フィッシングに悪用される

- オープンリダイレクト脆弱性の対策としては、リダイレクト先のURLを固定にすればよい

- HTTPヘッダ・インジェクションの原因は外部から指定された改行をそのまま出力することで、HTTPヘッダ出力部分を自分で作らずにヘッダ出力用のライブラリやAPIを利用することで対策ができる 

 

4-8 クッキー出力にまつわる脆弱性

- クッキーにSecure属性をつけていないと、平文で送信されて盗聴される可能性がある 

 

4-9 メール送信の問題

- メールのメッセージヘッダに外部から改行を追加されることがメールヘッダ・インジェクションの原因となり、対策にはメール送信に専用のAPIやライブラリを用いることが有効 

 

4-10 ファイルアクセスにまつわる問題

- ディレクトリ・トラバーサル脆弱性とは、外部からパラメータの形でサーバー上のファイル名を指定できるWebアプリケーションでファイル名のチェックが不十分な場合にアプリケーションの意図しないファイルが閲覧・改ざんされてしまう脆弱性

- ディレクトリ・トラバーサル攻撃の対策としては、外部からファイル名が指定できる仕様を避けることが有効 

 

4-10 OSコマンド呼び出しの際に発生する脆弱性

- OSコマンド・インジェクションの対策としては、OSコマンドを呼び出さない実装方法を選択することが有効 

 

4-11 ファイルアップロードにまつわる問題

- Webアプリケーションのアップロード機能に対して大量のデータを送信することで、
Webサイトに過大な負荷をかけるDoS攻撃があり、対策にはアップロードファイルの容量制限が有効 

 

4-12 インクルードにまつわる問題

- require・ includeなどでソースの一部を外部から指定できる場合、アプリケーションが意図しないファイルを指定することにより脆弱性が生まれることがあり、対策としてはインクルードするパス名に外部からのパラメータを含めないことが有効

 

4-16 Web API実装における脆弱性

- APIにおいてJSON文字列生成時のエスケープ処理に不備があると、意図しないJavaScriptJSONデータに混入する脆弱性があり、対策としては信頼できるライブラリを用いてJSONを生成することが有効

 

5 代表的なセキュリティ機能

5-1 認証

- パスワードを桁数や文字種類などで厳しくチェックしすぎると、かえって安全なパスワードをつける利用者のモチベーションを下げてしまうことがある

- オンラインでのブルートフォース攻撃への対抗策としてはアカウントロックが有効。10回程度パスワードを間違えたらアカウントロックがかかり、ロックから30分経過した場合は自動的に解除される、というような実装がされることが多い

 

5-2 アカウント管理

- メールアドレスの受信確認は、①メールにトークン付きURLを添付してそのURLから処理を継続する、②メールアドレスを入力した後にトークン(確認番号)入力画面に遷移し、トークンはメール送信される、の2パターンある。①がよく使われるが、メール記載のURLを利用者に閲覧させるという習慣はフィッシング対策上よくないので、筆者は②を推奨している

- 外部からの自動操作により大量に新規ユーザを作成されることを防ぐため、「私はロボットではありません」にチェックしてもらう等のCAPTCHAがよく利用される

- パスワードを変更する際は、現在のパスワードを照合する。これによりセッションハイジャックされた状態で第三者がパスワードを変更することを防止できる

- メールアドレス変更時のメール通知は新旧両方のメールアドレスに対して行う。これは第三者に不正にメールアドレスを変更された場合に正当なユーザが気づけるようにするため 

 

5-3 認可

- 認可制御の実装がきちんとされていないと、情報リソースのURLを知っているだけで認証なしで情報が閲覧できてしまう

- 認可制御の不備の原因の多くは画面の制御のみで認可制御を実装しているつもりになっていることであり、操作に先立ってこの機能を実行してよいユーザであるかを確認する必要がある

- ユーザ情報は、外部から書き換えできないセッション変数に保持する。書き換えができるクッキーやhiddenパラメータなどに保持しない 

 

5-4 ログ出力

- ログに記録すべきイベントは多すぎても少なすぎてもダメで、ログの使用目的から決定すべき。一般的には以下の認証・アカウント管理・重要な情報の操作をログ出力することが多い

    - ログイン・ログアウト(失敗も含む)

    - アカウントロック

    - ユーザ登録・削除

    - パスワード変更

    - 重要情報の参照

    - 重要な操作(物品の購入、送金、メール送信など)

- ログの出力項目は、4W1H(いつ、誰が、どこで、何を、どのように)に従った以下の項目を取得する

    - アクセス日時

    - リモートIPアドレス

    - ユーザID

    - アクセス対象(URL、ページ番号、スクリプトIDなど)

    - 操作内容(閲覧、変更、削除など)

    - 操作対象(リソースIDなど)

    - 操作結果(成功あるいは失敗、処理件数など)

- ログの出力先にはデータベースやファイルがよく用いられるが、ログの保護という観点からはログ専用のサーバーを用意することが望ましい 

 

6 文字コードとセキュリティ

- 文字コードの扱いに問題があると文字列処理にバグが生じ、脆弱性の原因になる

- 対策としてはアプリケーション全体の文字エンコーディングUTF-8で統一することが推奨されている 

 

7 脆弱性診断入門

- 開発時に脆弱性を作り込まないように気をつけていても脆弱性は混入してしまう可能性が高い。プログラミングにおいて機能を実装したら必ずテストをするのと同じように、脆弱性がないこともテストで確認する必要があり、それが脆弱性診断である

 

8 Webサイトの安全性を高めるために 

- Webサーバーがマルウェアに感染する経路は、メールが9割

- Webサーバーマルウェア対策としては、サーバーの脆弱性対処をタイムリーに行うことや、クライアントPCに最新のセキュリティパッチを導入することが有効

 

9 安全なWebアプリケーションのための開発にマネジメント

- 安全なアプリケーション開発のために費用対効果が高いのは開発標準(セキュリティガイドライン)の整備

- 開発標準に記載すべき重要項目は以下の通り

    - 脆弱性毎の対処方法

    - 認証、セッション管理、ログ出力などの実装方法

    - 各フェーズでのレビューとテストの方法(いつ、誰が、何を、どうやって)

    - 公開判定基準(誰が、いつ、どの基準で許可するか)

- セキュリティ機能は最終的にテストにより要件を満たすことを確認する必要がある。セキュリティテスト(脆弱性検査)の方法には、専門家に依頼する、専用ツールで診断する、などの方法がある

 

おわりに

ここまで読んでいただきありがとうございます。

Webアプリケーションの脆弱性については、実務では必須の知識なので(僕の会社でも現在進行形でこの本の勉強会を毎週しています)ご興味ある方は是非読んでみることをおすすめしますー!

来週も頑張ります!

【技術書メモ】安全なウェブサイトの作り方・安全なSQLの呼び出し方 〜毎週アウトプットチャレンジ③〜

毎週 1冊技術書を読んでブログでアウトプットするチャレンジの第三弾です〜!

今回は、安全なウェブサイトの作り方安全なSQLの呼び出し方(短いので2冊で1冊扱い)を読みました。

どちらもIPA独立行政法人 情報処理推進機構)が無料で公開しています。

f:id:ysk_pro:20180805204003j:plain

# はじめに

脆弱性対策には、根本的解決と保険的解決がある

根本的解決

- 脆弱性を作り込まない実装

- 根本的解決を実装することでその脆弱性を狙った攻撃を無効化できる

保険的対策

- 攻撃の影響を軽減する対策

- 根本的解決と違い、脆弱性の原因そのものを無くすものではないが、攻撃の影響を軽減できる
- 根本的解決の実装に漏れが生じる場合、保険的対策はセーフティネットとして機能するので、根本的解決と保険的対策を組み合わせるのが有効

 

1. ウェブアプリケーションのセキュリティ実装

設計や実装レベルでの対策

1) SQLインジェクション

根本的解決

- SQL文の組み立ては全てプレースホルダで実装する

- SQL文の組み立てを文字列連結で行う場合は、エスケープ処理を行うデータベースエンジンのAPIを用いて、SQL文のリテラルを正しく構成する

保険的対策

- エラーメッセージをそのままブラウザに表示しない 〜 攻撃者への手がかりを与えてしまう

- データベースアカウントに適切な権限を与える 〜 データベースに接続するアカウントの権限が必要以上に高いと攻撃による被害が深刻化する恐れがある

 

2) OSコマンド・インジェクション

- WebサーバのOSコマンドを不正に実行されてしまう問題

根本的解決

- シェルを起動できる言語機能の利用を避ける

保険的対策

- シェルを起動できる言語機能を利用する場合は、その引数を構成する全ての変数に対してチェックを行い、あらかじめ許可した処理のみを実行する

 

3) パス名パラメータの未チェック/ディレクトリ・トラバーサル

- パラメータにファイル名を指定しており、ファイル名指定の実装に問題がある場合、公開を想定していないファイルを参照されてしまう恐れがある

根本的解決

- 外部からのパラメータでWebサーバ内のファイル名を直接指定する実装は避ける

- ファイルを開く際は固定のディレクトリを指定し、かつファイル名にディレクトリ名が含まれないようにする

保険的対策

- Webサーバ内のファイルへのアクセス権限の設定を正しく管理する

- ファイル名のチェックを行う

 

4) セッション管理の不備

- セッションIDの発行や管理に不備がある場合、悪意のある人にログイン中の利用者のセッションIDを不正に取得され、その利用者になりすましてアクセスされてしまう可能性がある

根本的解決

- セッションIDを推測困難なものにする

- セッションIDをURLパラメータに格納しない

- HTTP通信で利用するCookieにはsecure属性を加える 〜 secure属性が設定されたCookieHTTPS通信のみで利用できる

- ログイン成功後に、新しくセッションを開始する

- ログイン成功後に既存のセッションIDとは別に秘密情報を発行し、ページ遷移ごとにその値を確認する

保険的対策

- セッションIDを固定値にしない

- セッションIDをCookieにセットする場合、有効期限の設定に注意する

 

5) クロスサイト・スクリプティング

- スクリプトを埋め込むことが可能な脆弱性がある場合、利用者のブラウザ上でスクリプトが実行される可能性がある

根本的解決

- Webページに出力するすべての要素に対して、エスケープ処理を施す

- URLを出力するときは、http://・https://で始まるもののみ許可する〜 javascript:の形式で始まるURLはクロスサイト・スクリプティング攻撃が可能になる場合がある

- <script>...</script>要素を動的に生成しない

- スタイルシートを任意のサイトから取り込めるようにしない

- HTTPレスポンスヘッダのContent-Typeフィールドに文字コード(charset)を指定する

保険的対策

- 入力値の内容チェックを行う

- Cookie情報の漏えい対策として、発行するCookieにHttpOnlyを加え、TRACEメソッドを無効化する

- クロスサイト・スクリプティング潜在的脆弱性対策として有効なブラウザの機能を有効にするレスポンスヘッダを返す

 

6) CSRF(クロスサイト・リクエスト・フォージェリ)

- ログインした利用者からのリクエストについて、その利用者が意図したリクエストであるかどうかを識別する仕組みを持たないwebサイトは、外部サイトを経由した悪意あるリクエストを受け入れてしまう場合がある

根本的解決

- 処理を実行するページPOSTメソッドでアクセスするようにし、そのhiddenパラメータに秘密情報が挿入されるよう、前のページを自動生成して、実行ページではその値が正しい場合のみ処理を実行する

- 処理を実行する直前のページで再度パスワードの入力を求め、実行ページでは再度入力されたパスワードが正しい場合のみ処理を実行する

- Refererが正しいリンク元かを確認し、正しい場合のみ処理を実行する 〜 Refererを確認することで、本来の画面遷移を経ているかどうかを確認できる

保険的対策

- 重要な操作を行った際に、その旨を登録済みのメールアドレスに自動送信する

 

7) HTTPヘッダ・インジェクション

- HTTPレスポンスヘッダのフィールド値を外部から渡されるパラメータ等を利用して動的に生成する実装に対して、レスポンス内容に任意のヘッダフィールドを追加する攻撃

根本的解決

- ヘッダの出力を直接行わず、webアプリケーションの実行環境や言語に用意されているヘッダ出力用APIを使用する

- 改行コードを適切に処理するヘッダ出力用APIを利用できない場合は、改行を許可しないように開発者自身で適切な処理を実装する 〜 HTTPヘッダは改行によって区切られる構造になっており、改行を許すと任意のヘッダフィールドや任意のボディを注入されたり、レスポンスを分割されたりする原因となる

保険的対策

- 外部からの入力の全てについて、改行コードを削除する

 

8) メールヘッダ・インジェクション

- メール送信機能を持つwebアプリケーションにおいて、管理者が設定した本来固定のメールアドレスではない宛先にメールを送信され、迷惑メールの送信に悪用される

根本的解決

- メールヘッダを固定値にして、外部からの入力は全てメール本文に出力する 〜 to, cc 等のメールヘッダの内容が外部からの入力に依存する場合、外部から与えられた改行コードが差し込まれてしまい、任意のメールヘッダの挿入や、任意の宛先へのメール送信に悪用される原因になる

- メールヘッダを固定値にできない場合、webアプリケーションの実行環境や言語に用意されているメール送信用APIを使用する

- HTMLで宛先を指定しない

保険的対策

- 外部からの入力の全てについて、改行コードを削除する

 

9) クリックジャッキング

- ログインしている利用者のみが使用可能な機能を、細工された罠ページを重ね合わせてクリックさせることにより、意図せず実行させる

根本的解決

- HTTPレスポンスヘッダに、X-Frame-Optionsヘッダフィールドを出力し、他ドメインのサイトからのframe要素やiframe要素による読み込みを制限する

- 処理を実行する直前のページで再度パスワードの入力を求め、実行ページでは再度入力されたパスワードが正しい場合のみ処理を実行する

保険的対策

- 重要な処理は、一連の操作をマウスのみで実行できないようにする

 

10) バッファオーバーフロー

- プログラムが入力されたデータを適切に扱わない場合、プログラムが確保したメモリの領域を超えて領域外のメモリを上書きして、意図しないコードを実行してしまう可能性がある

根本的解決

- 直接メモリにアクセスできない言語で記述する 〜 Rubyはメモリに直接アクセスできないため、バッファオーバーフローの問題は発生しない

- 直接メモリにアクセスできる言語で記述する部分を最小限にする

- 脆弱性が修正されたバージョンのライブラリを使用する

 

11) アクセス制御や認可制御の欠落

根本的解決

- アクセス制御機能による制御措置が必要とされるwebサイトには、パスワード等の秘密情報の入力を必要とする認証機能を設ける

- 認証機能に加えて認可制御の処理を実装し、ログイン中の利用者が他人になりすましてアクセスできないようにする 〜 認可とはどの利用者にどの操作を許可するか制御すること

 

2. ウェブサイトの安全性向上のための取り組み

運用レベルでの対策

1) Webサーバに関する対策

- OSやソフトウェアの脆弱性情報を継続的に入手し、脆弱性への対処を行う

- 公開を想定していないファイルを、web公開用のディレクトリ以下に置かない

 

2) DNSに関する対策

- DNSによりドメイン名を指定するだけで、該当するwebサイトへのアクセスやメールの送受信が可能になってしまう

- DNSソフトウェアの更新や設定を見直す

 

3) ネットワーク盗聴への対策

- 通信や情報が暗号化されていない場合、盗聴によって取得された情報が悪用される可能性がある

- webサイトの通信を暗号化する手段として、SSLを用いたHTTPS通信がある

- 利用者へ通知する重要情報は、メールで送らず暗号化されたhttps:// のページに表示する

 

4) フィッシング詐欺を助長しないための対策

- EV SSL証明書を取得し、サイトの運営者が誰であるかを証明する

- 利用者がログイン後に移動するページをリダイレクト機能で動的に実装しているウェブサイトについて、リダイレクト先のURLとして使用されるパラメータの値には自サイトのドメインのみを許可するようにする

 

5) パスワードに関する対策

- 入力後の応答メッセージが認証情報の推測のヒントとならない工夫をする

- ユーザIDもしくはパスワードが違います、というような表示をすることで、ヒントを与えないようにする

- パスワードをサーバ内で保管する際は、平文ではなくソルト付きハッシュ値の形で保管する

- ソルトとは乱数等により利用者毎に異なる文字列を生成すること

 

6) WAFによるwebアプリケーションの保護

- WAF(Web Application Firewall)はHTTP(HTTPS)を検査し、攻撃等の不正な通信を自動的に遮断するソフトウェア・ハードウェア

- webアプリケーションの改修が困難な状況でWAFが有効

 

おわりに

これら内容は分かっていないとwebエンジニアとして話にならないと思うので早く身につけます…!!

こちら(↓)の記事で紹介した本を順番にアウトプットしていく予定ですー!

ysk-pro.hatenablog.com

参考にしてみてください〜!

来週も頑張ります!