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?

【セキュリティ】Copyparty の k304 は何者なのか?

0
Posted at

はじめに

― CVE-2023-38501 を引き起こした“内部パラメータ”の正体 ―

Web アプリの脆弱性というのは、往々にして「本来ユーザーに触らせるつもりがなかった機能」が外に漏れたときに生まれます。今回の主人公 k304 もまさにその典型例。
CVE-2023-38501 で悪用されたこのパラメータは、一体何をするために存在していたのでしょうか?


1. k304 は「304 Not Modified」制御のための内部キー

Copyparty はアップロード機能のあるファイルサーバーで、ブラウザからのアクセスに対して、
キャッシュが使える場合は 304 Not Modified を返す 仕組みを持っています。

その内部判定の一部として利用されているのが k304

本来の目的はひと言でいうと:

「ブラウザとのキャッシュ比較のためのタグ値(ETag 相当)」をやり取りするためのキー

つまり、ユーザーが触る予定など一切なかった「サーバー内部の調整用パラメータ」です。


2. なぜ外部に露出していたのか?

Copyparty は GET パラメータをそのまま受け取り、
k304=xxx が送られてきたら、その値をヘッダの ETag 相当に書き込む」
という実装をしていました。

問題はその 値をサニタイズしないまま、HTTP レスポンスヘッダに出力していた こと。
パッチ前(v1.8.6 以前)の set_k304 は、ほぼ 1 行だけでした:GitHub

ざっくり書き直すと、イメージはこんな感じです:

def set_k304(self) -> bool:
    ck = gencookie("k304", self.uparam["k304"], self.args.R, False, 86400 * 299)
    self.out_headerlist.append(("Set-Cookie", ck))
    self.redirect("", "?h#cc")
    return True

ポイント:

  1. self.uparam["k304"]
    → クエリパラメータ ?k304=... がそのまま入る
  2. それを gencookie() に渡して Set-Cookie ヘッダを生成
  3. out_headerlist に追加され、send_headers() でレスポンスヘッダとして送信

つまり 「ユーザーが指定した文字列が header の一部(Set-Cookie 値)としてそのまま出力される」 状態です。

結果──
攻撃者が k304CRLF (%0D%0A) を注入すると、
レスポンスヘッダが意図せず途中で終了し、
続きが 攻撃者指定の HTML としてブラウザへ到達 します。

これがまさに HTTP Response Splitting → Reflected XSS のルート。


3. k304 を悪用した攻撃の流れ

攻撃者が以下の URL を踏ませるだけで:

?k304=y%0D%0A%0D%0A<img src=copyparty onerror=alert(1)>

サーバーは次のようなレスポンスを返します:

HTTP/1.1 200 OK
Content-Type: text/html
ETag: y

<img src=copyparty onerror=alert(1)>

ETag: の直後でレスポンスヘッダが強制的に終了し、
攻撃者が差し込んだ <img ...>レスポンスボディとして解釈され、XSS が実行 されます。

もはや「304 のための ETag」などどこかへ吹き飛び、
ただの 攻撃者の自由入力欄 と化してしまったわけですね。


4. 脆弱性の本質:内部機能の“漏洩”

この脆弱性が示すものはとてもシンプルで、しかし非常に重要です。

内部用パラメータを URL クエリから直接変更できるようにすると、攻撃者に「サーバーの内部スイッチ」をプレゼントしてしまう。

  • サーバー側が「ここはユーザーに触られないはず」と思っていた
  • しかし実際には GET パラメータとして誰でも操作できた
  • しかも出力が無検証だった
    → 当然 XSS となる

まさに 信頼境界の崩壊 が起きた例です。


5. どうやって防ぐべきだったのか?

防御策は3つの観点で語れます。

① 内部パラメータを公開しない

そもそも GET パラメータとして受け取る必要がない
内部ロジック専用の値はユーザー入力と同じチャンネルに置かない。

② HTTP ヘッダに出力する値は必ずサニタイズする

CRLF(改行)を含めない検証は最低限必要。
Header Injection は古典的だがいまだに強烈。

③ 設計段階で「外部から触れない前提」を作らない

「ユーザーが使わないはず」という前提は攻撃者には通じません。


6. 攻撃者から見た k304 の魅力

攻撃者視点から見ると、k304 はこう見えていたはず。

  • 出力位置が HTTP レスポンスヘッダ直後(これは超いいポジション)
  • 値が一切フィルタされない(CRLF 入れ放題)
  • HTML を自由に出せる(即 XSS)

「反射型 XSS 自動販売機」のような状態です。


まとめ

項目 説明
k304 の正体 304 判定のための内部キャッシュパラメータ
なぜ危険? ヘッダにそのまま出力され、CRLF で改行注入される
結果 HTTP Response Splitting → Reflected XSS
本質 内部ロジックが外部入力に漏れた典型例

アプリ開発では「外部から触られないはず」という思い込みが最も恐ろしい。
今回の事件は、そのことを静かに、でも強烈に教えてくれます。


リンク

https://www.exploit-db.com/exploits/51635
https://github.com/9001/copyparty

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?