パケットインスペクションとMalleable C2プロファイルの相関を通じて、Blue Teams、AV、EDR、スキャナーを撃退するCobalt Strike C2リバースプロキシ
(以前は proxy2's の malleable_redirector プラグインとして知られていました)
C2リダイレクタのIR耐性の水準を引き上げましょう。

レッドチームのビジネスでは、インシデントレスポンダーに対抗し、誤った方向へ導きながら、同時に耐性のあるC2リダイレクタネットワークを提供する方法について、いくつかの 異なる 素晴らしい アイデアが登場しています。
この作品は、それらの素晴らしいアイデアの多くを1つの軽量ユーティリティに統合し、そのルーツであるシンプルなHTTP(S)リバースプロキシとしてApache2を模倣しています。
Malleable C2プロファイルの理解、悪質なIPアドレスプールの知識、そして新しい検査および誤ルーティングロジックを容易に追加できる柔軟性を組み合わせることで、IR検査に対する巧妙な忌避手段が生まれました。

無効なインバウンドパケットがRedWardenに到達した場合、redirect、reset、または単にproxyで退避させることができます!
このプログラムは、インバウンドC2 HTTPリクエストに対していくつかの制限を課し、Teamserverに転送するパケットとドロップするパケットを選択するHTTP/HTTPSリバースプロキシとして機能します。これは、Apache2ので義務付けられている.htaccessファイルの制限と同様です。
mod_rewriteRedWardenは、C2リダイレクタ層におけるIR/AV/EDR/サンドボックスの回避の問題を解決するために作成されました。この目的で使用される古典的なApache2 + mod_rewriteのセットアップに取って代わることを意図しています。
特徴:
RedWardenは、入力としてMalleable C2プロファイルとteamserverのhostname:portを受け取ります。次に、提供されたMalleableプロファイルセクションを解析して契約を理解し、それを満たしたインバウンドリクエストのみを通過させ、その他は誤った方向へ導きます。
http-stager、http-get、http-postなどのセクションと、それらに対応するURI、ヘッダー、プリペンド/アペンドパターン、User-Agentはすべて、正当なビーコンのリクエストと無関係なインターネットノイズやIR/AV/EDRの範囲外パケットを区別するために使用されます。
このプログラムは、以下から提供される素晴らしい既知の悪質なIP範囲を活用しています: curi0usJackとその他: https://gist.github.com/curi0usJack/971385e8334e189d93a6cb4671238b10
IPアドレスのブラックリスト化と、リバースIP DNSクエリおよびHTTPヘッダー検査による既知の悪質キーワードの検索を組み合わせることで、攻撃者のインフラを調査しようとする不正なピアに対するリダイレクタの耐性を大幅に向上させる信頼性をもたらします。
無効なパケットは3つの戦略に従って誤ルーティングされる可能性があります:
この設定は設定ファイルで義務付けられています:```yaml
drop_action: redirect
以下の例は、`redirect` から `https://googole.com` へのリダイレクトの結果を示しています:

賢く使い、安全に保ちましょう。
### 要件
このプログラムは、fork を使用して複数のプロセスを生成するため、Linux システムでのみ実行できます。
また、SSL証明書の生成に使用されるため、`openssl` システムコマンドがインストールされていることが前提です。
最後に、以下のコマンドで Python3 PIP の要件をすべて簡単にインストールできます。```shell
bash $ sudo pip3 install -r requirements.txt
最小限のRedWardenのconfig.yaml設定ファイルには、次の内容を含めることができます:```yaml port:
profile: jquery-c2.3.14.profile
ssl_cacert: /etc/letsencrypt/live/attacker.com/fullchain.pem ssl_cakey: /etc/letsencrypt/live/attacker.com/privkey.pem
teamserver_url:
drop_action: reset
その後、設定ファイルへのパスを指定してプログラムを起動できます。```shell
bash$ sudo python3 RedWarden.py -c config.yaml
[INFO] 19:21:42: Loading 1 plugin...
[INFO] 19:21:42: Plugin "malleable_redirector" has been installed.
[INFO] 19:21:42: Preparing SSL certificates and keys for https traffic interception...
[INFO] 19:21:42: Using provided CA key file: ca-cert/ca.key
[INFO] 19:21:42: Using provided CA certificate file: ca-cert/ca.crt
[INFO] 19:21:42: Using provided Certificate key: ca-cert/cert.key
[INFO] 19:21:42: Serving http proxy on: 0.0.0.0, port: 80...
[INFO] 19:21:42: Serving https proxy on: 0.0.0.0, port: 443...
[INFO] 19:21:42: [REQUEST] GET /jquery-3.3.1.min.js
[INFO] 19:21:42: == Valid malleable http-get request inbound.
[INFO] 19:21:42: Plugin redirected request from [code.jquery.com] to [1.2.3.4:8080]
[INFO] 19:21:42: [RESPONSE] HTTP 200 OK, length: 5543
[INFO] 19:21:45: [REQUEST] GET /jquery-3.3.1.min.js
[INFO] 19:21:45: == Valid malleable http-get request inbound.
[INFO] 19:21:45: Plugin redirected request from [code.jquery.com] to [1.2.3.4:8080]
[INFO] 19:21:45: [RESPONSE] HTTP 200 OK, length: 5543
[INFO] 19:21:46: [REQUEST] GET /
[...]
[ERROR] 19:24:46: [DROP, reason:1] inbound User-Agent differs from the one defined in C2 profile.
[...]
[INFO] 19:24:46: [RESPONSE] HTTP 301 Moved Permanently, length: 212
[INFO] 19:24:48: [REQUEST] GET /jquery-3.3.1.min.js
[INFO] 19:24:48: == Valid malleable http-get request inbound.
[INFO] 19:24:48: Plugin redirected request from [code.jquery.com] to [1.2.3.4:8080]
[...]
上記の出力には、C2 プロファイルに準拠していない不正な受信リクエストがあり、提示された互換性のない User-Agent 文字列のためにドロップされたことを示す行が含まれています:``` [...] [DROP, reason:1] inbound User-Agent differs from the one defined in C2 profile. [...]
## 使用例
### ビーコントラフィックの発信元にIPジオロケーションを課す
プリフィッシングとOSINTをしっかりと行いました。これでターゲットの居住地がわかり、トラフィックがどこから発信されるべきかの手がかりが得られました。あるいは、まったく補助的なトラフィックを検出する方法は少なくともわかりました。
リダイレクタ上のビーコンリクエストにIPジオロケーションを課すにはどうすればよいですか?
RedWardenが役に立ちます!
例えば、ヨーロッパのポーランドからのトラフィックのみを受け入れたいとします。
Pre-Phish/OSINTの結果は次のことを示しています:
- `89.64.64.150` はあなたのターゲットの1つの正当なIPで、ポーランドからのものです
- `59.99.140.76` はそうではなく、通常のインターネットノイズパケットとしてシステムに到達しました。
RedWardenのユーティリティ `lib/ipLookupHelper.py` を使用して、これらの2つのアドレスに関するIP Geoメタデータを収集できます。```shell
bash$ python3 ipLookupHelper.py
Usage: ./ipLookupHelper.py <ipaddress> [malleable-redirector-config]
Use this small utility to collect IP Lookup details on your target IPv4 address and verify whether
your 'ip_geolocation_requirements' section of proxy2 malleable-redirector-config.yaml would match that
IP address. If second param is not given - no
前者はもたらす:```shell bash$ python3 ipLookupHelper.py 89.64.64.150 [dbg] Following IP Lookup providers will be used: ['ip_api_com', 'ipapi_co'] [.] Lookup of: 89.64.64.150 [dbg] Calling IP Lookup provider: ipapi_co [dbg] Calling IP Lookup provider: ip_api_com [dbg] New IP lookup entry cached: 89.64.64.150 [.] Output: { "organization": [ "UPC Polska Sp. z o.o.", "UPC.pl", "AS6830 Liberty Global B.V." ], "continent": "Europe", "continent_code": "EU", "country": "Poland", "country_code": "PL", "ip": "89.64.64.150", "city": "Warsaw", "timezone": "Europe/Warsaw", "fulldata": { "status": "success", "country": "Poland", "countryCode": "PL", "region": "14", "regionName": "Mazovia", "city": "Warsaw", "zip": "00-202", "lat": 52.2484, "lon": 21.0026, "timezone": "Europe/Warsaw", "isp": "UPC.pl", "org": "UPC Polska Sp. z o.o.", "as": "AS6830 Liberty Global B.V.", "query": "89.64.64.150" }, "reverse_ip": "89-64-64-150.dynamic.chello.pl" }
そして後者は次のようになります:```shell
bash$ python3 ipLookupHelper.py 59.99.140.76
[dbg] Following IP Lookup providers will be used: ['ip_api_com', 'ipapi_co']
[dbg] Read 1 cached entries from file.
[.] Lookup of: 59.99.140.76
[dbg] Calling IP Lookup provider: ip_api_com
[dbg] New IP lookup entry cached: 59.99.140.76
[.] Output:
{
"organization": [
"",
"BSNL Internet",
"AS9829 National Internet Backbone"
],
"continent": "Asia",
"continent_code": "AS",
"country": "India",
"country_code": "IN",
"ip": "59.99.140.76",
"city": "Palakkad",
"timezone": "Asia/Kolkata",
"fulldata": {
"status": "success",
"country": "India",
"countryCode": "IN",
"region": "KL",
"regionName": "Kerala",
"city": "Palakkad",
"zip": "678001",
"lat": 10.7739,
"lon": 76.6487,
"timezone": "Asia/Kolkata",
"isp": "BSNL Internet",
"org": "",
"as": "AS9829 National Internet Backbone",
"query": "59.99.140.76"
},
"reverse_ip": ""
}
さて、前者は "country": "Poland" を持ち、後者は "country": "India" を持っていることがわかります。この知識をもとに、大きなYAML辞書の形で制約を考案する準備が整いました。```yaml
ip_geolocation_requirements:
organization:
continent:
continent_code:
country:
- Poland
- PL
- Polska
country_code:
city:
timezone:
その辞書の各エントリは、インバウンドピアのIPアドレスの決定されたIP Geoメタデータに対してマッチさせる正規表現を受け入れます。
`country`プロパティの3つのエントリを使用して、指定された値のいずれかを持つリクエストを許可します。
設定でそれを設定したら、`ipLookupHelper`ユーティリティ(2番目のパラメータを受け付ける)を使用して、別のIPアドレスがRedWardenのIP Geolocation判別器を通過するかどうかを確認できます。

最後の行は、パケットがブロックされるか受け入れられるかを示します。
以上です!IP Geolocationの制約を賢く安全に設定し、RedWardenのログでIP Geo関連のDROPエントリを注意深く確認し、C2トラフィックをきちんと整頓してください!
### 改ざんされたBeaconリクエストの修復
もしAWS LambdaやCloudFlareなどの中間システムをDomain Fronting/リダイレクターとして使用している場合、一部のパケットが合意されたMalleable Contractから逸脱したためにTeamserverに受け入れられない状況に遭遇したことがあるでしょう。それが改ざんされたり削除されたHTTPヘッダー、並び替えられたCookie、その他何であれ、おそらく多くの時間を無駄にしたことでしょう。
C2チャネル設定プロセスの問題や中間システムによる改ざんに対抗するため、RedWardenはBeaconパケットを修復する機能を提供します。
これは、Malleable Profileがパケットに期待する内容をチェックし、プロファイルの要件に従って設定されたHTTPヘッダーを合意された値に復元することで実現します。
以下のシンプルなプロファイルを考えてみましょう:```
http-get {
set uri "/api/abc";
client {
header "Accept-Encoding" "gzip, deflate";
metadata {
base64url;
netbios;
base64url;
parameter "auth";
}
}
...
この Accept-Encoding がわかりますか?すべての Beacon リクエストはそのヘッダーとその値を持たなければなりません。もしあなたの Beacon が CloudFlare システムにヒットし、そのリクエストがそのヘッダーから取り除かれるか、代わりに Accept-Encoding: gzip が設定された場合、どうなるでしょうか?Teamserver はその場でリクエストをドロップします。
このヘッダーを RedWarden 設定セクションの repair_these_headers と呼ばれる場所で設定することで、接続を安全にできます。:```yaml
repair_these_headers:
### 問題のあるレスポンスヘッダーを削除する
Cobalt Strike 4.7+ 以降、Teamserver が何の通知もなく自動的に Content-Encoding ヘッダーを削除し、それによって malleable `http-(get|post).server` 契約に違反していることに気付きました。
RedWarden はその契約に従っていたため、Beacon はレスポンスをドロップするか、不正確に解凍していました。
このオプションは、Teamserver のレスポンスから Beacon プロセスに届く前に削除すべきヘッダーを指定します。```yaml
remove_these_response_headers:
- Content-Encoding
RedWardenは今後、CS4.7+バージョンとの互換性を維持するために、デフォルトでTeamserverのレスポンスからContent-Encodingヘッダーを削除します。
プロキシが生成する出力を見てみましょう。
verbose: Trueオプションでは、詳細度は最大でINFOに設定され、受け入れられたリクエストとドロップされたリクエストが区別されます。
リクエストがRedWardenの設定ファイルに設定されたすべての基準に適合した場合、そのリクエストは受け入れられる可能性があります。そのような場合、ログエントリに[ALLOW, ...]が続きます。```
[INFO] 2021-04-24/17:30:48: [REQUEST] GET /js/scripts.js
[INFO] 2021-04-24/17:30:48: == Valid malleable http-get (variant: default) request inbound.
[INFO] 2021-04-24/17:30:48: [ALLOW, 2021-04-24/19:30:48, 111.222.223.224] "/js/scripts.js" - UA: "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko"
[INFO] 2021-04-24/17:30:48: Connected peer sent 2 valid http-get and 0 valid http-post requests so far, out of 15/5 required to consider him temporarily trusted
[INFO] 2021-04-24/17:30:48: Plugin redirected request from [attacker.com] to [127.0.0.1:5555]
リクエストがRedWardenが各リクエストに対して行うチェックのいずれかに失敗した場合、対応する`[DROP, ...]`行が出力され、ドロップの**理由**に関する情報が含まれます。:```
[INFO] 2021-04-24/16:48:28: [REQUEST] GET /
[ERROR] 2021-04-24/16:48:29: [DROP, 2021-04-24/18:48:28, reason:1, 128.14.211.186] inbound User-Agent differs from the one defined in C2 profile.
[INFO] 2021-04-24/16:48:29: [DROP, 2021-04-24/18:48:28, 128.14.211.186] "/" - UA: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36"
[ERROR] 2021-04-24/16:48:29: [REDIRECTING invalid request from 128.14.211.186 (zl-dal-us-gp3-wk107.internet-census.org)] GET /
リクエストがドロップされるかどうかを決定する理由は数多くあります。これらの各チェックは、要件に応じて、または微調整や誤った判断の修正の過程で、独立してオン/オフを切り替えることができます:
example-config.yaml からの抜粋:```yaml
policy:
allow_proxy_pass: True
allow_dynamic_peer_whitelisting: True
drop_invalid_useragent: True
drop_http_banned_header_names: True
drop_http_banned_header_value: True
drop_dangerous_ip_reverse_lookup: True
drop_ipgeo_metadata_containing_banned_keywords: True
drop_malleable_without_expected_header: True
drop_malleable_without_expected_header_value: True
drop_malleable_without_expected_request_section: True
drop_malleable_without_request_section_in_uri: True
drop_malleable_without_prepend_pattern: True
drop_malleable_without_apppend_pattern: True
drop_malleable_unknown_uris: True
drop_malleable_with_invalid_uri_append: True
デフォルトでは、これらすべてのチェックが有効になっています。
`debug: True`を有効にすると、RedWardenが複雑な判断プロセスで実行する各ステップのログ行が大量にコンソールバッファにあふれます。
リクエストとレスポンスの完全なボディを確認したい場合は、`debug`と`trace`をtrueに設定すると、ログの洪水に埋もれてしまいます!
## FAQ
**- このプログラムはMalleable Profileなしで実行できますか?**
はい、可能です。ただし、リクエスト検査ロジックはオフになりますが、その他の機能(IP地理位置情報の適用、逆引きロジック、禁止IPリストなど)は正常に動作します。
**- このプログラムは他のC2フレームワーク(Mythic、Covenantなど)にも簡単に適応できますか?**
簡単にはできません。少し努力すれば可能です。以下で説明したように、このツールは他のC2への適応を困難にするように書かれています。しかし、時間と労力をかければ十分に可能です。
**- パケットがドロップされます。なぜですか?**
`debug: True`と`trace: True`を有効にして、できるだけ多くのログを収集してみてください。その後、ログを確認して何が起こっているのか調査する必要があります。パケットはMalleable Profileで期待した通りに届いていますか?あるいは、ネットワーク経由で微妙な改ざんがあり、それがRedWarden(そしてTeamserverも)にパケットをドロップさせる原因になっている可能性はありませんか?
## 既知の問題点
- インタラクティブスリープスループットにわずかなオーバーヘッドが追加される可能性があります。
- ProxyPassの処理ロジックは完全とはほど遠く、**非常に**バグが多いです(そして、なんと醜いことか!)。
- 設定ファイルの奇妙な形式は、RedWardenのパーサーを脱線させ、エラーを引き起こす可能性があります。これを回避する最も簡単な方法は、`example-config.yaml`をコピーして、代わりにそれを編集することです。
## なぜこのコードはこんなにも工学的なクソなのか?
このコードは**めちゃくちゃでっかいクソの山**です – それは認めます – そしてそれには正直な理由もあります。このプロジェクトは、実際のRed Teamのエンゲージメント中に90%開発されました。誰もが知っているように、こうしたエンゲージメントにはやるべきことが非常に多く、適切な複雑なツールを開発する時間はほとんど残されていません。ましてや、プロジェクトのセットアップにおけるこのプログラムの重要性は言うまでもありません。このツールは当初、Python2で書かれたシンプルなプロキシスクリプトとして始まり、その後プラグイン対応のプロキシへと進化し、`malleable_redirector`プラグインを受け入れました。それ以来、私は`proxy2`の後方互換性を維持しようと必死に努力してきました(かわいそうな私、まるでMicrosoftのようでした!)。これは私が作成した他のプラグインとの互換性と、元の目的を維持するためです。
しかし、手放し、名前を変え、導入された悪いコードの臭いをすべて修正し始める時が来ました。
とはいえ、問題を報告したり、プルリクエストを送信したりする際には、ある程度の思いやりを私に示してください。そして、判断するのではなく、助けようとしてください! :-)
ありがとうございます!
## TODO
- 脅威インテリジェンスフィードを悪意のある目的(例えば、IPに基づくセキュリティベンダーの検出など)に使用する可能性を調査する
- MaxMind GeoIPデータベース/APIのサポートを追加する
- JA3シグネチャの検出とブロッキング、およびnginx/Apache2/カスタムセットアップの偽装のサポートを実装する
- 独自の裁量でステージングと通信プロセスを拒否する柔軟性を提供するために、ユニークなビーコントラッキングロジックを追加する
- リダイレクト機能を提供する際に時間帯の制約を導入する(_営業時間内のみプロキシ_)
- CONNECT/リレーにプロキシ認証と認可ロジックを追加する
- モバイルユーザーを対象としたリダイレクトを追加する
- 注入するカスタムHTTPヘッダー、または削除するヘッダーを定義するための設定オプションを追加する
- ProxyPass基準を通過するリクエストに特定のHTTPヘッダーの存在を要求する設定オプションを追加する
- Nmapのように、入力された単純な文字で出力ログの詳細度を制御できるインタラクティブインターフェース
- Malleableプロファイルパーサーのロジックを[pyMalleableC2](https://github.com/Porchetta-Industries/pyMalleableC2)に書き換える。初めて独自のパーサーロジックを書き始めたとき、Githubにはそのようなツールキットはありませんでした。
- すべてのコードベースをリファクタリングする
---
### ☕ サポートをお願いします ☕
このプロジェクトや他のプロジェクトは、眠れぬ夜と**たくさんのハードワーク**の結果です。私の活動を気に入っていただき、常にコミュニティに還元していることに感謝していただけるなら、
[コーヒーをおごることを検討してください](https://github.com/sponsors/mgeeky) _(またはビールの方が良いかも)_ ありがとうの気持ちとして! 💪
---
## 著者```
Mariusz Banach / mgeeky, '19-'21
<mb [at] binary-offensive.com>
(https://github.com/mgeeky)