Socket.IO: Engine.IOプロトコルのバージョン不一致によるDoS攻撃
### 影響
Engine.IO / Socket.IOサーバーにおいて、トランスポートのアップグレードを許可する機能に、サービス拒否の脆弱性が存在します。
Engine.IOプロトコルのバージョンは、初期のハンドシェイク中にネゴシエーションされ、セッションに保存されますが、新たに作成されたトランスポート、特にWebSocketのアップグレードトランスポートは、アップグレードリクエストのクエリパラメータから、独立して異なるプロトコルバージョンを決定する可能性があります。サーバーは、アップグレードリクエストのプロトコルバージョンが、既存のセッションのプロトコルバージョンと一致するかどうかを確認していませんでした。
悪意のあるクライアントは、有効なEngine.IOセッションを確立し、その後、異なる、または省略された`EIO`クエリパラメータを含むアップグレードリクエストを送信することで、この不一致を悪用できます。これにより、サーバーは、セッションと一貫性のないパーサーやハートビート動作を持つトランスポートを接続する可能性があります。特定の条件下では、巧妙に作成されたハートビートパケットが、予期しない例外を引き起こし、Node.jsプロセスを終了させる可能性があります。
デフォルトのEngine.IO v4プロトコルを使用しているサーバーに影響があります。Engine.IO v3との互換性が無効になっている場合でも、この問題が発生する可能性があります。これは、省略された`EIO`パラメータが、影響を受けるトランスポートパスでプロトコルv3として解釈されるためです。
影響は、プロセスクラッシュによる**サービス拒否**です。
影響を受けるバージョン:
- `engine.io >= 6.6.0, < 6.6.10`
## 修正
この問題は、以下のバージョンで修正されました。
- **engine.io 6.6.10**
ユーザーは、`engine.io@6.6.10`以降にアップグレードする必要があります。
Engine.IOに依存するSocket.IOパッケージを使用している場合は、修正されたEngine.IOバージョンを含むSocket.IOのリリースに更新する必要があります。
### 対策
すぐにアップグレードできない場合は、トランスポートのアップグレードを無効にすることで、リスクを軽減できます。
```javascript
const io = new Server(httpServer, {
allowUpgrades: false
});
```
または、WebSocketのみなど、単一のトランスポートのみを許可することもできます。
```javascript
const io = new Server(httpServer, {
transports: ["websocket"]
});
```
これらの対策は、脆弱なアップグレード経路を回避しますが、クライアントの互換性や接続動作に影響を与える可能性があります。
追加の一時的な対策として、展開環境では、既存の`sid`に対するEngine.IOリクエストで、`EIO`クエリパラメータが欠けている場合、または初期ハンドシェイクで使用されたプロトコルバージョンと一致しない場合に、リクエストを拒否する可能性があります。ただし、この対策は、展開環境がセッションでネゴシエートされたプロトコルを確実に追跡できる場合に限り、アプリケーションプロキシまたはミドルウェア層でのみ実施するのが最適です。
アップグレードは、依然として推奨される解決策です。
影響を受けるパッケージ:
- npm (JavaScript) engine.io: 影響を受けるバージョンは 6.6.0 以降、6.6.10 未満。6.6.10 で修正済み。