Cの構造体が不正なSOCKSリクエストを生む理由
コンパイラのレイアウトをワイヤ形式とみなさず、明示的なフィールド幅、バイト順、ストリームI/Oを確認します。
有効なプロキシアドレスがあっても、手書きのSOCKSメッセージが有効になるわけではありません。CやC++の構造体を送ると、プロトコルが求めていないパディングやホスト順の整数まで送ってしまうことがあります。
SOCKS5のドメイン名CONNECTリクエストでは、メソッド交渉と選択した認証の後に、この順序を明示的にシリアライズします。
- バージョン、コマンド、予約バイト、アドレス種別
- ドメイン長とドメインバイト
- ネットワークバイト順の2バイトの宛先ポート
アドレス長はSOCKSのバージョンとアドレス種別によって変わります。固定幅の数値フィールドには規定の表現が必要で、ドメイン文字列には独自の長さエンコードがあります。C文字列の終端は、ワイヤメッセージにゼロを付ける一般的な指示ではありません。
| 実装上の近道 | 確認すべき問題 |
|---|---|
| 8ビットポインタ経由で32ビット値を代入する | 4バイトすべてを出力しない |
| バッファをより大きい整数ポインタにキャストする | アラインメントとバイト順の扱いが依然として必要 |
| 1回の読み取りや書き込みを1メッセージとみなす | TCPはプロトコル手順の一部しか転送できない |
各フィールドを意図した宛先と比較し、部分的なI/Oを処理します。2バイトを受け取っただけでは、応答全体が届いたことにはなりません。その境界を調べれば、不正なリクエストと、正しく記述された接続を拒否するサーバーを区別できます。