OWASP Top 10 を通じて、Webアプリケーションのセキュリティを学び直しています。
今回は、Cryptographic Failures(暗号化の失敗)についてまとめます。

Laravelアプリケーション開発時の対策や、バイブコーディング(生成AIコーディング)でも役立つ対策も考えていきますね。
*本記事では、執筆時点で最新版のOWASP Top 10: 2021の内容をもとにしています。
A02:2021 – Cryptographic Failures(暗号化の失敗)
Cryptographic Failures(暗号化の失敗)について、公式説明ページはこちら:
パスワードや個人データなど流出してはいけないデータは、暗号化して保存します。
ですが、この暗号化の方法が古かったり、簡単に推測できたりすると、大事なデータが流出してしまいます。
Cryptographic Failures(暗号化の失敗)は、こういったリスクに関する脆弱性をさします。

個人データ・機密データ流出による損害と信頼失墜を考えると、おそろしい限りですね。
CWE(共通脆弱性タイプ)
このカテゴリーに含まれる主なCWE(脆弱性分類)は次のとおりです。
-
CWE-259:ハードコードされたパスワード
-
パスワードをプログラムコードに直接書いてしまう
-
-
CWE-327:不適切な暗号化アルゴリズム
- 古かったり、弱かったりする暗号化方式を使い続けている
-
CWE-331:不十分なエントロピー(ランダム性)
- パスワードやトークンを生成する際、予測しやすいパターンを使ってしまう
対策
このリスクに対して、下記のような対策が挙げられます。
-
データを分類する
扱うデータを分類し、法律や社内ルールに沿って機密データを特定する。 -
不要な機密データは保存しない
必要な期間を過ぎたらすぐ削除。できるだけ保存しない。 -
保存するときは暗号化する
データをサーバーなどに保存する際は、必ず暗号化して守る。 -
強力で最新の暗号を使う
古い方式を避け、最新の安全なアルゴリズム・鍵・設定を使う。
鍵の管理(生成・保存・更新)も正しく行う。 -
通信中のデータも暗号化する
TLSなど安全な通信方式を使い、サーバー側で暗号設定を優先させる。
HSTSなどを設定して、常に暗号化通信を強制する。 -
機密データをキャッシュしない
ブラウザや中継サーバーに一時保存されないよう、キャッシュを無効にする。 -
データの種類に応じて対策を変える
分類したデータごとに、必要なセキュリティ対策を適用する。 -
古い通信プロトコルを使わない
FTPやSMTPなど、暗号化されていない古い通信方法で機密データを送らない。 -
パスワードは安全なハッシュで保存する
bcrypt、scrypt、Argon2などの強力な方式を使い、ソルトを付けて保存する。 -
初期化ベクトル(IV)を正しく扱う
暗号モードに応じて、CSPRNG(安全な乱数生成器)で作る。
同じ鍵で同じIVを二度使わない。 -
「認証付き暗号化」を使う
単なる暗号化ではなく、認証付き暗号を利用する。 -
鍵は安全に作り、安全に使う
鍵は暗号的に安全な方法でランダム生成し、バイト配列として保持する。
パスワードを使う場合は、鍵導出関数(PBKDF2など)で鍵に変換する。 -
安全な乱数を使う
暗号処理では必ず安全な乱数(CSPRNG)を使い、予測されないようにする。
最近のAPIは自動で安全な設定になっていることが多い。 -
古い暗号やハッシュを使わない
MD5、SHA1、PKCS#1 v1.5 などの古い方式は避ける。 -
設定を確認・検証する
暗号や通信設定が本当に安全に動作しているか、第三者による確認やテストを行う。
*分かりやすく書きなおしていますが、正確な元文章を確認したい場合は、こちらご覧ください。
Laravelでの対策
「そういわれても、具体的に何をしたら」という方のために、Laravelでの関連する対策・技術をまとめます。
暗号化
Laravelの暗号化サービスは、OpenSSL経由でAES-256およびAES-128暗号化を使用しています。
暗号化の際に使われる「キー」は、.envのAPP_KEYに設定します。通常はインストール時に自動で生成されます。デフォルトでは、より安全なAES256用のキーの長さとなっています。
AES-256は、非常に強力な暗号化アルゴリズムです。
暗号化を行う際には、Cryptファサードを使います。encrypt()ヘルパ関数を使うこともできます。
【暗号化の例】
|
1 2 3 4 5 6 7 8 |
public function store(Request $request): RedirectResponse { $request->user()->fill([ 'token' => Crypt::encryptString($request->token), ])->save(); return redirect('/secrets'); } |
Laravelの暗号化について詳細はこちら。
ハッシュ化
Laravelは、【対策】にも挙げられていた安全なBcryptとArgon2ハッシュをサポートしています。
Laravelアプリケーションスターターキットを使用している場合は、登録と認証時のパスワード保存時には、デフォルトでBcryptが使用されます。
【ハッシュ化の例】
|
1 2 3 4 5 6 7 8 9 10 |
public function update(Request $request): RedirectResponse { // Validate the new password length... $request->user()->fill([ 'password' => Hash::make($request->newPassword) ])->save(); return redirect('/profile'); } |
通信の暗号化(HTTPS化)
通信の暗号化(HTTPS化)は、基本的に サーバー側で行います。
本番環境にデプロイする際には、.htaccess ファイル(Apache)や nginx.conf(Nginx)などで、HTTP から HTTPS へのリダイレクト設定を行いましょう。
*ロードバランサーの背後でアプリケーションを実行している場合は、TrustProxies ミドルウェアを設定する必要があります。
バイブコーディングでも役立つ全般的な注意点
バイブコーディング(生成AIコーディング)では、AIが基本的なセキュリティコードは書いてくれます。ただし、生成されたコードのチェックは必要です。
また技術的な実装以前に、設計段階での判断がとても重要です。具体的には、下記について考えておく必要があります。
- どういったデータを扱っているのか分類する
-
必要なければ、機密データ/個人データはデータベースに保存しない
その上で、機密データを保存せねばならない時は、適切に暗号化を行っていきます。
さいごに
パスワードや機密データが漏れると一発アウトといいますか、かなり怖い事態。
不必要に個人データ・機密データを保存しない。シンプルながら、これが最も大事ですよね。
たとえば、Stripe を利用する場合は、支払い処理を Stripe側で完結させる設計 にすれば、Webアプリのデータベースに クレジットカード番号を保存しない で済みます。

ここはしっかりと「人」が決めていく部分です。技術面だけでなく、やはりこういった設計は重要ですね。

-120x68.png)