セキュリティ対策の基本 #5 【認証】(覚え書き)

セキュリティ

現代のセキュリティシステムの要、「ユーザ認証」について、わかりやすく解説します。ログイン時に「本当にあなた?」と確認する仕組みは、実はさまざまな方式で構成されているんです。今回は、パスワード認証、チャレンジ・レスポンス方式、そして生体認証の例を、Pythonコードとともに見ていきましょう!

ユーザ認証ってなに?

ユーザ認証とは、システムにアクセスする人や機器が「本当に意図した本人(または正当なもの)」かを確認するプロセスです。関連する用語もおさらいしておきましょう:

  • 識別(Identification)
    ユーザを一意に特定する(例:ユーザID)。
  • 認証(Authentication)
    「本人である」ことを確認するプロセス。
    例:パスワード、PIN、指紋など。
  • 認可(Authorization)
    認証が確認されたユーザに対して、サービスを提供したり権限を付与したりすること。

認証情報の種類

認証方式は大きく3つに分類されます。それぞれの特徴やメリット・デメリットを簡単にご紹介!

A. What-you-have型

(例:IDカード、スマホ、トークン)

  • 長所
    • 乱数などを用いれば安全な認証情報が作れる
    • 認証情報の更新も容易
  • 短所
    • 常に携帯する必要があり、紛失や盗難のリスクあり

B. What-you-know型

(例:パスワード、PIN、パス画像)

  • 長所
    • 所持物を必要とせず、誰でも使いやすい
  • 短所
    • 人間の記憶に依存するため、覚えにくく、推測されやすいリスクがある

C. What-you-are型

(例:指紋、顔、虹彩などの生体認証)

  • 長所
    • ユーザの本質的な特徴を用いるため、なりすましが困難
  • 短所
    • 生体情報は一度盗まれると変更ができない、プライバシーの懸念あり

ユーザ認証のプロセス

認証には大きく分けて登録フェーズ認証フェーズがあります。

  • 登録フェーズ
    ユーザとシステムが認証情報(パスワード、生体情報など)を共有し、後で照合できる状態にする。
  • 認証フェーズ
    ユーザがログインする際に、登録された情報と提示された情報を照合して本人確認を行う。

また、認証の種類としては「1対1認証」(特定のユーザ本人の確認)と「1対n認証」(登録されたユーザの中から誰であるか識別)があり、用途に応じて使い分けられます。

パスワード認証とハッシュ関数(Python例)

import hashlib

def hash_password(password):
    # パスワードをSHA256でハッシュ化
    return hashlib.sha256(password.encode()).hexdigest()

# ★ ユーザ登録時(例:パスワード「mypassword123」)
stored_hash = hash_password("mypassword123")
print("登録されたパスワードのハッシュ:", stored_hash)

# ★ 認証時(ユーザが入力したパスワードをチェック)
input_password = "mypassword123"  # ここはユーザ入力と想定
if hash_password(input_password) == stored_hash:
    print("認証成功!")
else:
    print("認証失敗!")

このように、入力されたパスワードのハッシュと保存されたハッシュを比較することで認証が行われます。

チャレンジ・レスポンス方式で安全な認証

チャレンジ・レスポンス方式は、サーバがランダムなチャレンジ(数字や文字のビット列)を送り、クライアントがそれに秘密情報を組み合わせて計算した結果(レスポンス)を返す方法です。これにより、盗聴されたとしても同じチャレンジが再利用できないため、安全性が向上します。

以下は、シンプルなチャレンジ・レスポンス方式のPython例です。

import hashlib, os

def generate_challenge():
    # ランダムなチャレンジコードを生成
    return os.urandom(16).hex()

def compute_response(challenge, secret):
    # チャレンジと秘密情報を組み合わせ、SHA256ハッシュを計算
    return hashlib.sha256((challenge + secret).encode()).hexdigest()

# クライアントとサーバが共有する秘密情報
secret = "super_secret_password"

# サーバがクライアントにチャレンジコードを送信
challenge = generate_challenge()
print("サーバからのチャレンジ:", challenge)

# クライアント側でレスポンスを計算
response = compute_response(challenge, secret)
print("クライアントのレスポンス:", response)

この仕組みにより、同じチャレンジに対してのみ正しいレスポンスが生成され、リプレイ攻撃などへの対策にもなります。

生体認証(バイオメトリクス)のしくみ

「What-you-are型」認証、すなわち生体認証は、指紋や顔、虹彩といったユーザ固有の生体情報を利用します。
バイオメトリック認証のポイントは:

  • 普遍性:誰もが持っている
  • 唯一性:同じものは存在しない
  • 永続性:時間が経っても基本的に変わらない

例:指紋認証のビット列比較(Python例)

実際、指紋認証では登録された指紋データと、認証時に抽出された指紋データのビットの違いをカウントして、しきい値以下なら「一致」と判断します。

def compare_fingerprints(fp1, fp2):
    # 2つのビット列(文字列)を比較し、異なるビット数をカウント
    differences = sum(1 for a, b in zip(fp1, fp2) if a != b)
    return differences

# 登録されている指紋データ
registered = "1001101101"

# 認証時のサンプル1(ビットの差が1)
sample1 = "1001101110"  
# 認証時のサンプル2(ビットの差が4)
sample2 = "0011001100"  

print("Sample1のビット差:", compare_fingerprints(registered, sample1))
print("Sample2のビット差:", compare_fingerprints(registered, sample2))

このように、しきい値(例:3ビット以下なら一致とみなす)を設定することで、誤認識(FRRやFAR)をコントロールします。

ユーザ認証に対する脅威とその対策

ユーザ認証システムは、さまざまな攻撃手法の標的となります。主な脅威とその対策を見てみましょう。

脅威の例

  • ブルートフォース攻撃
    短時間で総当たり攻撃を試みる手法。
  • 辞書攻撃
    よく使われる単語を組み合わせた攻撃。
  • スニッフィング・リプレイ攻撃
    通信データを盗み取り、その情報を再利用する攻撃。
  • フィッシング
    正規サイトに似せた偽サイトで認証情報を詐取する手法。
  • Man-In-The-Browser攻撃
    ブラウザ内の認証情報を不正に取得・改ざんする手口。

対策

  • 利用者側
    • 複雑で十分な長さのパスワードを設定
    • 定期的なパスワード変更と、他サービスでの再利用を避ける
  • 管理者側
    • 複数回のログイン失敗時にアカウントをロックアウト
    • パスワードの有効期限や長さのポリシーを設定
    • 多要素認証(例:パスワード+生体認証)を導入

CAPTCHAでボット対策

CAPTCHAは、人間と自動プログラム(ボット)を識別するための仕組みです。

  • 原理:人間なら簡単に解けるが、ボットには難しい問題(画像認識や文字認識)を提示する
  • 課題:高度なOCR技術を持つマルウェアやリレー攻撃に対する脆弱性も存在

まとめ

ユーザ認証は、セキュリティシステムの第一関門です。

  • 多様な認証方式(What-you-have, What-you-know, What-you-are)にはそれぞれメリット・デメリットがあり、用途に応じた選択が必要です。
  • 最新の攻撃手法に対応するため、ハッシュ関数、チャレンジ・レスポンス、多要素認証など、さまざまな技術が組み合わされます。
  • CAPTCHAのような仕組みも加えることで、自動プログラムからの攻撃を防ぐ工夫がされています。

セキュリティは日々進化しています。今回の基本的な仕組みや対策を押さえ、自分のシステムやアプリケーションの認証方法を見直してみましょう!

コメント