デューデリジェンスにより、モジュール自体のコードを変更することなく、誰もがサードパーティのアプリケーションのようにこれらの機能を独自に実装できると確信していましたが、誰もそれをしなかったので、PoCをしなければなりませんでした。
最初は、モジュールをコンストラクターの形にしたかったのですが、KISSの原則をキャンセルした人はいなかったため、すべてのクライアント側の機能をサードパーティアプリケーションの形で実装することにしました。 Nginxはプロキシで問題なく動作しているため、最も簡単な方法は、プロキシを個別のHTTPサービスとして記述することです。
これには次の利点があります。
- 私たちは私たちにとって便利な任意の言語で書きます(私はPythonが好きです)
- 私たちはnginxに縛られておらず、コードの品質はそれほど重要ではありません-itdなどをブロックすることができます
- すべての範囲のキャッシュ機能nginxを使用できます
- サービスが存在する場合でも、すでにCookieを受け取ったすべての正当なユーザーはこれに気付きません-メインリソースは利用可能です 。
私が追加しなければならなかったこと
testcookie-filterモジュールのメインディレクティブでは 、古い「on」および「off」の値に加えて、別の値「var」が追加されました。 モジュールがvarモードの場合、特定の場所に対して:
- Cookieの検証が実行されます。
- nginx変数($ testcookie_nexturlを除くすべて)が公開されます。
- リダイレクト、Cookieの設定、リクエストのインターセプトは行われません 。
それは何のためですか?
したがって、HTTPヘッダーを介してアプリケーションに正しいCookie値を転送できるようになりました。
location = /testcookie.swf { testcookie var; proxy_pass http://127.0.0.1:1234/; proxy_set_header Testcookie-Value $testcookie_set; proxy_set_header Testcookie-Valid $testcookie_ok; proxy_set_header Testcookie-Name "BPC"; }
Flashの場合、paramではなくヘッダーを使用するのはなぜですか?
値はクライアント部分に平文で表示されないため、たとえばregexpによって抽出できません。
それでも、フラッシュ?
Flashを介してCookieを設定する方法は最も適切ではないと思いますが、ユーザーが望むので、そうではありません。
静的SWFを作成し、 Robooで行われていたように値を代入するというアイデアは、すぐに却下しました-簡単に分解したり、変更したりすることは困難です。
したがって、ユーザーに自分で攻撃者の生活を複雑にする機会を与えることにしました。
このため、プロジェクトには2つのファイルがあります。
cookie_encoder.py (Python):
def encode_cookie(cookie_value): key = 42 res = '' for x in cookie_value: res += chr(ord(x) ^ key) return res
cookie_decoder.as (ActionScript):
function flash_cookie_crypt_routine(str) { var result; for (var i = 0; i < str.length; i++) { result += String.fromCharCode(str.charCodeAt(i) ^ 42); } return result; } getURL("javascript:void(document.cookie='#TESTCOOKIE_NAME#=" + flash_cookie_crypt_routine("#TESTCOOKIE_VALUE#") + "');void(location.href='" + nexturl + "');");
ご想像のとおり、最初の値は値のエンコード用(この例では42のxorim)で、2番目はクライアント側でのデコード用です(再び42のxorim)。
ActionScriptは、 libmingを使用してSWFで動的にコンパイルされます。 ちなみに、少なくともメンテナーが関数名の選択をやめてプルを承認するまで、プロジェクトは私のフォークでのみ動作します。
サービスフレームワークは、Python用の高速非同期Webサーバーであるfapws3を使用します。
古いcoreduoでは、1つのプロセスで、最適化とキャッシュなしで、同時性1kで〜3k req / sが得られます。 本番環境では、nginxプロキシキャッシュを使用できるため、SWFは各クライアントに対して1回だけ生成され、nginxで配布してサービス自体を配置することは非常に困難です。
すべて一緒に
設定例:
server { listen 80; server_name domain.com; testcookie off; testcookie_name BPC; testcookie_secret keepmescret; testcookie_session $remote_addr; testcookie_arg attempt; testcookie_max_attempts 3; testcookie_fallback /cookies.html?backurl=http://$host$request_uri; testcookie_get_only on; testcookie_redirect_via_refresh on;
#testcookie.swfをswfobject経由で接続します(はい、私は怠け者です)
#testcookie_refresh_templateディレクティブを使用し、
#param経由で$ testcookie_nexturlの値を渡す
testcookie_refresh_template '<html><body><script type="text/javascript" src="/swfobject.js"></script><script type="text/javascript">swfobject.embedSWF("/testcookie.swf", "cookie_installer", "100", "100", "9.0.0", "/expressInstall.swf", {"nexturl":"$testcookie_nexturl"});</script><div id="cookie_installer">welcome screen</div></body></html>';
#Cookieチェックを無効にする
#フォールバックURL、swfobject.jsおよびexpressInstall.swf
location = /cookies.html { root /var/www/public_html; } location = /swfobject.js { gzip on; gzip_min_length 1000; gzip_types text/plain; root /usr/local/nginx/root; } location = /expressInstall.swf { testcookie off; gzip on; gzip_min_length 1000; gzip_types text/plain; root /usr/local/nginx/root; }
#この場所で、サービスは動的にSWFを生成します
location = /testcookie.swf { # testcookie var testcookie var; # testcookie-flash-processor proxy_pass http://127.0.0.1:1234/; # cookies proxy_set_header Testcookie-Value $testcookie_set; # ? # SWF , # cookie proxy_set_header Testcookie-Valid $testcookie_ok; # cookie - # testcookie_name proxy_set_header Testcookie-Name "BPC"; }
#バックエンドアクセスのあるメインの場所
location / { testcookie on; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_pass http://127.0.0.1:8080; } }
Captchaも同じようにねじ込まれます。
ソースコード
インストール手順とドキュメントを含むソースは、BSDライセンスの下でgithubで入手できます。
パッチ、アドオン、テスト、バグレポートを歓迎します。