mgeeky / RedWarden

Cobalt Strike C2 Reverse proxy that fends off Blue Teams, AVs, EDRs, scanners through packet inspection and malleable profile correlation
GNU General Public License v3.0
885 stars 139 forks source link

Issue with new 4.7 beacon (maybe my error)? #23

Open ghost opened 1 year ago

ghost commented 1 year ago

Hello, first of all awesome tool as usual!

I'm having a strange issue when beacon will send first post data.

First connection seems ok, as it appear on my screen, but after that i get an error and everything seems welll setup (i think)

This is my error:

[DEBUG] 2022-09-30/17:51:49: Returning cached entry for IP address: REDACTED
[DEBUG] 2022-09-30/17:51:49: Analysing IP Geo metadata keywords...
[DEBUG] 2022-09-30/17:51:49: Extracted keywords from Peer's IP Geolocation metadata: REDACTED
[DEBUG] 2022-09-30/17:51:49: Peer's IP Geolocation metadata didn't raise any suspicion.
[DEBUG] 2022-09-30/17:51:49: Deep request inspection of URI (/jquery-3.3.1.min.js) parsed as section:http-get, variant:default
[DEBUG] 2022-09-30/17:51:49: Requests's MD5 hash computed: REDACTED
[ERROR] 2022-09-30/17:51:49: [DROP, 2022-09-30/19:51:49, reason:0, REDACTED] identical request seen before. Possible Replay-Attack attempt.
[ERROR] 2022-09-30/17:51:49: Exception catched in request_handler: cannot unpack non-iterable bool object
Uncaught exception GET /jquery-3.3.1.min.js (REDACTED)
HTTPServerRequest(protocol='https', host='REDACTED, method='GET', uri='/jquery-3.3.1.min.js', version='HTTP/1.1', remote_ip='REDACTED')
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/dist-packages/tornado/web.py", line 1713, in _execute
    result = await result
  File "/home/n0t/RedWarden/lib/proxyhandler.py", line 1176, in get
    self.my_handle_request()
  File "/home/n0t/RedWarden/lib/proxyhandler.py", line 289, in my_handle_request
    self._internal_my_handle_request(*args, **kwargs)
  File "/home/n0t/RedWarden/lib/proxyhandler.py", line 422, in _internal_my_handle_request
    output = handler()
  File "/home/n0t/RedWarden/lib/proxyhandler.py", line 529, in _my_handle_request
    (modified, req_body_modified) = self.request_handler(self.request, self.request.body)
  File "/home/n0t/RedWarden/lib/proxyhandler.py", line 1104, in request_handler
    req_body_current = handler(req, req_body_current)
  File "/home/n0t/RedWarden/lib/../plugins/malleable_redirector.py", line 1042, in request_handler
    return self._request_handler(req, req_body)
  File "/home/n0t/RedWarden/lib/../plugins/malleable_redirector.py", line 1064, in _request_handler
    drop_request = self.drop_check(req, req_body, malleable_meta)
  File "/home/n0t/RedWarden/lib/../plugins/malleable_redirector.py", line 1701, in drop_check
    (ret, reason) = self._client_request_inspect(section, variant, req, req_body, malleable_meta, ts, peerIP)
TypeError: cannot unpack non-iterable bool object

this error immediately appears on beacon's second request.

maybe i did something wrong? Thanks in advace

mgeeky commented 1 year ago

Hi!

Thank you for your issue request. Can you please check with the latest version if problem remains? I attempted to fix it in commit ba209002.

ghost commented 1 year ago

Hello, thanks for your answer!

I will try again ASAP and will let you know! Thanks in advance.

ghost commented 1 year ago

So, now there is this issue: Redirector now drops second and others requests.

[DEBUG] 2022-10-06/14:25:33: Returning cached entry for IP address: REDACTED
[DEBUG] 2022-10-06/14:25:33: Analysing IP Geo metadata keywords...
[DEBUG] 2022-10-06/14:25:33: Extracted keywords from Peer's IP Geolocation metadata: REDACTED
[DEBUG] 2022-10-06/14:25:33: Peer's IP Geolocation metadata didn't raise any suspicion.
[DEBUG] 2022-10-06/14:25:33: Deep request inspection of URI (/jquery-3.3.1.min.js) parsed as section:http-get, variant:default
[DEBUG] 2022-10-06/14:25:33: Requests's MD5 hash computed: REDACTED
[ERROR] 2022-10-06/14:25:33: [DROP, 2022-10-06/16:25:33, reason:0, REDACTED] identical request seen before. Possible Replay-Attack attempt.
[DROP, 2022-10-06/16:25:33, REDACTED, r:0] "/jquery-3.3.1.min.js" - UA: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36"
[DROP, 2022-10-06/16:25:33, REDACTED, r:0] "/jquery-3.3.1.min.js" - UA: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36"
[ERROR] 2022-10-06/14:25:34: [DROPPING invalid request from REDACTED (REDACTED)] GET /jquery-3.3.1.min.js
[ERROR] 2022-10-06/14:25:34: Plugin demanded to drop the request: (DropConnectionException: Not a conformant beacon request.)
REDACTED - - [06/Oct/2022:14:25:33 +0000] "GET /jquery-3.3.1.min.js HTTP/1.1" 0 0 "http://code.jquery.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36"

But i don't see errors / crashes now, maybe the issue is that with my profile it does always a request to the same file ? I'm using a clean https://github.com/threatexpress/malleable-c2/blob/master/jquery-c2.4.6.profile profile, without edits (the only edit is the added valid SSL cert)

I think he drops it as the cookies is always similar and headers + uri path are always the same.

But honestly idk how i can help you more

mgeeky commented 1 year ago

So at least it does not crash, that's something to work with.

Now the questions I have:

Let me know if any of these helped! I'll sit down to this and try with CS4.7 myself maybe tomorrow, will make sure to nail it down and fix it once and for all!

Kind regards, Mariusz.

ghost commented 1 year ago

Hello, thanks for the answer. 1 - yes i use it 2 - I should be using CF, but i make it dns only 3 - ok

I will try and let you know again,thanks again!

mgeeky commented 1 year ago

So yes, first of all I would disable mitigate_replay_attack as its not that useful after all and might be causing troubles here.

Secondly, in Cloudflare you can set up a Caching policy to not cache at all. Its somewhere under Page Rule -> Cache Level -> Bypass. Turning off cache, as well as purging currently held cached responses might push all your packets out to your Teamserver.

Thirdly, try the above two workarounds first. If you get your traffic flowing to teamserver - then there's no need to disable blocking (so no need to set report_only to True - keep it False so that RedWarden remains in blocking mode).

Let me know if that helped!

mgeeky commented 1 year ago

@h0nus

Can you please try RedWarden now? I've spent a lot of time troubleshooting issues related to Content-Encoding. So in a nutshell, if there's Accept-Encoding request header defined in your malleable-profile, RedWarden was able to go around it and not apply any sort of response body gzip compression. Now, starting in 4.7 something has changed in Teamserver - still unsure what.

But there two viable solutions:

  1. Either dont use Accept-Encoding and Content-Encoding headers in your malleable profile, at all
  2. Or use newly added YAML option named:

remove_these_response_headers:
  - Content-Encoding

and that should help. We now instruct RedWarden to strip Content-Encoding header from the Teamserver responses, similarly to how Teamserver 4.7 behaves.

Let me know if that helps!

Regards, Mariusz.

ghost commented 1 year ago

Hello, so, i've tried to: 1 - Remove those two headers from malleable config and from RedWarden config, still hangup on second request 2 - Disabled mitigate_replay_attack and use the new header config, still not working 3 - New config, i've just removed the Accept-Encoding header from malleable config, i've set the remove_these_response_headers as you said and removed the replay attack thing

Seems the beacon is not doing any POST requests, i wonder why? Should i try without any malleable to see it that would work? I get all "Host called home", but it won't get any data back due to the POST request not done. Thanks for your awesome work!

ghost commented 1 year ago

Little addition, here is the error of POST requests: image

And here the error from Red Warden:

[DEBUG] 2022-10-08/18:14:42: Peer's IP Geolocation metadata didn't raise any suspicion.
[DEBUG] 2022-10-08/18:14:42: (No malleable profile) Request contents validation skipped, as there was no profile provided.
[DEBUG] 2022-10-08/18:14:42: Peer reached the server at port: 443
[DEBUG] 2022-10-08/18:14:42: Redirecting to "https://127.0.0.1:4443/submit.php?id=1511878070"
[INFO] 2022-10-08/18:14:42: Plugin redirected request from [REDACTED] to [127.0.0.1:4443]
[DEBUG] 2022-10-08/18:14:42: Plugin redirected request to a full URL: (https://127.0.0.1:4443/submit.php?id=1511878070)
[DEBUG] 2022-10-08/18:14:42: Plugin overidden host header: [REDACTED] => [127.0.0.1:4443]
[ERROR] 2022-10-08/18:14:42: Could not proxy request: ('latin-1' codec can't encode character '\u067f' in position 128: ordinal not in range(256))
Uncaught exception POST https://127.0.0.1:4443/submit.php?id=1511878070 (REDACTED)
HTTPServerRequest(protocol='https', host='REDACTED', method='POST', uri='https://127.0.0.1:4443/submit.php?id=1511878070', version='HTTP/1.1', remote_ip='REDACTED')
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/dist-packages/tornado/web.py", line 1713, in _execute
    result = await result
  File "/home/n0t/RedWarden/lib/proxyhandler.py", line 1184, in post
    self.my_handle_request()
  File "/home/n0t/RedWarden/lib/proxyhandler.py", line 289, in my_handle_request
    self._internal_my_handle_request(*args, **kwargs)
  File "/home/n0t/RedWarden/lib/proxyhandler.py", line 422, in _internal_my_handle_request
    output = handler()
  File "/home/n0t/RedWarden/lib/proxyhandler.py", line 701, in _my_handle_request
    self.logger.dbg('DEBUG REQUESTS: request("{}", "{}", "{}", ...'.format(
  File "/home/n0t/RedWarden/lib/proxylogger.py", line 125, in dbg
    ProxyLogger.out(txt, self.options['log'], 'debug', **kwargs)
  File "/home/n0t/RedWarden/lib/proxylogger.py", line 88, in out
    ProxyLogger.writeToLogfile(fd, line)
  File "/home/n0t/RedWarden/lib/proxylogger.py", line 101, in writeToLogfile
    f.write(line)
UnicodeEncodeError: 'latin-1' codec can't encode character '\u067f' in position 128: ordinal not in range(256)

strange, as i didn't touch anything and i'm using no malleable config at all.

mgeeky commented 1 year ago

Hi, so this week I might be unable to sit down to your issue, but I've experienced it too! Just be sure I'm tracking it and trying to nail it down.

So that exception you've shown means that RedWarden tried to print your request/response which contained binary data - therefore unprintable. That's expected, but I should have anticipate that and prepare. As a quick workaround you can try just surround that 101 line in proxylogger.py with:

try:
    f.write(line)
except:
   pass

Its ugly, but will work until I got something better. Now, I also experienced no POST requests coming from CS4.7+. Still unsure what have changed in Cobalt Strike, but I speculate they might have changed something with Teamserver request/response contents.

So it would really help if you could provide me with your anonymized malleable profile and RedWarden YAML config. Feel free to anonymise (Find & Replace) all sensitive details, header values, user-agent and so on. I just need to be able to recreate your specific issue - because last commit fixed the issues I've experienced.

Thanks a lot for cooperating with me on this one! :) Regards, Mariusz.

ghost commented 1 year ago

Hello, to my analysis, seems sometimes it tries to do some POST (the submit.php request with id), but seems it fails due to that error. I will try with your adviced "fix" and i will let you know ! Thanks one more time :)

I will send you also here the profiles i'm using and yaml config .

mgeeky commented 1 year ago

Let me know - looking forward to it. I really need to hunt this down cause it might be affecting all the users and might get the communication impossible so treating it really seriously. I'll wait for your YAML and profile then.

You can send me to my mail if you prefer - mb [at] binary-offensive.com

ghost commented 1 year ago

Email sent :) Let me know!