It Instalando CTFd no Ubuntu 20.04 com Nginx e uWSGI
Post
Cancel

Instalando CTFd no Ubuntu 20.04 com Nginx e uWSGI

CTFd é uma plataforma desenvolvida em Python para organização de jogos no estilo Capture sua Bandeira (Capture The Flag) muito comum em ambientes controlados de Segurança Ofensiva e Defensiva. Segue a url do fabricante (https://ctfd.io/)

Como demorei para encontrar tutoriais completos e atualizados resolvi juntar tudo em um só e funcional para vocês. Até a versão 18.04 do Ubuntu há um tutorial funcional utilizando a aplicação gunicorn, porém como este pacote foi descontinuado na versão 20.04 do Ubuntu tive que buscar uma forma de fazer e é este trabalho que trago para vocês de forma organizada e comando por comando.

Instalando pacotes e dependências

Antes de mais nada se faz necessário realizar a instalação de todas as dependências necessárias para o correto funcionamento do ambiente.

Adicionando repositório do nginx no ambiente

1
2
root@M4v3r1ck:~# echo deb http://nginx.org/packages/mainline/ubuntu/ `lsb_release --codename --short` nginx > /etc/apt/sources.list.d/nginx.list
root@M4v3r1ck:~# curl -s http://nginx.org/keys/nginx_signing.key | apt-key add -

Atualizando o ambiente

1
root@M4v3r1ck:~# apt-get update && apt-get -y upgrade

Instalando pacotes e dependências

1
root@M4v3r1ck:~# apt install nginx python3 python3-pip python3-dev build-essential libssl-dev libffi-dev python3-setuptools python3-venv

Pré-configurando o NGINX

Como utilizaremos o NGINX como um proxy reverso para expor o CTFd para a internet, então vamos realizar uma pré-configuração do mesmo, para posteriormente ajustar para a configuração final. Estamos fazendo isso neste ponto pois logo a frente iremos realizar um teste inicial de acesso ao CTFd, e para isso precisaremos que essa comunicação já seja realizada via NGINX.

Edite o arquivo /etc/nginx/nginx.conf para que o mesmo fique exatamente conforme abaixo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    limit_conn_zone $binary_remote_addr zone=addr:10m;
    server_names_hash_bucket_size  256;

    client_max_body_size 10m;

    log_format log_standard '$remote_addr, $http_x_forwarded_for - $remote_user [$time_local] "$request_method $scheme://$host$request_uri $server_protocol" $status $body_bytes_sent "$http_referer" "$http_user_agent" to: $upstream_addr';

    access_log /var/log/nginx/access.log log_standard;
    error_log /var/log/nginx/error.log;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}

Edite o arquivo /etc/nginx/conf.d/default.conf de forma que o mesmo fique com o conteúdo abaixo:

1
2
3
4
5
6
7
8
9
10
11
12
server {
    listen      80;
    server_name _;

    location / {

        proxy_pass http://127.0.0.1:8080;
        #include uwsgi_params;
        #uwsgi_pass unix:/home/ctfd/CTFd/ctfd.sock;

    }
}

Reinicie o nginx

1
root@M4v3r1ck:~# /etc/init.d/nginx restart

Instalando e configurando o CTFd

Agora que temos o nginx já funcional, podemos instalar o CTFd e suas dependências.

Adicione o usuário e grupo conforme abaixo

1
2
root@M4v3r1ck:~# groupadd ctfd
root@M4v3r1ck:~# adduser --disabled-password --ingroup ctfd ctfd

Altere para o contexto do usuário

1
root@M4v3r1ck:~# su - ctfd

Realize o download do CTFd. Note que o comando está sendo executado com o usuário ctfd e dentro do seu diretório home (/home/ctfd)

1
ctfd@M4v3r1ck:~$ git clone https://github.com/CTFd/CTFd.git

Agora vamos criar um ambiente virtual para isolar o nosso ambiente de outras aplicações python.

1
ctfd@M4v3r1ck:~$ python3 -m venv CTFd

Isso instalará uma cópia local do Python e do pip para um diretório chamado CTFd.

Antes de instalar aplicativos no ambiente virtual, você precisa ativá-lo. Faça isso digitando:

1
ctfd@M4v3r1ck:~$ source CTFd/bin/activate

Seu prompt mudará para indicar que você agora está operando no ambiente virtual. Ele se parecerá com isso (CTFd) ctfd@M4v3r1ck:~$.

Agora vamos instalar todas as dependências python necessárias para o ctfd.

Independente da versão do Python neste ponto usar o pip ao invés do pip3 (pois já estamos dentro de um ambiente python3)

Primeiramente, vamos instalar o wheel com a instância local do pip para garantir que nossos pacotes serão instalados mesmo se estiverem faltando arquivos wheel:

1
(CTFd) ctfd@M4v3r1ck:~$ pip install wheel

Posteriormente, iremos instalar o uwsgi, flask e as dependências

1
2
(CTFd) ctfd@M4v3r1ck:~$ pip install uwsgi flask testresources werkzeug==0.16.0
(CTFd) ctfd@M4v3r1ck:~$ pip install -r CTFd/requirements.txt

