272 lines
11 KiB
Bash
272 lines
11 KiB
Bash
#!/usr/bin/env bash
|
|
if [ "$(id -u)" -ne "0" ]; then
|
|
echo "This script must be run as root" >&2
|
|
exit 1
|
|
fi
|
|
### CONFIGURATION ###
|
|
LICENSES=100
|
|
DOMAIN='test.com'
|
|
BUSINESS_NAME='Awesome Hackers LTD'
|
|
BUSINESS_EMAIL='ceo@test.com'
|
|
HAXHQ_USER_NICKNAME='hacker1'
|
|
HAXHQ_USER_JOBTITLE='Senior Pen Tester'
|
|
HAXHQ_USER_EMAIL='hacker1@test.com'
|
|
INSTALLDIR='/opt/haxhq.com/'
|
|
DBNAME='haxhq'
|
|
DBUSER='flask'
|
|
REPO='haxhq'
|
|
OS_ADMIN_USER='operations'
|
|
CADIR='/opt/easyrsa'
|
|
HAXHQ_RUNAS='haxhq'
|
|
### END CONFIGURATION ###
|
|
#apt -y install vim sudo tcpdump iptables-persistent ntp net-tools nullmailer aptitude libmime-lite-perl man-db manpages-posix curl wget
|
|
apt -y install git nginx postgresql python3-venv memcached sudo aptitude ntp
|
|
CA_KEY=`openssl rand -base64 42`
|
|
CSRF_KEY=`openssl rand -base64 42`
|
|
DBPASS=`openssl rand -base64 32`
|
|
WORDS=`shuf -n3 /usr/share/dict/words | tr '\n' ' '`
|
|
OS_ADMIN_PASS="${WORDS::-1}" # remove the trailing space!
|
|
HPASS=`openssl rand -base64 32`
|
|
/usr/sbin/useradd --shell /bin/false "$HAXHQ_RUNAS"
|
|
/usr/bin/echo "$HAXHQ_RUNAS:$HPASS" | /usr/sbin/chpasswd
|
|
/usr/sbin/usermod -L "$HAXHQ_RUNAS"
|
|
/usr/sbin/useradd -m --shell /bin/bash $OS_ADMIN_USER
|
|
/usr/bin/echo "$OS_ADMIN_USER:$OS_ADMIN_PASS" | /usr/sbin/chpasswd
|
|
/usr/sbin/usermod -a -G sudo "$OS_ADMIN_USER"
|
|
|
|
#XXX allow the haxhq user to reload nginx configuration.
|
|
# Required to enable config changes (below) and server/client certificate updates
|
|
echo "$HAXHQ_RUNAS ALL=(root) NOPASSWD: /usr/sbin/nginx -s reload" > /etc/sudoers.d/"$HAXHQ_RUNAS"
|
|
#XXX allow the haxhq user to switch between available nginx sites.
|
|
# Required to enable toggling of client certificate authentication from the web interface.
|
|
echo "$HAXHQ_RUNAS ALL=(root) NOPASSWD: /usr/bin/ln -s -f /etc/nginx/sites-available/haxhq /etc/nginx/sites-enabled/haxhq" >> /etc/sudoers.d/"$HAXHQ_RUNAS"
|
|
echo "$HAXHQ_RUNAS ALL=(root) NOPASSWD: /usr/bin/ln -s -f /etc/nginx/sites-available/haxhq-certauth /etc/nginx/sites-enabled/haxhq" >> /etc/sudoers.d/"$HAXHQ_RUNAS"
|
|
chmod 0440 /etc/sudoers.d/"$HAXHQ_RUNAS"
|
|
## setup CA
|
|
if git clone -b haxhq https://git.mitev.net/nik/easyrsa.git "$CADIR"; then
|
|
echo 'Repository cloned'
|
|
else
|
|
echo 'Failed to clone haxhq repository'
|
|
exit 1
|
|
fi
|
|
# setup HaxHQ
|
|
if git clone https://git.mitev.net/nik/"$REPO" "$INSTALLDIR"; then
|
|
echo 'Repository cloned'
|
|
else
|
|
echo 'Failed to clone haxhq repository'
|
|
exit 1
|
|
fi
|
|
cd "$INSTALLDIR"/haxhq
|
|
mkdir logs xml report_templates generated_reports qrcode
|
|
chmod 775 logs xml report_templates generated_reports haxhq qrcode
|
|
#/usr/sbin/usermod -a -G $OS_ADMIN_USER haxhq
|
|
cd "$INSTALLDIR"/
|
|
python3 -m venv venv
|
|
source venv/bin/activate
|
|
pip install -r requirements.txt
|
|
echo "import os
|
|
#DEBUG = True
|
|
SECRET_KEY = os.urandom(42)
|
|
WTF_CSRF_SECRET_KEY = '$CSRF_KEY'
|
|
#WTF_CSRF_TIME_LIMIT = None
|
|
SESSION_COOKIE_SECURE = True
|
|
SESSION_COOKIE_HTTPONLY = True
|
|
SESSION_COOKIE_SAMESITE='Strict'
|
|
SESSION_COOKIE_NAME = 'haxhq_session'
|
|
SESSION_TYPE = 'filesystem'
|
|
SESSION_PERMANENT = True
|
|
UPLOAD_FOLDER = '../xml'
|
|
REPORT_FOLDER = '../generated_reports'
|
|
PENTEST_TEMPLATE = 'pentest_report_template.docx'
|
|
AUDIT_TEMPLATE = 'audit_report_template.docx'
|
|
VULNSCAN_TEMPLATE = 'vulnscan_report_template.docx'
|
|
FAVICON_FOLDER = 'static/favicon'
|
|
QRCODE_FOLDER = '../qrcode/'
|
|
ALLOWED_EXTENSIONS = {'xml', 'nessus', 'html', 'txt'}
|
|
DB_NAME = '$DBNAME'
|
|
DB_USER = '$DBUSER'
|
|
DB_PASS = '$DBPASS'
|
|
CA_KEY = '$CA_KEY'
|
|
CADIR = '$CADIR'
|
|
SMTP_SERVER = 'smtp.haxhq.com'
|
|
SENDER_DOMAIN = '$DOMAIN'
|
|
# requires SSL connection.
|
|
# STARTTLS and plaintext are insecure but support can be added if security is provided in alternative ways
|
|
SMTP_PORT = '587'
|
|
#SMTP_USER = ''
|
|
#SMTP_PASS = ''
|
|
SHOWLOGS=True
|
|
ORG_NAME = '$BUSINESS_NAME'" > haxhq/haxhq/def_settings.py
|
|
sudo -u postgres psql -c "create role $DBUSER with password '$DBPASS' login;"
|
|
sudo -u postgres psql -c "create database $DBNAME with owner $DBUSER;"
|
|
sudo -u postgres psql -c "alter database $DBNAME set datestyle to 'ISO, DMY';"
|
|
cd "$INSTALLDIR"/haxhq/haxhq
|
|
if flask initdb; then
|
|
# ADD INITIAL USER
|
|
sudo -u postgres psql -d "$DBNAME" -c "insert into customers (contact_email, business_name, licenses) values ('$BUSINESS_NAME', '$BUSINESS_EMAIL', $LICENSES)"
|
|
sudo -u postgres psql -d "$DBNAME" -c "insert into users (nickname, email, user_type, user_group, customer_id, admin) values ('$HAXHQ_USER_NICKNAME', '$HAXHQ_USER_EMAIL', '$HAXHQ_USER_JOBTITLE', 'hackers', 1, true)"
|
|
else
|
|
echo "failed to initialise database"
|
|
exit 1
|
|
fi
|
|
if flask init_ca; then
|
|
echo 'Initialised integrated root CA'
|
|
else
|
|
echo "failed to initialise CA"
|
|
exit 1
|
|
fi
|
|
cp "$CADIR"/pki/ca.crt "$INSTALLDIR"/haxhq/haxhq/static/ca.crt
|
|
mv /etc/nginx/nginx.conf /etc/nginx/nginx.conf.orig
|
|
cp "$INSTALLDIR"/nginx.conf /etc/nginx/nginx.conf
|
|
echo "map \$http_upgrade \$connection_upgrade {
|
|
default upgrade;
|
|
'' close;
|
|
}
|
|
|
|
upstream haxhq {
|
|
server unix:$INSTALLDIR/haxhq/haxhq/app.sock;
|
|
}
|
|
|
|
server {
|
|
listen 443 ssl;
|
|
listen [::]:443 ssl;
|
|
server_name haxhq.$DOMAIN;
|
|
|
|
ssl_certificate $CADIR/pki/issued/haxhq.$DOMAIN.crt;
|
|
ssl_certificate_key $CADIR/pki/private/haxhq.$DOMAIN.key;
|
|
ssl_dhparam $CADIR/pki/dh.pem;
|
|
|
|
add_header X-Frame-Options SAMEORIGIN;
|
|
add_header X-Content-Type-Options nosniff;
|
|
add_header X-XSS-Protection \"1; mode=block\";
|
|
add_header Content-Security-Policy \"script-src 'self' object-src 'self' frame-ancestors 'none'\";
|
|
add_header Strict-Transport-Security \"max-age=31536000; includeSubdomains; preload\";" |tee /etc/nginx/sites-available/haxhq-certauth /etc/nginx/sites-available/haxhq > /dev/null
|
|
|
|
echo "
|
|
# client certificate
|
|
ssl_client_certificate $CADIR/pki/ca.crt;
|
|
# make verification optional, so we can display a 403 message to those
|
|
# who fail authentication
|
|
ssl_verify_client optional;
|
|
ssl_crl $CADIR/pki/crl.pem;
|
|
|
|
error_page 403 /client_certificate_required.html;
|
|
location = /client_certificate_required.html {
|
|
root /opt/haxhq.com/html;
|
|
internal;
|
|
}
|
|
|
|
location / {
|
|
# if the client-side certificate failed to authenticate, show a 403 message to the client
|
|
if (\$ssl_client_verify != SUCCESS) {
|
|
error_page 403 /static/client_certificate_required.html;
|
|
return 403;
|
|
}
|
|
|
|
include proxy_params;
|
|
proxy_pass http://haxhq;
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Upgrade \$http_upgrade;
|
|
proxy_set_header Connection \$connection_upgrade;
|
|
proxy_set_header X-SSL-Client-S-Dn \$ssl_client_s_dn;
|
|
proxy_set_header X-SSL-Client-Remain \$ssl_client_v_remain;
|
|
proxy_set_header X-SSL-Client-Fp \$ssl_client_fingerprint;
|
|
}
|
|
}" >> /etc/nginx/sites-available/haxhq-certauth
|
|
|
|
echo "
|
|
location / {
|
|
include proxy_params;
|
|
proxy_pass http://haxhq;
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Upgrade \$http_upgrade;
|
|
proxy_set_header Connection \$connection_upgrade;
|
|
}
|
|
}" >> /etc/nginx/sites-available/haxhq
|
|
|
|
ln -s /etc/nginx/sites-available/haxhq /etc/nginx/sites-enabled/haxhq
|
|
|
|
echo "$INSTALLDIR/haxhq/logs/*.log {
|
|
daily
|
|
missingok
|
|
rotate 7
|
|
compress
|
|
delaycompress
|
|
notifempty
|
|
su $HAXHQ_RUNAS $HAXHQ_RUNAS
|
|
create 0660 $HAXHQ_RUNAS $HAXHQ_RUNAS
|
|
postrotate
|
|
/bin/systemctl restart haxhq.service
|
|
endscript
|
|
}" > /etc/logrotate.d/haxhq.logrotate
|
|
|
|
echo "[Unit]
|
|
# specifies metadata and dependenciesDescription=Gunicorn instance to serve myproject
|
|
After=network.target
|
|
# tells the init system to only start this after the networking target has been reached# We will give our regular user account ownership of the process since it owns all of the relevant files
|
|
[Service]
|
|
# Service specify the user and group under which our process will run.
|
|
User=$HAXHQ_RUNAS
|
|
# give group ownership to the www-data group so that Nginx can communicate easily with the Gunicorn processes.
|
|
Group=$HAXHQ_RUNAS
|
|
# We'll then map out the working directory and set the PATH environmental variable so that the init system knows where our the executables for the process are located (within our virtual environment).
|
|
WorkingDirectory=$INSTALLDIR/haxhq/haxhq
|
|
Environment="PATH=$INSTALLDIR/venv/bin"
|
|
StandardError=append:$INSTALLDIR/haxhq/logs/haxhq.log
|
|
# We'll then specify the commanded to start the service
|
|
ExecStart=$INSTALLDIR/venv/bin/gunicorn --workers 3 --timeout 360 --bind unix:app.sock -m 011 wsgi:app
|
|
# This will tell systemd what to link this service to if we enable it to start at boot. We want this service to start when the regular multi-user system is up and running:
|
|
[Install]
|
|
WantedBy=multi-user.target" > /etc/systemd/system/haxhq.service
|
|
#chown -R $OS_ADMIN_USER:haxhq $INSTALLDIR/*
|
|
echo "#!/bin/bash
|
|
source $INSTALLDIR/venv/bin/activate
|
|
cd $INSTALLDIR/haxhq/haxhq
|
|
|
|
$INSTALLDIR/venv/bin/python haxhqcli.py \$@
|
|
|
|
if [ "$(id -u)" -eq "0" ]; then
|
|
/usr/bin/chown -R $HAXHQ_RUNAS:$HAXHQ_RUNAS $CADIR/pki
|
|
/usr/bin/chmod +rx $CADIR/pki
|
|
/usr/bin/chmod +r $CADIR/pki/ca.crt
|
|
fi
|
|
" > /usr/local/bin/haxhqcli
|
|
|
|
chmod 755 /usr/local/bin/haxhqcli
|
|
IP=`ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1'`
|
|
echo "
|
|
To finalise your setup:
|
|
1) update the operations user passwd - if you are logged in as operations just run 'passwd'
|
|
2) update the root password with e.g. 'sudo -u root passwd'
|
|
3) check network connectivity with 'haxhqcli check_connectivity'
|
|
4) check the system time using 'date'.
|
|
If it is not accurate, update it with 'sudo systemctl stop ntpd && sudo ntpd -gq && sudo systemctl start ntpd'
|
|
5) re-initialise the certificate authority so a new private key is generated for the root certificate: 'sudo -u haxhq haxhqcli init_ca'
|
|
6) download the generated root CA certificate from https://$IP/static/ca.crt and
|
|
install it in your browser as a trusted root CA. This will remove certificate warnings and help protect against MitM attacks.
|
|
7) set the password for the initial HaxHQ admin user: 'sudo -u haxhq haxhqcli update_pass $HAXHQ_USER_EMAIL'
|
|
8) login at https://$IP as $HAXHQ_USER_EMAIL with the password you just set
|
|
|
|
The above steps should only take a couple of minutes. Please do email support@haxhq.com if you need help at any stage, we will be happy to help.
|
|
|
|
Once you are logged in to the web interface, you can add further users as needed (user menu -> Administration)
|
|
|
|
While you are on the Administration page you may also want to download the default report template and apply your branding,
|
|
then upload it again. If you prefer, email support@haxhq.com with your current template and we will create a HaxHQ compatible version of it.
|
|
" > /home/$OS_ADMIN_USER/HaxHQ_readme.txt
|
|
|
|
echo "# m h dom mon dow command
|
|
0 5 01 * * haxhq /usr/local/bin/haxhqcli renew_server_cert" > /etc/cron.d/haxhq
|
|
|
|
chown -R "$HAXHQ_RUNAS":"$HAXHQ_RUNAS" "$INSTALLDIR" "$CADIR"
|
|
systemctl daemon-reload
|
|
systemctl enable haxhq
|
|
systemctl start haxhq
|
|
systemctl restart nginx
|
|
systemctl stop ntpd
|
|
/usr/sbin/ntpd -gq
|
|
systemctl start ntpd
|
|
|
|
echo "admin user: $OS_ADMIN_USER"
|
|
echo "admin pass: $OS_ADMIN_PASS"
|