mitre / caldera

Automated Adversary Emulation Platform
https://caldera.mitre.org
Apache License 2.0
5.65k stars 1.07k forks source link

Caldera uses insecure_certificate.pem even when the haproxy conf states a different certificate #2934

Closed Pablo-offsec closed 7 months ago

Pablo-offsec commented 7 months ago

Hey team,

I am having trouble with the SSL plugin, hoping you can help me out.

I have followed the steps from the documentation to enable SSL plugin as stated here: https://caldera.readthedocs.io/en/latest/Plugin-library.html#ssl

Setup:

Version: 4.2.0

I generated a new self signed certificate using the same command as mentioned in the doc: openssl req -x509 -newkey rsa:4096 -out conf/certificate.pem -keyout conf/certificate.pem -nodes and I have this new cert in the following path: plugins/ssl/conf/certificate.pem.

I also have a haproxy.conf file in the same folder and here are the contents of the conf file:

global
    maxconn 20000
    nbproc 1
    nbthread 4
    ssl-default-bind-ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
    ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets

defaults
    timeout connect 10s
    timeout client 30s
    timeout server 30s
    mode http
    option forwardfor
    option http-server-close

frontend caldera-https
    bind *:8443 ssl crt plugins/ssl/conf/certificate.pem
    http-request add-header proxy_port 8443
    http-request set-header X-Forwarded-Proto https
    default_backend caldera_server

backend caldera_server
    balance leastconn
    cookie SERVERUSED insert indirect nocache
    default-server maxconn 20
    server caldera_main 127.0.0.1:8888 cookie caldera_main

so I am using the self signed certificate for HTTPS connection.

As far as caldera conf goes, I have made a copy of the default.yml file to local.yml file and added ssl in the plugins. Here are the contents of the local.yml file under /conf.

ability_refresh: 60
api_key_blue: BLUEADMIN123
api_key_red: ADMIN123
app.contact.dns.domain: mycaldera.caldera
app.contact.dns.socket: 0.0.0.0:8853
app.contact.ftp.host: 0.0.0.0
app.contact.ftp.port: 2222
app.contact.ftp.pword: caldera
app.contact.ftp.server.dir: ftp_dir
app.contact.ftp.user: caldera_user
app.contact.gist: API_KEY
app.contact.html: /weather
app.contact.http: http://0.0.0.0:8888
app.contact.slack.api_key: SLACK_TOKEN
app.contact.slack.bot_id: SLACK_BOT_ID
app.contact.slack.channel_id: SLACK_CHANNEL_ID
app.contact.tcp: 0.0.0.0:7010
app.contact.tunnel.ssh.host_key_file: REPLACE_WITH_KEY_FILE_PATH
app.contact.tunnel.ssh.host_key_passphrase: REPLACE_WITH_KEY_FILE_PASSPHRASE
app.contact.tunnel.ssh.socket: 0.0.0.0:8022
app.contact.tunnel.ssh.user_name: sandcat
app.contact.tunnel.ssh.user_password: s4ndc4t!
app.contact.udp: 0.0.0.0:7011
app.contact.websocket: 0.0.0.0:7012
auth.login.handler.module: default
crypt_salt: REPLACE_WITH_RANDOM_VALUE
encryption_key: ADMIN123
exfil_dir: /tmp/caldera
host: 0.0.0.0
objects.planners.default: atomic
plugins:
- access
- atomic
- compass
- debrief
- fieldmanual
- manx
- response
- sandcat
- stockpile
- training
- ssl
port: 8888
reports_dir: /tmp
requirements:
  go:
    command: go version
    type: installed_program
    version: 1.11
  python:
    attr: version
    module: sys
    type: python_module
    version: 3.7.0
users:
  blue:
    blue: admin
  red:
    admin: admin
    red: admin

Now the setup works as expected and I do see SSL enabled but I get a warning: Insecure SSL private key and certificate in use. Consider generating and using your own to improve security. Please see documentation.

Why am I getting this error? Do I need to change something else for caldera to start using my self signed cert?

Debugging

Out of curiosity, I removed the insecure_certificate.pem file and renamed the certificate.pem to insecure_certificate.pem. I also added a new line to print the server certificate in hook.py under method _check_using_default_cert():

async def _check_using_default_cert():
    await asyncio.sleep(5)
    server_cert = get_server_certificate(('127.0.0.1', 8443))
    print(server_cert)
    default_cert = _read_default_cert()
    if server_cert == default_cert:
        logging.warn('Insecure SSL private key and certificate in use. Consider generating and using your own '
                     'to improve security. Please see documentation.')

To my surprise, the server certificate is still the same as the insecure_certificate which I have deleted, so is this value stored somewhere or am I missing something?

Can you help me out here.

github-actions[bot] commented 7 months ago

Looks like your first issue -- we aim to respond to issues as quickly as possible. In the meantime, check out our documentation here: http://caldera.readthedocs.io/

Guil33 commented 7 months ago

Doing the same as you seem to have done (i.e. creating a self-signed and editing the bind line with the new certificate in the haproxy conf file, Caldera uses the correct certificate and displays no warning on my instance.

Your local.yml looks fine to me, but... Why did you create it by copying default.yml? Did you maybe not remove the insecure flag?

Pablo-offsec commented 7 months ago

I was reading some blog somewhere where they created a copy of default.yml and renamed it to local.yml.

But I tried cloning caldera again and adding ssl in default.yml and then letting caldera generate the local.yml with credentials for caldera. When I ran the server for the first time, it was still using insecure_certificate.pem but when I restarted the server, I see no errors now and I also made changes in hook.py to confirm that my new self signed certificate is being used.

Not sure why I was getting an error in the first place, maybe I should let caldera create the local.yml file rather than copy pasting it myself.

I don't need any help on this at the moment and thanks for taking a look into this. Will reach out again if I need any help.