クラウドサービスにおける ReDoS 対策
正規表現のマッチングにかかる処理時間が指数的に増えることでDoS脆弱性が発生し、それを利用した攻撃を ReDoS 攻撃と呼びます。
詳しくは、
最近書かれた、立命館コンピュータクラブの記事もよくまとまっております。
クラウドサービスにおける ReDoS 対策
クラウドのサービスでは、お客様にサーバやミドルウェアの設定として正規表現やワイルドカードを入力していただくことがあります。そうした場合に正規表現がReDoSの対象とならないよう、チェックしなければなりません。
さくらのクラウドのエンハンスドロードバランサではコントロールパネルにてワイルドカードを入力する箇所がいくつかあります。ワイルドカードはL7ロードバランサとして利用しているHAProxyの設定では正規表現に変換されて使用されます。
以前は、マッチングの負荷を抑えるため、ワイルドカード文字 *
や ?
を利用する数を数個に制限しておりましたが、現在ではその制限を緩和し、 ReDoS につながる正規表現をチェックする以下のライブラリを使って負荷になる正規表現にならないか確認しています。
safe-regexのREADMEにも書かれてますが、より正確なチェックをするには別のライブラリがおすすめされています。
また、立命館コンピュータクラブの記事でも紹介されている recheck もあります。
今回はワイルドカードからの変換であり、自由に正規表現が指定できないので safe-regex を利用しています。
ワイルドカード文字の個数制限をやめてReDoSチェックの導入する提案はフロントエンドのエンジニアから頂き、開発も一緒にやりました。さくらのクラウドの開発チームはフロントエンド、バックエンド、基盤などの役割を問わず改善のアイディアを出し合って開発を進めています。
正規表現チェックサーバ
さくらのクラウドのコントロールパネルは JavaScript/TypeScript で作られていますので、上記のライブラリはフロントエンドそのまま使えますが、APIや基盤の制御、ミドルウェアの設定の生成をするサーバ側はPHPやPerlまたはGoといった言語で書かれているので、そのまま使うことはできません。
そこで、davisjam/safe-regex を呼び出すだけのAPIサーバを Node.js で作り hacobune で動作させ、PHP/Perlから利用するようにしました。小さいAPIを作るのは Mackerel の Plugin をインストールするための release Tag キャッシュサーバ と同じアイディアです。
使い方
$ docker run -p 3000:300 ghcr.io/kazeburo/safe-regex-api:latest
$ curl -sSf -XPOST --data-urlencode 'regexp=[a-z]+' localhost:3000/is_safe_regexp {"error":false,"is_safe":true}
expressのmiddlewareの機能により、form-urlencodedまたはJSONでPOSTできます。
curl -sSf -XPOST -H 'Content-type: application/json' -d '{"regexp":"[a-z]+"}' localhost:3000/is_safe_regexp {"error":false,"is_safe":true}
安全でない正規表現を送るとis_safe
が false
となることがわかります
$ curl -sSf -XPOST --data-urlencode 'regexp=(a+)+' localhost:3000/is_safe_regexp {"error":false,"is_safe":false}