INT 4: HACKER

Web security research

How to forcibly block communication in ASP.NET(C#) managed module / IHttpModuleで通信を遮断するIIS(Azure)拡張モジュールを実装する

f:id:reinforchu:20200209123210p:plain

 任意のルールにマッチするHTTP通信を遮断する動作を、IIS/Azureの拡張モジュール(マネージド)で実装します。お手軽に対応するのであれば、Web.configでURL Rewriteのルールを沢山書くとよいですが、マネージドモジュールで実装すると、TCPソケット接続の制御が可能であるため、Connection resetを返すような遮断動作を実装できます。なお、拡張モジュール自体の実装方法は過去のブログをご参照ください。

www.hack.vet

 ●具体的な実装方法

 実装においては、ASP.NETのライフサイクルを理解する必要性があるかもしれません。ここでは言及しませんが、HTTPリクエストのContextにアクセスするためにはイベントPreRequestHandlerExecuteからのイベントハンドラを実装します。つまり、HTTPリクエストベースの遮断ルールはここで決定されるでしょう。

 次に遮断の実装方法です。私が調査したところによると、いくつかの手段がありました。その一つ、ある任意のルールにマッチした場合のアクション(悪意あるアクセスなど検知した時)にConnection reset を返したい場合は、HttpContext.Current.Response.Close();を呼びます。Response.Close();はTCPソケット接続を突然切断させるメソッドです。HTTPのリクエスト/レスポンスにおいては手荒い動作をしますが、これでHTTPレスポンスを返さずにConnection resetを返すことができます。以上において、次のC#ソースコードをサンプルとして提示します。

◆バインドされたホスト名“localhost”への接続にERR_CONNECTION_RESETを返す

localhostBlocker

f:id:reinforchu:20200209114641p:plain

 

●Azure Web Serviceに応用する / Hiding *.azurewebsites.net

  前項のサンプルコードは、次のケースに応用できると思いませんか。Azure Web Serviceの仮想アプリケーション/パスを設定して、複数のホスト名をバインドしている場合、デフォルトでバインドされている {APP_NAME}.azurewebsites.net は当然アクセス可能であるため、秘匿したい、そもそもアクセスをさせたくないし遮断したいというニーズがあると思います。実際には、いくつかの手段が存在しますが、IISのモジュールでも暫定的に対策ができます。暫定的というのが、Azure Web Serviceにおいて、HttpContext.Current.Response.Close();メソッドは期待した動作をしません。代替手段が必要ですので模索してみました。パブリッククラウドサービス上で“手荒いことは”避けるべきだと思うため、不明なプロトコルにリダイレクトさせる手法に落ち着きました。

◆Hiding *.azurewebsites.net (Unknown protocol)

AZBlocker

f:id:reinforchu:20200209122805p:plain

  テスト用のコードが残っていますが、何が起こるか簡単にコメントを残しているので、参考までに。サンプルコードはscript:プロトコル(?)を使っていますが、未定義であれば何でも良いのかもしれません。javascript:スキームを使うのも検討しましたが、トップレベルでのjavascriptスキームの実行は基本的に禁止されているのでやめました。そもそも不明なプロトコル・スキームにリダイレクトさせる方法は些かどうなんでしょう。安全に振るのであれば、ブランクページを返すHttpApplication.CompleteRequest();メソッドが適切だと思います。HttpContext.Current.Response.End();も類似した振る舞いをしますが、こちらはThreadAbortExceptionを投げるのでエラーが溜まってくようです。

 

 ●参照記事

docs.microsoft.com

docs.microsoft.com

docs.microsoft.com

stackoverflow.com