Agora podemos testar o sistema

1
2
(CTFd) ctfd@M4v3r1ck:~$ cd CTFd
(CTFd) ctfd@M4v3r1ck:~/CTFd$ uwsgi --socket 0.0.0.0:8080 --protocol=http -w wsgi:app

Abra o seu navegador e acesse o IP do seu servidor http://[IP], a imagem igual abaixo deve ser exibida

Imagem ilustrativa

Quando você tiver confirmado que ele está funcionando corretamente, pressione CTRL-C na janela do seu terminal.

Acabamos agora o nosso ambiente virtual, para que possamos desativá-lo:

1
(CTFd) ctfd@M4v3r1ck:~$ deactivate

Agora, qualquer comando Python voltará a usar o ambiente do sistema Python.

Criar arquivo ctfd.ini

Note que neste arquivo iremos definir o modo de conexão (entre o nginx e o wsgi) como sendo um socket unix que é mais rápido e seguro.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[uwsgi]
module = wsgi:app

master = true
processes = 5

pidfile = ctfd.pid
socket = ctfd.sock
chmod-socket = 660
vacuum = true

die-on-term = true

logto = /var/log/ctfd/%n.log

Volte ao acesso como root

1
ctfd@M4v3r1ck:~$ exit

Os comandos agora são executados como root.

Crie o diretório de logs e defina sua permissão

1
2
ctfd@M4v3r1ck:~# mkdir /var/log/ctfd
ctfd@M4v3r1ck:~# chown ctfd:adm /var/log/ctfd/

Crie o arquivo para logrotate com nome /etc/logrotate.d/ctfd com o seguinte conteúdo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/var/log/ctfd/*.log {
    daily
    missingok
    rotate 365
    compress
    datetext
    delaycompress
    notifempty
    create 640 ctfd adm
    sharedscripts
    postrotate
            if [ -f /home/ctfd/CTFd/ctfd.pid ]; then
                    kill -HUP `cat /home/ctfd/CTFd/ctfd.pid`
            fi
    endscript
}

Crie o arquivo /etc/systemd/system/ctfd.service

1
2
3
4
5
6
7
8
9
10
11
12
13
[Unit]
Description=CTFd Service
After=network.target

[Service]
User = ctfd
Group = nginx
WorkingDirectory=/home/ctfd/CTFd
Environment="PATH=/home/ctfd/CTFd/bin"
ExecStart=/home/ctfd/CTFd/bin/uwsgi --ini ctfd.ini

[Install]
WantedBy=multi-user.target

Podemos agora iniciar o serviço uWSGI que criamos e habilitá-lo para que ele seja iniciado na inicialização:

1
2
3
root@M4v3r1ck:~# systemctl daemon-reload
root@M4v3r1ck:~# systemctl enable ctfd
root@M4v3r1ck:~# systemctl start ctfd

Verifique o status

1
root@M4v3r1ck:~# systemctl status ctfd

Você deve ver um resultado como este:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
root@M4v3r1ck:~# systemctl status ctfd
● ctfd.service - CTFd Service
     Loaded: loaded (/etc/systemd/system/ctfd.service; enabled; vendor preset: enabled)
     Active: active (running) since Sat 2020-06-20 03:51:28 UTC; 8s ago
   Main PID: 27730 (uwsgi)
      Tasks: 6 (limit: 2249)
     Memory: 59.2M
     CGroup: /system.slice/ctfd.service
             ├─27730 /home/ctfd/CTFd/bin/uwsgi --ini ctfd.ini
             ├─27740 /home/ctfd/CTFd/bin/uwsgi --ini ctfd.ini
             ├─27741 /home/ctfd/CTFd/bin/uwsgi --ini ctfd.ini
             ├─27742 /home/ctfd/CTFd/bin/uwsgi --ini ctfd.ini
             ├─27743 /home/ctfd/CTFd/bin/uwsgi --ini ctfd.ini
             └─27744 /home/ctfd/CTFd/bin/uwsgi --ini ctfd.ini

Estando tudo correto agora vamos editar o nginx para se conectar ao wsgi através do socket unix que criamos.

Altere o arquivo /etc/nginx/conf.d/default.conf para:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
server {
    listen      80;
    server_name _;

    location / {

        uwsgi_param   Host                 $host;
        uwsgi_param   X-Real-IP            $remote_addr;
        uwsgi_param   X-Forwarded-For      $proxy_add_x_forwarded_for;
        uwsgi_param   X-Forwarded-Proto    $http_x_forwarded_proto;

        proxy_read_timeout 600;
        proxy_connect_timeout 1d

;
        proxy_max_temp_file_size 5024m;
        proxy_send_timeout 600;
        uwsgi_read_timeout 600;
        uwsgi_send_timeout 600;
        include uwsgi_params;

        uwsgi_pass unix:/home/ctfd/CTFd/ctfd.sock;

    }
}

Recarregue a configuração do nginx

1
root@M4v3r1ck:~# nginx -s reload

Realize o teste de acesso ao CTFd através da URL http://[IP]

Agora você tem o CTFd rodando na porta 80 do seu servidor, basta o teste de acesso ao CTFd através da URL http://[IP].

Fontes: