Proxy inverse C2 Cobalt Strike qui repousse les Blue Teams, AVs, EDRs, scanners grâce à l'inspection de paquets et la corrélation de profils malléables.
(précédemment connu sous le nom de plugin malleable_redirector de proxy2)
Élevons la barre en matière de résilience IR des redirecteurs C2, n'est-ce pas ?

Le secteur du Red Teaming a vu plusieurs différentes excellentes idées sur la façon de contrer les répondants aux incidents et de les tromper tout en offrant un réseau de redirecteurs C2 résistant.
Ce travail combine plusieurs de ces excellentes idées en un utilitaire léger, imitant Apache2 dans ses racines en tant que simple proxy inverse HTTP(S).
La combinaison de la compréhension des profils Malleable C2, de la connaissance des pools d'adresses IP malveillantes et d'une flexibilité pour ajouter facilement de nouvelles logiques d'inspection et de détournement - a abouti à un répulsif astucieux pour les inspections IR.

Si un paquet entrant invalide atteint RedWarden - vous pouvez le redirect, reset ou simplement le !
proxyCe programme agit comme un proxy inverse HTTP/HTTPS avec plusieurs restrictions imposées aux requêtes HTTP C2 entrantes, sélectionnant les paquets à diriger vers le Teamserver et ceux à rejeter, de manière similaire aux restrictions du fichier .htaccess imposées dans mod_rewrite d'Apache2.
RedWarden a été créé pour résoudre le problème de l'évasion des IR/AV/EDR/Sandbox au niveau de la couche de redirecteur C2. Il est destiné à remplacer les configurations classiques Apache2 + mod_rewrite utilisées à cet effet.
Fonctionnalités :
RedWarden prend en entrée le profil Malleable C2 et le hostname:port du teamserver. Il analyse ensuite les sections du profil malleable fourni pour comprendre le contrat et ne laisser passer que les requêtes entrantes qui le satisfont, tout en détournant les autres.
Des sections telles que http-stager, http-get, http-post et leurs uris, en-têtes, motifs de préfixe/suffixe, User-Agent correspondants sont toutes utilisées pour distinguer les requêtes légitimes du beacon du bruit Internet non lié ou des paquets hors limites des IR/AV/EDR.
Le programme bénéficie des merveilleuses plages IP indésirables connues provenant de : curi0usJack et les autres : https://gist.github.com/curi0usJack/971385e8334e189d93a6cb4671238b10
L'utilisation d'une liste noire d'adresses IP ainsi que la recherche de mots-clés indésirables connus via des requêtes DNS inverses et l'inspection des en-têtes HTTP, apportent la fiabilité nécessaire pour augmenter considérablement la résilience du redirecteur face aux pairs non autorisés souhaitant examiner les infrastructures des attaquants.
Les paquets invalides peuvent être détournés selon trois stratégies :
Cette configuration est imposée dans le fichier de configuration :```yaml
drop_action: redirect
L'exemple ci-dessous montre le résultat de la redirection vers `https://googole.com` :

Utilisez-le avec sagesse, restez en sécurité.
### Prérequis
Ce programme ne peut fonctionner que sur les systèmes Linux car il utilise fork pour lancer plusieurs processus.
De plus, la commande système `openssl` doit être installée car elle est utilisée pour générer des certificats SSL.
Enfin, installez facilement toutes les dépendances Python3 PIP avec :```shell
bash $ sudo pip3 install -r requirements.txt
Le fichier de configuration minimal config.yaml de RedWarden pourrait contenir :```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
Ensuite, le programme peut être lancé en lui donnant un chemin vers le fichier de configuration:```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]
[...]
La sortie ci-dessus contient une ligne indiquant qu'il y a eu une requête entrante non autorisée, non conforme à notre profil C2, qui a été abandonnée en raison d'un en-tête User-Agent incompatible présenté :``` [...] [DROP, reason:1] inbound User-Agent differs from the one defined in C2 profile. [...]
## Cas d'utilisation
### Imposer la géolocalisation IP aux émetteurs de trafic de votre Beacon
Vous avez très bien réalisé votre Pre-Phish et votre OSINT. Vous savez maintenant où vivent vos cibles et avez des indices sur l'origine attendue du trafic, ou au moins comment détecter un trafic complètement auxiliaire.
Comment imposer la géolocalisation IP aux requêtes Beacon sur un redirecteur ?
RedWarden est là pour vous aider !
Disons que vous souhaitez n'accepter que le trafic provenant de Pologne, en Europe.
Vos résultats Pre-Phish/OSINT indiquent que :
- `89.64.64.150` est une IP légitime d'une de vos cibles, provenant de Pologne
- `59.99.140.76` quant à elle, ne l'est pas et a atteint vos systèmes comme un paquet de bruit Internet régulier.
Vous pouvez utiliser l'utilitaire `lib/ipLookupHelper.py` de RedWarden pour collecter les métadonnées de géolocalisation IP de ces deux adresses :```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
Le premier apporte:```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" }
et ce dernier donne :```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": ""
}
Maintenant vous voyez que le premier avait "country": "Poland" alors que le second "country": "India". Forts de cette connaissance, nous sommes prêts à concevoir nos contraintes sous la forme d'un dictionnaire YAML conséquent :```yaml
ip_geolocation_requirements:
organization:
continent:
continent_code:
country:
- Poland
- PL
- Polska
country_code:
city:
timezone:
Chacune des entrées de ce dictionnaire accepte une expression régulière à faire correspondre sur les métadonnées IP Geo déterminées de l'adresse IP du pair entrant.
Nous utilisons trois entrées dans la propriété `country` pour autoriser les requêtes ayant l'une des valeurs spécifiées.
Ayant cela défini dans votre configuration, vous pouvez vérifier si une autre adresse IP passerait ou non le discriminateur de géolocalisation IP de RedWarden avec l'utilitaire `ipLookupHelper` acceptant un second paramètre :

