Twisted IRCサーバーにおける認証なしのリモートDoS脆弱性:バッファオーバーフロー

## 概要

Twisted words IRCサーバーにおけるバッファオーバーフローの脆弱性(CWE-770)により、認証されていないリモートクライアントがサーバーのメモリを枯渇させることが可能です。`twisted.words.protocols.irc.IRC.dataReceived`は、受信したすべてのバイトを接続ごとのバッファに追加し、改行文字が現れるまでデータを削除しますが、最大長は設定されていません。`IRC`が単純な`Protocol`であり`LineReceiver`ではないため、改行文字なしでバイトを送信する接続があると、バッファが無限に増加し、シングルスレッドプロセス全体がメモリ不足になり、すべてのユーザーが同時に切断されます。`twistd words`サーバーは、`IRCUser`を介してこのメソッドをそのまま継承しており、認証処理の前にデータがバッファリングされます。

## 詳細

`IRC.dataReceived`は、最後の改行文字までのすべてのデータを`self.buffer`に保持します。

```python
# twisted/words/protocols/irc.py
class IRC(protocol.Protocol): # LineReceiverではないため、MAX_LENGTHはない
buffer = ""
def dataReceived(self, data):
if isinstance(data, bytes):
data = data.decode("utf-8")
lines = (self.buffer + data).split(LF)
self.buffer = lines.pop() # 改行文字がない場合、入力全体がバッファに保持される
...
```

データに改行文字が含まれていない場合、`lines.pop()`は累積されたすべての内容を`self.buffer`に返します。そのため、バッファは各チャンクで増加し、制限されません。`IRC`は`MAX_LENGTH`、`lineLengthExceeded`、およびタイムアウトを定義していないため、接続は決して閉じられません。`twistd words`サーバーのプロトコル`IRCUser`は、`IRC`を継承しますが、`dataReceived`をオーバーライドしていないため、認証用の`PASS`、`NICK`、または`USER`を送信する前にバッファが満たされます。

影響を受ける製品:Twisted (`twisted.words`)、`twisted.words.protocols.irc.IRC`およびそのサブクラス`twisted.words.service.IRCUser`
影響を受けるバージョン:26.4.0以前

## PoC

標準的なTwistedのIRCサーバー(`twistd words`というサーバーで、`IRCUser`を使用)において、認証されていないクライアントが単一のTCP接続を開き、改行を含まないデータを継続的に送信します。このデータは、行末が定義されないため、常に不完全な状態で送信されます。送信されたデータはすべて接続の行バッファに追加され、完全な行が形成されないため、バッファは消費されず、送信されたデータ量に応じて増加します。

実際の`IRCFactory`サーバーに対するテストでは、認証されていない単一の接続が60MBの改行を含まないデータを送信すると、サーバープロセスのメモリ使用量が約47MBから2966MBに増加しました(送信された1MBあたり約49MBの増加)。この状態で接続は維持され、制限は発生しませんでした。同様の量のデータを、通常の方法(行末文字付き)で送信すると、メモリ使用量は変化しません。これにより、問題の原因が、行の長さに関する制限がないことに特定されました。

## 影響

認証されていないリモートDoS攻撃(CWE-770)が発生し、制限のないメモリ割り当てにより、制御不能なリソース消費(CWE-400)を引き起こします。単一の認証情報なしの接続が、`twistd words`プロセスのメモリをすべて消費し、1つのプロセスがすべてのユーザーにサービスを提供するため、プロセスがクラッシュすると、すべての接続が同時に切断され、サービスは再起動されるまで停止します。バッファのコピー処理も同様の効果をもたらしますが、より速く発生します。機密性や完全性への影響はなく、コードの実行もありません。

影響を受けるパッケージ:
- pip (Python) Twisted: 影響を受けるバージョンは26.4.0以下、26.10.0rc1で修正済み。