
Proxy inverso C2 di Cobalt Strike che respinge Blue Teams, AV, EDR, scanner attraverso l'ispezione dei pacchetti e la correlazione del profilo malleabile
(precedentemente noto come plugin malleable_redirector di proxy2)
Alziamo l'asticella nella resilienza IR dei redirector C2, che ne dite?

Il settore del Red Teaming ha visto diverse differenti ottime idee su come combattere gli incident responder e disorientarli offrendo allo stesso tempo una rete di redirector C2 resistente.
Questo lavoro combina molte di quelle grandi idee in un unico, leggero strumento, imitando Apache2 nelle sue radici di semplice proxy inverso HTTP(S).
Combinando la comprensione dei profili Malleable C2, la conoscenza del pool di indirizzi IP dannosi e la flessibilità di aggiungere facilmente nuova logica di ispezione e disorientamento - si è ottenuto un astuto repellente per le ispezioni IR.

Se un qualsiasi pacchetto in entrata non valido raggiunge RedWarden - puoi redirect, reset o semplicemente proxy via!
Questo programma agisce come un proxy inverso HTTP/HTTPS con diverse restrizioni imposte sulle richieste HTTP C2 in entrata, selezionando quali pacchetti indirizzare al Teamserver e quali scartare, in modo simile alle restrizioni dei file .htaccess imposte da mod_rewrite di Apache2.
RedWarden è stato creato per risolvere il problema dell'evasione di IR/AV/EDR/Sandbox a livello di redirector C2. Ha lo scopo di sostituire le classiche configurazioni Apache2 + mod_rewrite utilizzate per questo scopo.
Caratteristiche:
RedWarden prende in input il profilo Malleable C2 e l'hostname:port del teamserver. Quindi analizza le sezioni del profilo malleable fornito per comprendere il contratto e far passare solo quelle richieste in entrata che lo soddisfano, disorientando le altre.
Sezioni come http-stager, http-get, http-post e i corrispondenti uri, header, pattern prepend/append, User-Agent sono tutti utilizzati per distinguere tra una richiesta legittima del beacon e il rumore Internet non correlato o i pacchetti fuori limite di IR/AV/EDR.
Il programma beneficia dei meravigliosi intervalli IP dannosi noti provenienti da: curi0usJack e gli altri: https://gist.github.com/curi0usJack/971385e8334e189d93a6cb4671238b10
L'uso di una blacklist di indirizzi IP insieme alla ricerca di parole chiave dannose note attraverso query DNS Reverse-IP e l'ispezione degli header HTTP, porta l'affidabilità ad aumentare considerevolmente la resilienza del redirector verso peer non autorizzati che vogliono esaminare le infrastrutture degli attaccanti.
I pacchetti non validi possono essere deviati secondo tre strategie:
Questa configurazione è imposta nel file di configurazione:```yaml
drop_action: redirect
Below example shows outcome of `redirect` to `https://googole.com`:

Usalo con saggezza, stai al sicuro.
### Requisiti
Questo programma può funzionare solo su sistemi Linux poiché utilizza fork per generare più processi.
Inoltre, si presuppone che il comando di sistema `openssl` sia installato, poiché viene utilizzato per generare certificati SSL.
Infine, installa tutti i requisiti Python3 PIP facilmente con:```shell
bash $ sudo pip3 install -r requirements.txt
Il file di configurazione config.yaml minimo di RedWarden potrebbe contenere:```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
Quindi, il programma può essere avviato fornendo il percorso del file di configurazione:```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]
[...]
L'output sopra contiene una riga che segnala che c'è stata una richiesta in entrata non autorizzata, non conforme al nostro profilo C2, che è stata scartata a causa di una stringa User-Agent incompatibile presentata:``` [...] [DROP, reason:1] inbound User-Agent differs from the one defined in C2 profile. [...]
## Casi d'uso
### Imporre la geolocalizzazione IP sugli originatori del traffico Beacon
Hai svolto molto bene le fasi di Pre-Phish e OSINT. Ora sai dove vivono i tuoi target e hai alcuni indizi su da dove il traffico dovrebbe provenire, o almeno come rilevare traffico completamente ausiliario.
Come imporre la geolocalizzazione IP sulle richieste Beacon su un redirector?
RedWarden viene in aiuto!
Supponiamo che tu voglia accettare solo traffico proveniente dalla Polonia, Europa.
I tuoi risultati di Pre-Phish/OSINT indicano che:
- `89.64.64.150` è un IP legittimo di uno dei tuoi target, proveniente dalla Polonia
- `59.99.140.76` invece questo non lo è e ha raggiunto i tuoi sistemi come un normale pacchetto di rumore Internet.
Puoi utilizzare l'utility di RedWarden `lib/ipLookupHelper.py` per raccogliere metadati di geolocalizzazione IP su questi due indirizzi:```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
Il primo porta:```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" }
e quest'ultimo dà:```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": ""
}
Ora vedi che il primo aveva "country": "Poland" mentre il secondo "country": "India". Con questa conoscenza siamo pronti a elaborare i nostri vincoli sotto forma di un corposo dizionario YAML:```yaml
ip_geolocation_requirements:
organization:
continent:
continent_code:
country:
- Poland
- PL
- Polska
country_code:
city:
timezone:
Ciascuna delle voci di quel dizionario accetta un'espressione regolare da abbinare ai metadati IP Geo determinati dell'indirizzo IP del peer in ingresso.
Utilizziamo tre voci nella proprietà `country` per consentire richieste che hanno uno dei valori specificati.
Con questa impostazione nella configurazione, puoi verificare se un altro indirizzo IP verrebbe passato attraverso il discriminatore di geolocalizzazione IP di RedWarden o meno con l'utilità `ipLookupHelper` che accetta un secondo parametro:

L'ultima riga ti dice se il pacchetto verrebbe bloccato o accettato.
E questo è tutto! Configura le tue restrizioni di geolocalizzazione IP con saggezza e sicurezza, ispeziona attentamente i log di RedWarden per eventuali voci DROP relative a IP Geo e mantieni il tuo traffico C2 pulito e ordinato!
### Riparare richieste Beacon manomesse
Se ti capita di utilizzare sistemi intermedi come AWS Lambda o CloudFlare come Domain Fronting / reindirizzatori, ti sarai sicuramente imbattuto in una situazione in cui alcuni dei tuoi pacchetti non potevano essere accettati dal Teamserver perché si discostavano dal contratto malleabile concordato. Che si trattasse di un'intestazione HTTP manomessa o rimossa, cookie riordinati o qualsiasi altra cosa - scommetto che ti ha fatto perdere ore della tua vita.
Per combattere i problemi del processo di configurazione dei canali C2 e le manomissioni dei sistemi intermedi, RedWarden offre funzionalità per riparare i pacchetti Beacon.
Lo fa controllando cosa il profilo malleabile si aspetta che sia un pacchetto e può ripristinare le intestazioni HTTP configurate ai loro valori concordati secondo i requisiti del profilo.
Considera il seguente profilo semplice:```
http-get {
set uri "/api/abc";
client {
header "Accept-Encoding" "gzip, deflate";
metadata {
base64url;
netbios;
base64url;
parameter "auth";
}
}
...
Vedi questo Accept-Encoding? Ogni richiesta del Beacon deve includere quell'Header e quel valore. Cosa succede se il tuo Beacon colpisce i sistemi CloudFlare e questi emettono una richiesta che verrà privata di quell'Header o avrà Accept-Encoding: gzip? Il Teamserver scarterà la richiesta immediatamente.
Impostando questo header nella sezione di configurazione di RedWarden denominata repair_these_headers puoi salvare la tua connessione.:```yaml
repair_these_headers:
### Rimuovi header di risposta problematici
Con Cobalt Strike 4.7+ ho notato che Teamserver rimuove automaticamente l'header Content-Encoding senza alcun preavviso, violando così il nostro contratto malleable `http-(get|post).server`.
Poiché RedWarden seguiva il contratto, Beacon stava eliminando le risposte o decomprimendole in modo errato.
Questa opzione specifica quali header provenienti dalle risposte di Teamserver devono essere rimossi prima di raggiungere il processo Beacon:```yaml
remove_these_response_headers:
- Content-Encoding
RedWarden rimuoverà ora l'intestazione Content-Encoding dalle risposte del Teamserver di default, per mantenere la compatibilità con le versioni CS4.7+.
Diamo un'occhiata all'output prodotto dal proxy.
Con l'opzione verbose: True, la verbosità sarà impostata su INFO al massimo, indicando le richieste accettate rispetto a quelle rifiutate.
La richiesta può essere accettata se soddisfa tutti i criteri configurati nel file di configurazione di RedWarden. Tale situazione sarà seguita da un log di ingresso [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]
Se la richiesta non supera uno dei controlli che RedWarden esegue su ogni richiesta, la corrispondente riga `[DROP, ...]` verrà emessa contenente informazioni sul **motivo** della caduta.:```
[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 /
Ci sono molte ragioni che determinano se una richiesta può essere scartata. Ciascuno di questi controlli può essere attivato o disattivato indipendentemente in base alle esigenze o in un processo di messa a punto o di correzione di decisioni errate:
Estratto da 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
Per impostazione predefinita, tutti questi controlli sono attivi.
Attivare `debug: True` inonderà il buffer della console con molte righe di log che descrivono ogni passo del complesso processo decisionale di RedWarden.
Se vuoi vedere i corpi completi delle richieste e delle risposte - imposta `debug` e `trace` a true e lasciati seppellire dal carico di logging!
## FAQ
**- Questo programma può funzionare senza un Malleable Profile?**
Sì, può. Tuttavia la logica di ispezione delle richieste sarà disattivata, il resto dovrebbe funzionare: applicazione della geolocalizzazione IP, logica di reverse-lookup, lista IP bannati, ecc.
**- Questo programma può essere facilmente adattato ad altri framework C2? Come Mythic, Covenant, ecc.?**
Facilmente no. Con un po' di sforzo - sì. Come ho descritto sotto, lo strumento è scritto male, il che renderà l'adattamento ad altri C2 una seccatura. Tuttavia è assolutamente fattibile con un po' di tempo e impegno.
**- I miei pacchetti vengono scartati. Perché?**
Prova ad attivare `debug: True` e `trace: True` per raccogliere quanti più log possibili. Poi dovrai esaminare i log e capire cosa sta succedendo. I pacchetti hanno l'aspetto che ti aspettavi nel tuo profilo Malleable? O forse c'è stata una sottile manomissione lungo la rete che ha causato lo scarto del pacchetto da parte di RedWarden (e potrebbe far scartare il pacchetto anche al Teamserver?).
## Problemi noti
- Può _aggiungere_ un leggero overhead al throughput del sleep interattivo
- La logica di elaborazione di ProxyPass è tutt'altro che perfetta ed è _davvero_ piena di bug (e oh ragazzi, è brutta!).
- Forme strane di file di configurazione possono far deragliare il parser di RedWarden e farlo lamentare. L'approccio più semplice per superare questo problema è copiare `example-config.yaml` e lavorare su quello invece.
## Oh mio dio, perché questo codice è un tale schifo ingegneristico?
Il codice è _UN ENORME CASINO_ - lo ammetto - e c'è anche una ragione onesta per questo: il progetto è stato sviluppato al 90% durante vere attività di Red Team. Come tutti sappiamo, questo tipo di impegni comporta così tante cose da fare, lasciando poco tempo per uno sviluppo adeguato di uno strumento complesso. Per non parlare della criticità di questo programma nella configurazione del progetto. Lo strumento inizialmente è nato come un semplice script proxy scritto in Python2, per poi evolversi in un proxy con plugin, ha ricevuto il plugin `malleable_redirector` - e da allora ho cercato molto duramente di mantenere la compatibilità all'indietro di `proxy2` (povero me, ero come Microsoft!) con altri plugin che ho creato e di restare fedele al suo scopo originale.
Tuttavia è arrivato il momento di lasciarlo andare, rinominarlo e iniziare a correggere tutti i cattivi odori del codice introdotti.
Detto questo, per favore mostrate un po' di compassione per me quando aprite issue, inviate pull request e cercate di aiutare piuttosto che giudicare! :-)
Grazie!
## TODO
- Ricercare la possibilità di utilizzare feed di Threat Intelligence per scopi malevoli - come ad esempio rilevare i fornitori di sicurezza basandosi sugli IP
- Aggiungere supporto per il database/API MaxMind GeoIP
- Implementare il supporto per le firme JA3 sia nel rilevamento e blocco che nell'impersonificazione per falsificare setup nginx/Apache2/personalizzati.
- Aggiungere una logica di tracciamento unica dei beacon per offrire flessibilità nel rifiutare i processi di staging e comunicazione a discrezione del proxy
- Introdurre vincoli di orario per offrire capacità di reindirizzamento (_proxy solo durante l'orario di ufficio_)
- Aggiungere logica di autenticazione e autorizzazione del proxy su CONNECT/relay.
- Aggiungere reindirizzamento mirato per utenti mobili
- Aggiungere opzioni di configurazione per definire intestazioni HTTP personalizzate da iniettare, o da rimuovere
- Aggiungere opzioni di configurazione per richiedere che specifiche intestazioni HTTP siano presenti nelle richieste che superano i criteri di ProxyPass.
- Interfaccia interattiva che permette di digitare semplici caratteri per controllare la verbosità del logging dell'output, simile a quella di Nmap
- Riscrivere la logica del parser del profilo Malleable utilizzando [pyMalleableC2](https://github.com/Porchetta-Industries/pyMalleableC2). Quando ho iniziato a scrivere la mia logica di parser, non esisteva un tale toolkit su Github.
- Rifattorizzare tutta la codebase
---
### ☕ Mostra Supporto ☕
Questo progetto e altri sono il risultato di notti insonni e **molto duro lavoro**. Se ti piace quello che faccio e apprezzi che restituisco sempre alla comunità,
[Considera di offrirmi un caffè](https://github.com/sponsors/mgeeky) _(o meglio una birra)_ solo per dirti grazie! 💪
---
## Autore```
Mariusz Banach / mgeeky, '19-'21
<mb [at] binary-offensive.com>
(https://github.com/mgeeky)