La toute dernière ligne vous indique si le paquet serait bloqué ou accepté.
Et voilà ! Configurez vos contraintes de géolocalisation IP avec sagesse et sécurité, inspectez attentivement les logs de RedWarden pour toute entrée DROP liée à la géolocalisation IP et gardez votre trafic C2 propre et ordonné !
### Réparer les requêtes Beacon falsifiées
Si vous utilisez des systèmes intermédiaires tels qu'AWS Lambda ou CloudFlare comme frontaux de domaine / redirecteurs, vous avez sûrement rencontré une situation où certains de vos paquets n'ont pas pu être acceptés par le Teamserver car ils s'écartaient du contrat malléable convenu. Que ce soit un en-tête HTTP falsifié ou supprimé, des cookies réordonnés ou autre chose - je parie que cela vous a fait perdre des heures de votre vie.
Pour lutter contre les problèmes de configuration des canaux C2 et les falsifications des systèmes intermédiaires, RedWarden offre une fonctionnalité pour réparer les paquets Beacon.
Il le fait en vérifiant ce que le profil malléable attend du paquet et peut restaurer les en-têtes HTTP configurés à leurs valeurs convenues selon les exigences du profil.
Considérez le profil simple suivant :```
http-get {
set uri "/api/abc";
client {
header "Accept-Encoding" "gzip, deflate";
metadata {
base64url;
netbios;
base64url;
parameter "auth";
}
}
...
Vous voyez ce Accept-Encoding ? Chaque requête Beacon doit comporter cet en-tête et cette valeur. Que se passe-t-il si votre Beacon atteint les systèmes CloudFlare et qu'ils émettent une requête qui sera dépourvue de cet en-tête ou qui aura Accept-Encoding: gzip à la place ? Teamserver supprimera la requête immédiatement.
En définissant cet en-tête dans la section de configuration de RedWarden appelée repair_these_headers, vous pouvez sécuriser votre connexion :```yaml
repair_these_headers:
### Supprimer les en-têtes de réponse problématiques
Avec Cobalt Strike 4.7+, j'ai remarqué que Teamserver supprime automatiquement l'en-tête Content-Encoding sans aucun avertissement, violant ainsi notre contrat malleable `http-(get|post).server`.
Étant donné que RedWarden respectait le contrat, Beacon supprimait les réponses ou les décompressait incorrectement.
Cette option spécifie quels en-têtes provenant des réponses de Teamserver doivent être supprimés avant d'atteindre le processus Beacon :```yaml
remove_these_response_headers:
- Content-Encoding
RedWarden supprimera désormais par défaut l'en-tête Content-Encoding des réponses du Teamserver, afin de maintenir la compatibilité avec les versions CS4.7+.
Jetons un coup d'œil à la sortie produite par le proxy.
Avec l'option verbose: True, la verbosité sera réglée au maximum sur INFO, indiquant les requêtes acceptées et celles rejetées.
La requête peut être acceptée si elle satisfait à tous les critères configurés dans le fichier de configuration de RedWarden. Une telle situation sera suivie d'une entrée de log [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]
Si la requête échoue à l'un des contrôles que RedWarden effectue sur chaque requête, la ligne `[DROP, ...]` correspondante sera émise contenant des informations sur la **raison**.:```
[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 /
Il existe de nombreuses raisons déterminant si une requête peut être rejetée. Chacune de ces vérifications peut être activée ou désactivée indépendamment selon les besoins ou dans un processus de réglage fin ou de correction de décisions erronées:
Extrait de 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
Par défaut, toutes ces vérifications sont appliquées.
Activer `debug: True` inondera votre tampon de console avec de nombreuses lignes de journal décrivant chaque étape du processus décisionnel complexe de RedWarden.
Si vous souhaitez voir le corps complet de vos requêtes et réponses, réglez `debug` et `trace` sur true et préparez-vous à être submergé par les journaux !
## FAQ
**- Ce programme peut-il fonctionner sans profil Malleable ?**
Oui, il le peut. Cependant, la logique d'inspection des requêtes sera désactivée ; le reste devrait fonctionner correctement : application de la géolocalisation IP, logique de recherche inverse, liste des IP bannies, etc.
**- Ce programme peut-il être facilement adapté à d'autres frameworks C2 ? Comme Mythic, Covenant, etc. ?**
Non facilement. Avec des efforts, oui. Comme je l'ai décrit plus bas, l'outil est mal écrit, ce qui rendra l'adaptation à d'autres C2 fastidieuse. Cependant, c'est tout à fait réalisable avec un peu de temps et d'efforts.
**- Mes paquets sont rejetés. Pourquoi ?**
Essayez d'activer `debug: True` et `trace: True` pour collecter autant de journaux que possible. Ensuite, vous devrez parcourir les journaux et inspecter ce qui se passe. Les paquets ressemblent-ils exactement à ce que vous attendiez dans votre profil Malleable ? Ou peut-être y a-t-il eu une altération subtile le long du réseau qui amène RedWarden à rejeter le paquet (et cela pourrait également amener Teamserver à le rejeter ?).
## Problèmes connus
- Cela _peut_ ajouter une légère surcharge au débit du sommeil interactif
- La logique de traitement de ProxyPass est loin d'être parfaite et est _vraiment_ boguée (et oh là là, c'est moche !).
- Des formes étranges de fichiers de configuration peuvent dérailler l'analyseur de RedWarden et le faire se plaindre. L'approche la plus simple pour contourner ce problème serait de copier `example-config.yaml` et de travailler dessus à la place.
## Oh mon Dieu, pourquoi ce code est-il une telle merde d'ingénierie ?
Le code est _UN VRAI BORDEL MONSTRUEUX_ - je l'admets - et il y a aussi une raison honnête à cela : le projet a été développé à 90 % pendant des missions réelles de Red Team. Comme nous le savons tous, ce genre de missions implique tellement de choses à faire qu'il ne reste quasiment pas de temps pour un développement d'outil complexe approprié. Sans parler de la criticité de ce programme dans la configuration du projet. L'outil a commencé comme un simple script proxy écrit en Python2, pour ensuite évoluer en un proxy avec des plugins, a reçu le plugin `malleable_redirector` - et depuis, j'ai essayé très fort de maintenir la compatibilité ascendante de `proxy2` (pauvre de moi, j'étais comme Microsoft !) avec les autres plugins que j'ai créés et de rester fidèle à son objectif initial.
Cependant, le moment est venu de le laisser tomber, de le renommer et de commencer à corriger toutes les mauvaises pratiques de code introduites.
Cela dit, je vous prie de bien vouloir faire preuve d'un peu de compassion à mon égard lorsque vous ouvrez des issues, soumettez des pull requests et essayez d'aider plutôt que de juger ! :-)
Merci !
## TODO
- Rechercher la possibilité d'utiliser des flux de Threat Intelligence à des fins malveillantes - par exemple détecter les fournisseurs de sécurité en fonction des IPs
- Ajouter le support de la base de données/API MaxMind GeoIP
- Implémenter le support des signatures JA3 à la fois pour la détection et le blocage, et pour l'usurpation afin de simuler des configurations nginx/Apache2/personnalisées.
- Ajouter une logique de suivi unique des beacons pour offrir la flexibilité de refuser les processus de staging et de communication à la discrétion du proxy
- Introduire une contrainte de jour et d'heure lors de l'offre de capacités de redirection (_proxy uniquement pendant les heures de bureau_)
- Ajouter une logique d'authentification et d'autorisation du proxy sur CONNECT/relais.
- Ajouter une redirection ciblée pour les utilisateurs mobiles
- Ajouter des options de configuration pour définir des en-têtes HTTP personnalisés à injecter ou à supprimer
- Ajouter des options de configuration pour exiger que des en-têtes HTTP spécifiques soient présents dans les requêtes répondant aux critères de ProxyPass.
- Interface interactive permettant de taper des caractères simples pour contrôler la verbosité des journaux de sortie, similaire à celle de Nmap
- Réécrire la logique d'analyse du profil Malleable avec [pyMalleableC2](https://github.com/Porchetta-Industries/pyMalleableC2). Lorsque j'ai commencé à coder ma propre logique d'analyse, il n'existait pas encore un tel outil sur Github.
- Refactoriser toute la base de code
---
### ☕ Montrez votre soutien ☕
Ce projet et d'autres sont le fruit de nuits blanches et de **beaucoup de travail acharné**. Si vous aimez ce que je fais et appréciez que je donne toujours en retour à la communauté, [Envisagez de m'offrir un café](https://github.com/sponsors/mgeeky) _(ou mieux une bière)_ juste pour dire merci ! 💪
---
## Auteur```
Mariusz Banach / mgeeky, '19-'21
<mb [at] binary-offensive.com>
(https://github.com/mgeeky)