OpenSSLのDoS脆弱性、わずか11バイトのペイロードでリモート攻撃者がサーバーメモリを枯渇可能に

新たに公表された脆弱性は、デジタルインフラがいかに基盤ライブラリに深く依存しているかを改めて浮き彫りにしています。

Vulnerabilityscanning tools

Okta Red Teamは最近、OpenSSLに存在するサービス拒否(DoS)の欠陥「HollowByte」を発見しました。この脆弱性を悪用すると、リモートの未認証攻撃者はセキュリティのハンドシェイクが始まる前の段階で、わずか11バイトのペイロードだけでサーバーに不釣り合いなメモリチャンクを確保させることができます。

TLSハンドシェイクは、レコードに包まれたClientHelloメッセージから始まります。各ハンドシェイクメッセージには、受信予定のメッセージ本体のサイズを示す4バイトのヘッダーが付与されています。

OpenSSLのDoS脆弱性

OpenSSLの旧バージョンでは、実際にデータが到着する前に、攻撃者が申告したこの長さに基づいて受信バッファを確保してしまいます。悪意ある11バイトのペイロードが届くと、TLSステートマシンがヘッダーを読み込み、3バイトの長さ申告に基づいて未検証のまま事前割り当てを引き起こします。

Read Header → grow_init_buf() → OPENSSL_clear_realloc() → malloc(attacker_size)

この段階ではペイロードの検証が一切行われないため、malloc()は信頼できないパケットの申告のみを根拠に、最大131KBものメモリを確保してしまいます。その後、ワーカースレッドは決して届くことのないデータを待ち続け、無期限にブロックされた状態になります。

接続を開いたまま保持してスレッドを枯渇させる手口は、Slowlorisと同様の古典的な攻撃です。HollowByteはこれに加えて、glibcのメモリ管理方式に起因するさらに厄介な副作用をもたらします。

接続が切断されるとOpenSSLはバッファを解放しますが、glibcは中小規模の確保領域を即座にOSへ返却せず、再利用に備えて保持し続けます。

攻撃者が申告サイズをランダムに変えながら接続の波を送り込むことで、アロケータが解放済みチャンクを再利用できなくなります。その結果ヒープは激しく断片化し、サーバーの常駐セットサイズ(RSS)は増大を続けます。

攻撃者が切断した後もサーバーは肥大化した状態のままとなり、修復するにはプロセスを強制終了する以外に手段がありません。NGINX上で未修正版と修正済み版のOpenSSLインスタンスをテストしたところ、この脅威の深刻さが明らかになりました。1GBのRAM環境では、未修正のサーバーはメモリを547MBまで断片化・凍結させた時点でOOM Killerによって強制終了されました。

16GBのRAM環境では、通常の接続数上限を下回ったまま、システム全体のメモリの25%を攻撃によって占有されてしまいました。つまり、一般的な接続数制限による防御策ではこの攻撃を防げないということです。

OpenSSLは非常に広く組み込まれているため、この脆弱性はWebサーバー(Apache、NGINX)、言語ランタイム(Node.js、Python、Ruby、PHP)、データベース(MySQL、PostgreSQL)にまで影響を及ぼします。

OpenSSLはこの問題を解決するため、バッファをインクリメンタルに拡張する方式へと切り替え、PR #30792、#30793、#30794としてマージしました。この修正はOpenSSL v4.0.1で静かに配布され、3.6.3、3.5.7、3.4.6、3.0.21へもバックポートされています。

申告されたヘッダーサイズを無条件に信頼するのではなく、OpenSSLは今後、実際に回線上でバイトが届いた分だけバッファを拡張するようになりました。これにより、空の申告がサーバーに一切コストをかけることはなくなります。なお、OpenSSLはこれを正式なCVEアドバイザリとしてではなく、堅牢化のための修正として分類しています。

いずれにせよ、セキュリティチームは直ちにOpenSSLパッケージのアップグレードを優先すべきです。特にインターネットに面したサーバーでは、接続数制限だけではこの攻撃に対して何の防御にもならない点に注意が必要です。

Securityawareness training

 脅威検知と迅速な調査を加速し、SOCを強化しましょう。 -> ANY.RUNをあなたのSOCと統合今すぐ

翻訳元: https://gbhackers.com/openssl-dos-vulnerability/

ソース: gbhackers.com