diff --git a/.travis.yml b/.travis.yml index 0a8e73f..27b7762 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,4 +13,3 @@ before_install: script: - docker-compose build - - docker-compose -f docker-compose-nginx.yml build diff --git a/README.md b/README.md index 7a4b0fe..e146816 100644 --- a/README.md +++ b/README.md @@ -7,24 +7,20 @@ The files in this repository are used to create a Docker container running a [MI I rewrote the Docker file to split the components in multiple containers (which is more in the philosophy of Docker). Therefore there is no longer a Dockerfile in the root directory. -The MISP container needs at least a MySQL container to store the data. By default it listen to port 80. I highly recommend to serve it behind a NGinx or Apache reverse proxy. +The MISP container needs at least a MySQL container to store the data. By default it listen to port 443 and port 80, which is redirected to 443. -The build is based on Ubuntu and will install all the required components. The following configuration steps are performed automatically: +The build is based on Ubuntu and will install all the required components, using the INSTALL script provided in the MISP repository. + +Using the Install script has the advantage that we can rely on a tested installation routine which is maintained and kept up to date. The amount of custom work to be done in the Dockerfile and run.sh files is limited to the necessary to make MISP container compliant. + +The following configuration steps are performed automatically: * Reconfiguration of the base URL in `config.php` * Generation of a new salt in `config.php` * Generation of a self-signed certificate * Optimization of the PHP environment (php.ini) to match the MISP recommended values * Creation of the MySQL database * Generation of the admin PGP key - -## Config -* add your "*.crt" and "*.key" files to the ./proxy/ssl folder -If not implementing SSL (not recommended) then simply comment out the appropriate lines in the "./proxy/default.conf" file. -* Update "server_name" in default.conf file (will implement ENVIRONMENT VARIABLE in the future) - -# Optional NGINX config - -Included is an optional Docker Compose file 'docker-compose-nginx.yml' to spin up a reverse proxy to sit in front of MISP. +* Installation of misp modules # Building your image @@ -41,27 +37,12 @@ $ vi .env ``` $ docker-compose build or -$ docker-compose -f docker-compose-nginx.yml build +$ docker-compose -f docker-compose.yml build ``` ## Run containers ``` $ docker-compose up or -$ docker-compose -f docker-compose-nginx.yml up +$ docker-compose -f docker-compose.yml up ``` - -# Optional NGINX config - SSL certificates - -You can create the certificates manually if they are not automatically created. - -``` -openssl req -new -nodes -x509 -subj "/C=BE/ST=Brussels/L=Brussels/O=CTI/CN=localhost" -days 3650 -newkey rsa:4096 -keyout proxy/ssl/misp.key -out proxy/ssl/misp.crt -``` - -Then rebuild the proxy container and restart al the containers. - -``` -docker-compose -f docker-compose-nginx.yml build --no-cache proxy -docker-compose -f docker-compose-nginx.yml up -``` \ No newline at end of file diff --git a/docker-compose-nginx.yml b/docker-compose-nginx.yml deleted file mode 100644 index c5fcfc9..0000000 --- a/docker-compose-nginx.yml +++ /dev/null @@ -1,44 +0,0 @@ -version: '2' - -services: - proxy: - build: - context: proxy - container_name: misp_proxy - restart: unless-stopped - image: misp-proxy:latest - ports: - - 80:80 - - 443:443 - - web: - build: web - container_name: misp_web - image: misp:latest - restart: unless-stopped - volumes: - - /dev/urandom:/dev/random - - ${DATA_DIR}/web:/var/www/MISP - environment: - - MYSQL_HOST=${MYSQL_HOST} - - MYSQL_DATABASE=${MYSQL_DATABASE} - - MYSQL_USER=${MYSQL_USER} - - MYSQL_PASSWORD=${MYSQL_PASSWORD} - - MISP_ADMIN_EMAIL=${MISP_ADMIN_EMAIL} - - MISP_ADMIN_PASSPHRASE=${MISP_ADMIN_PASSPHRASE} - - MISP_BASEURL=${MISP_BASEURL} - - POSTFIX_RELAY_HOST=${POSTFIX_RELAY_HOST} - - TIMEZONE=${TIMEZONE} - - db: - container_name: misp_db - image: mysql/mysql-server:5.7 - restart: unless-stopped - volumes: - - ${DATA_DIR}/db:/var/lib/mysql - environment: - - MYSQL_DATABASE=${MYSQL_DATABASE} - - MYSQL_USER=${MYSQL_USER} - - MYSQL_PASSWORD=${MYSQL_PASSWORD} - - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} - diff --git a/docker-compose.yml b/docker-compose.yml index 05ce870..2d87ef2 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,4 +1,4 @@ -version: '2' +version: '3' services: web: @@ -10,6 +10,7 @@ services: restart: unless-stopped ports: - "80:80" + - "443:443" volumes: - /dev/urandom:/dev/random - ${DATA_DIR}/web:/var/www/MISP diff --git a/proxy/Dockerfile b/proxy/Dockerfile deleted file mode 100644 index 60aad83..0000000 --- a/proxy/Dockerfile +++ /dev/null @@ -1,10 +0,0 @@ -FROM nginx:1.18 - -# default conf for proxy service -COPY ./default.conf /etc/nginx/conf.d/default.conf - -# Proxy and SSL configurations -COPY ./includes/ /etc/nginx/includes/ - -# Proxy SSL certificates -COPY ./ssl/ /etc/ssl/certs/nginx/ diff --git a/proxy/default.conf b/proxy/default.conf deleted file mode 100644 index 8a0f3f8..0000000 --- a/proxy/default.conf +++ /dev/null @@ -1,26 +0,0 @@ -# plain http redirect to https -server { - listen 80; - listen [::]:80; - server_name localhost; - return 301 https://$server_name$request_uri; -} -# main server, reverse proxy to 'web' container -server { - listen 443 ssl http2 default_server; - listen [::]:443 ssl http2 default_server; - server_name localhost; - - # Path for SSL config/key/certificate - ssl_certificate /etc/ssl/certs/nginx/misp.crt; - ssl_certificate_key /etc/ssl/certs/nginx/misp.key; - include /etc/nginx/includes/ssl.conf; - - location / { - include /etc/nginx/includes/proxy.conf; - proxy_pass http://web; - } - - access_log off; - error_log /var/log/nginx/error.log error; -} diff --git a/proxy/includes/proxy.conf b/proxy/includes/proxy.conf deleted file mode 100644 index 716d590..0000000 --- a/proxy/includes/proxy.conf +++ /dev/null @@ -1,8 +0,0 @@ -proxy_set_header Host $host; -proxy_set_header X-Real-IP $remote_addr; -proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; -proxy_set_header X-Forwarded-Proto $scheme; -proxy_buffering off; -proxy_request_buffering off; -proxy_http_version 1.1; -proxy_intercept_errors on; diff --git a/proxy/includes/ssl.conf b/proxy/includes/ssl.conf deleted file mode 100644 index 6501d91..0000000 --- a/proxy/includes/ssl.conf +++ /dev/null @@ -1,7 +0,0 @@ -ssl_session_timeout 1d; -ssl_session_cache shared:SSL:50m; -ssl_session_tickets off; - -ssl_protocols TLSv1 TLSv1.1 TLSv1.2; -ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHAECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS'; -ssl_prefer_server_ciphers on; diff --git a/proxy/ssl/place_certs_here b/proxy/ssl/place_certs_here deleted file mode 100644 index e69de29..0000000 diff --git a/template.env b/template.env index 96e8ec8..e1af9d4 100644 --- a/template.env +++ b/template.env @@ -1,4 +1,4 @@ -MYSQL_HOST=db +MYSQL_HOST=misp-db MYSQL_DATABASE=misp MYSQL_USER=misp MYSQL_PASSWORD=misp diff --git a/web/Dockerfile b/web/Dockerfile index c5bafae..fe7afa4 100644 --- a/web/Dockerfile +++ b/web/Dockerfile @@ -1,152 +1,40 @@ -FROM ubuntu:focal +FROM ubuntu:latest # Install core components ENV DEBIAN_FRONTEND noninteractive RUN apt-get update && \ - apt-get dist-upgrade -y && apt-get autoremove -y && apt-get clean && \ + apt-get dist-upgrade -y && apt-get upgrade && apt-get autoremove -y && apt-get clean && \ apt-get install -y software-properties-common && \ apt-get install -y postfix && \ apt-get install -y mysql-client curl gcc git gnupg-agent \ - make python openssl redis-server sudo vim zip locales + make openssl redis-server sudo vim zip locales wget iproute2 supervisor cron + +RUN add-apt-repository ppa:deadsnakes/ppa +RUN apt-get update && apt-get -y install python3.9 python3-pip +RUN pip3 install --upgrade pip + RUN locale-gen en_US.UTF-8 ENV LANG en_US.UTF-8 -# Apache -RUN apt-get install -y apache2 apache2-doc apache2-utils && \ - a2dismod status && \ - a2dissite 000-default +RUN useradd misp && usermod -aG sudo misp + +# Install script +COPY INSTALL_NODB.sh . +RUN chmod +x INSTALL_NODB.sh +RUN echo "ALL ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers -# PHP 7.4 and install MySQL PDO extension -RUN apt-get update -RUN apt-get install -y --fix-missing libapache2-mod-php php php-dev php-json \ - php-mysql php-redis php-xml php-mbstring \ - php-gd php-pear php-opcache \ - pkg-config libbson-1.0 libmongoc-1.0-0 \ - php-zip php-bcmath php-intl -# Fix php.ini with recommended settings -RUN sed -i \ - -e "s/max_execution_time = 30/max_execution_time = 300/" \ - -e "s/memory_limit = 128M/memory_limit = 2048M/" \ - -e "s/upload_max_filesize = 2M/upload_max_filesize = 50M/" \ - -e "s/post_max_size = 8M/post_max_size = 50M/" \ - /etc/php/7.4/apache2/php.ini +USER misp -RUN apt-get install -y python3-dev python3-pip python3-setuptools \ - python3-lxml libjpeg-dev \ - libxml2-dev libxslt1-dev zlib1g-dev libfuzzy-dev && \ - apt-get install -y cron logrotate supervisor syslog-ng-core && \ - apt-get clean - -WORKDIR /var/www -RUN chown www-data:www-data /var/www -USER www-data -RUN git clone https://github.com/MISP/MISP.git -WORKDIR /var/www/MISP -RUN git checkout tags/$(git describe --tags `git rev-list --tags --max-count=1`) && \ - git config core.filemode false && \ - git submodule update --init --recursive && \ - git submodule foreach --recursive git config core.filemode false +RUN bash INSTALL_NODB.sh -A -u USER root -RUN pip3 install git+https://github.com/STIXProject/python-stix.git \ - git+https://github.com/CybOXProject/python-cybox.git \ - git+https://github.com/CybOXProject/mixbox.git \ - git+https://github.com/MAECProject/python-maec.git \ - /var/www/MISP/cti-python-stix2 \ - plyara -USER www-data -WORKDIR /var/www/MISP -RUN git submodule init && git submodule update -WORKDIR /var/www/MISP/app +RUN pip3 list -o | cut -f1 -d' ' | tr " " "\n" | awk '{if(NR>=3)print}' | cut -d' ' -f1 | xargs -n1 pip3 install -U ; exit 0 #Hack error code -# FIX COMPOSER -RUN curl --fail --location -o composer-setup.php https://getcomposer.org/installer && \ - EXPECTED_SIGNATURE="$(curl https://composer.github.io/installer.sig)"; php -r "if (hash_file('sha384', 'composer-setup.php') == '$(echo $EXPECTED_SIGNATURE)' ) { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" && \ - php composer-setup.php && \ - php -r "unlink('composer-setup.php');" -# END FIX - -RUN php composer.phar update && \ - php composer.phar config vendor-dir Vendor && \ - php composer.phar install --ignore-platform-reqs -USER root -RUN phpenmod redis -USER www-data -RUN cp -fa /var/www/MISP/INSTALL/setup/config.php /var/www/MISP/app/Plugin/CakeResque/Config/config.php - -# Fix permissions -USER root -RUN chown -R www-data:www-data /var/www/MISP && \ - chmod -R 750 /var/www/MISP && \ - chmod -R g+ws /var/www/MISP/app/tmp && \ - chmod -R g+ws /var/www/MISP/app/files && \ - chmod -R g+ws /var/www/MISP/app/files/scripts/tmp && \ - chmod +x /var/www/MISP/app/Console/cake - -RUN cp /var/www/MISP/INSTALL/misp.logrotate /etc/logrotate.d/misp - -# Preconfigure setting for packages -RUN echo "postfix postfix/main_mailer_type string Local only" \ - | debconf-set-selections && \ - echo "postfix postfix/mailname string localhost.localdomain" | \ - debconf-set-selections - -# Redis Setup -RUN sed -i 's/^\(daemonize\s*\)yes\s*$/\1no/g' /etc/redis/redis.conf -RUN sed -i 's/^\(bind\s*\)127.0.0.1 ::1\s*$/\1127.0.0.1/g' /etc/redis/redis.conf - -# Add a healthcheck endpoint -COPY healthcheck.patch healthcheck.patch -RUN patch /var/www/MISP/INSTALL/apache.misp.ubuntu < healthcheck.patch - -# Apache Setup -RUN cp /var/www/MISP/INSTALL/apache.misp.ubuntu /etc/apache2/sites-available/misp.conf && \ - a2dissite 000-default && \ - a2ensite misp && \ - a2enmod rewrite && \ - a2enmod headers - -# MISP base configuration -RUN sudo -u www-data cp -a /var/www/MISP/app/Config/bootstrap.default.php /var/www/MISP/app/Config/bootstrap.php && \ - sudo -u www-data cp -a /var/www/MISP/app/Config/database.default.php /var/www/MISP/app/Config/database.php && \ - sudo -u www-data cp -a /var/www/MISP/app/Config/core.default.php /var/www/MISP/app/Config/core.php && \ - sudo -u www-data cp -a /var/www/MISP/app/Config/config.default.php /var/www/MISP/app/Config/config.php && \ - chown -R www-data:www-data /var/www/MISP/app/Config && \ - chmod -R 750 /var/www/MISP/app/Config - -# Replace the default salt -RUN sed -i -E "s/'salt'\s=>\s'(\S+)'/'salt' => '`openssl rand -base64 32|tr "/" "-"`'/" /var/www/MISP/app/Config/config.php - -# Enable workers at boot time -RUN chmod a+x /var/www/MISP/app/Console/worker/start.sh && \ - echo "sudo -u www-data bash /var/www/MISP/app/Console/worker/start.sh" >>/etc/rc.local - -# Install templates & stuff -WORKDIR /var/www/MISP/app/files -RUN rm -rf misp-objects && git clone https://github.com/MISP/misp-objects.git && \ - rm -rf misp-galaxy && git clone https://github.com/MISP/misp-galaxy.git && \ - rm -rf warninglists && git clone https://github.com/MISP/misp-warninglists.git ./warninglists && \ - rm -rf taxonomies && git clone https://github.com/MISP/misp-taxonomies.git ./taxonomies && \ - chown -R www-data:www-data misp-objects misp-galaxy warninglists taxonomies - -# Install MISP build requirements -RUN sudo -E apt-get -y install libpoppler97 libpoppler-dev libpoppler-cpp-dev - -# Install MISP Modules -WORKDIR /opt -RUN git clone --branch v2.4.134 https://github.com/MISP/misp-modules.git -RUN cd misp-modules && \ - pip3 install --upgrade pip setuptools wheel && \ - pip3 install scikit-build && \ - pip3 install opencv-python && \ - pip3 install -I -r REQUIREMENTS && \ - pip3 install -I . && \ - echo "sudo -u www-data misp-modules -s -l 127.0.0.1 &" >>/etc/rc.local # Supervisord Setup RUN ( \ @@ -173,20 +61,18 @@ RUN ( \ echo 'autorestart = false'; \ echo ''; \ echo '[program:misp-modules]'; \ - echo 'command=/bin/bash -c "misp-modules -s -l 127.0.0.1"'; \ + echo 'command=/bin/bash -c "/var/www/MISP/venv/bin/misp-modules -l 127.0.0.1 -s"'; \ echo 'user = www-data'; \ echo 'startsecs = 0'; \ echo 'autorestart = false'; \ ) >> /etc/supervisor/conf.d/supervisord.conf - -# Modify syslog configuration -RUN sed -i -E 's/^(\s*)system\(\);/\1unix-stream("\/dev\/log");/' /etc/syslog-ng/syslog-ng.conf # Add run script # Trigger to perform first boot operations ADD run.sh /run.sh +RUN mv /etc/apache2/sites-available/misp-ssl.conf /etc/apache2/sites-available/misp-ssl.conf.bak +ADD misp-ssl.conf /etc/apache2/sites-available/misp-ssl.conf RUN chmod 0755 /run.sh && touch /.firstboot.tmp - # Make a backup of /var/www/MISP to restore it to the local moint point at first boot WORKDIR /var/www/MISP RUN tar czpf /root/MISP.tgz . diff --git a/web/INSTALL_NODB.sh b/web/INSTALL_NODB.sh new file mode 100755 index 0000000..3a65211 --- /dev/null +++ b/web/INSTALL_NODB.sh @@ -0,0 +1,3243 @@ +#!/usr/bin/env bash +############################################################ +###### # +##### Please AutoGenerated... ## +#### Do NOT was ### +### Manually It #### +## Change this Script... ##### +# ###### +############################################################ +############################################################ +#INSTALLATION INSTRUCTIONS # +########################################################## +#------------------------- for Debian Flavored Linux Distributions +# +#-------------------------------------------------------| +# 0/ Quick MISP Instance on Debian Based Linux - Status | +#-------------------------------------------------------| +# +# 20200513: Ubuntu 20.04 tested and working. -- sCl +# 20200412: Ubuntu 18.04.4 tested and working. -- sCl +# 20190302: Ubuntu 18.04.2 tested and working. -- sCl +# 20190208: Kali Linux tested and working. -- sCl +# +# +#-------------------------------------------------------------------------------------------------| +# 1/ For other Debian based Linux distributions, download script and run as **unprivileged** user | +#-------------------------------------------------------------------------------------------------| +# +# The following installs only MISP Core: +# $ wget --no-cache -O /tmp/INSTALL.sh https://raw.githubusercontent.com/MISP/MISP/2.4/INSTALL/INSTALL.sh ; bash /tmp/INSTALL.sh -c +# +# This will install MISP Core and misp-modules +# $ wget --no-cache -O /tmp/INSTALL.sh https://raw.githubusercontent.com/MISP/MISP/2.4/INSTALL/INSTALL.sh ; bash /tmp/INSTALL.sh -c -M +# +# +#-------------------------------------------------------| +# 2/ For Kali, download and run Installer Script | +#-------------------------------------------------------| +# +# To install MISP on Kali copy paste the following to your shell: +# # wget --no-cache -O /tmp/misp-kali.sh https://raw.githubusercontent.com/MISP/MISP/2.4/INSTALL/INSTALL.sh && bash /tmp/misp-kali.sh +# NO other version then 2020.x supported, kthxbai. +# /!\ Please read the installer script before randomly doing the above. +# The script is tested on a plain vanilla Kali Linux Boot CD and installs quite a few dependencies. +# +# +#----------------------------------------------------------| +# 3/ The following script has been partially autogenerated | +#----------------------------------------------------------| +# +# To generate this script yourself, the following steps need to be taken. +# $ git clone https://github.com/SteveClement/xsnippet.git +# Make sure xsnippet resides somewhere in your $PATH - It is a shell script so a simple, copy to somewhere sane is enough. +# $ git clone https://github.com/MISP/MISP.git +# $ cd MISP/INSTALL ; ./INSTALL.tpl.sh +# +## +### +####----------------\ +## Developer Note | +####--------------------------------------------------------------------------------------------------| +## In theory the order does not matter as everything is a self-contained function. | +# That said, ideally leave the order as is and do NOT change the lines as they are place-holders. | +# Script files that do NOT have a #_name.sh are scripts that have NO functions. This is by design. | +#-----------------------------------------------------------------------------------------------------| +# +# ToC # +# +#### BEGIN AUTOMATED SECTION #### +# +# $ eval "$(curl -fsSL https://raw.githubusercontent.com/MISP/MISP/2.4/docs/generic/globalVariables.md | grep -v \`\`\`)" +# $ MISPvars +MISPvars () { + debug "Setting generic ${LBLUE}MISP${NC} variables shared by all flavours" 2> /dev/null + # Local non-root MISP user + MISP_USER="${MISP_USER:-misp}" + MISP_PASSWORD="${MISP_PASSWORD:-$(openssl rand -hex 32)}" + + # The web server user + # RHEL/CentOS + if [[ -f "/etc/redhat-release" ]]; then + WWW_USER="apache" + SUDO_WWW="sudo -H -u ${WWW_USER} " + # Debian flavoured + elif [[ -f "/etc/debian_version" ]]; then + WWW_USER="www-data" + SUDO_WWW="sudo -H -u ${WWW_USER} " + # OpenBSD + elif [[ "$(uname -s)" == "OpenBSD" ]]; then + WWW_USER="www" + PATH_TO_MISP="${PATH_TO_MISP:-/var/www/htdocs/MISP}" + SUDO_WWW="doas -u www " + SUDO_CMD="doas " + # NetBSD + elif [[ "$(uname -s)" == "NetBSD" ]]; then + WWW_USER="www" + PATH_TO_MISP="$PATH_TO_MISP:-/usr/pkg/share/httpd/htdocs/MISP}" + SUDO_WWW="sudo -H -u ${WWW_USER} " + else + # I am feeling lucky + WWW_USER="www-data" + SUDO_WWW="sudo -H -u ${WWW_USER} " + fi + + # MISP configuration variables + PATH_TO_MISP="${PATH_TO_MISP:-/var/www/MISP}" + PATH_TO_MISP_SCRIPTS="${PATH_TO_MISP}/app/files/scripts" + + + FQDN="${FQDN:-misp.local}" + + MISP_BASEURL="${MISP_BASEURL:-""}" + + MISP_LIVE="1" + + # Database configuration + DBHOST="${DBHOST:-localhost}" + DBNAME="${DBNAME:-misp}" + DBUSER_ADMIN="${DBUSER_ADMIN:-root}" + DBPASSWORD_ADMIN="${DBPASSWORD_ADMIN:-$(openssl rand -hex 32)}" + DBUSER_MISP="${DBUSER_MISP:-misp}" + DBPASSWORD_MISP="${DBPASSWORD_MISP:-$(openssl rand -hex 32)}" + + # OpenSSL configuration + OPENSSL_CN=${FQDN} + OPENSSL_C="LU" + OPENSSL_ST="State" + OPENSSL_L="Location" + OPENSSL_O="Organization" + OPENSSL_OU="Organizational Unit" + OPENSSL_EMAILADDRESS="info@${FQDN}" + + # GPG configuration + GPG_REAL_NAME="Autogenerated Key" + # On a REAL install, please do not set a comment, see here for why: https://www.debian-administration.org/users/dkg/weblog/97 + GPG_COMMENT="WARNING: MISP AutoGenerated Key consider this Key VOID!" + GPG_EMAIL_ADDRESS="admin@admin.test" + # 3072 bits used as per suggestions here: https://riseup.net/en/security/message-security/openpgp/best-practices + GPG_KEY_LENGTH="3072" + GPG_PASSPHRASE="$(openssl rand -hex 32)" + + # debug alias to make sure people are not confused when blindly copy pasting blobs of code + alias debug="echo -e" + + # checkAptLock alias to make sure people are not confused when blindly copy pasting blobs of code + alias checkAptLock="echo 'Function used in Installer to make sure apt is not locked'" + + # php.ini configuration + upload_max_filesize="50M" + post_max_size="50M" + max_execution_time="300" + memory_limit="2048M" + + CAKE="${PATH_TO_MISP}/app/Console/cake" + + # sudo config to run $LUSER commands + if [[ "$(groups ${MISP_USER} |grep -o 'staff')" == "staff" ]]; then + SUDO_CMD="sudo -H -u ${MISP_USER} -g staff" + else + SUDO_CMD="sudo -H -u ${MISP_USER}" + fi + + echo "The following DB Passwords were generated..." + echo "Admin (${DBUSER_ADMIN}) DB Password: ${DBPASSWORD_ADMIN}" + echo "User (${DBUSER_MISP}) DB Password: ${DBPASSWORD_MISP}" +} + +# Leave empty for NO debug messages, if run with set -x or bash -x it will enable DEBUG by default +DEBUG= + +case "$-" in + *x*) NO_PROGRESS=1; DEBUG=1 ;; + *) NO_PROGRESS=0 ;; +esac + +## Function Section ## + +## Usage of this script +usage () { + if [ "$0" == "bash" ]; then + WEB_INSTALL=1 + SCRIPT_NAME="Web Installer Command" + else + SCRIPT_NAME=$0 + fi + + space + echo -e "Please specify what type of ${LBLUE}MISP${NC} setup you want to install." + space + echo -e "${SCRIPT_NAME} -c | Install ONLY ${LBLUE}MISP${NC} Core" # core + echo -e " -M | ${LBLUE}MISP${NC} modules" # modules + ## FIXME: The current state of misp-dashboard is broken, disabling any use. + ##echo -e " -D | ${LBLUE}MISP${NC} dashboard" # dashboard + ## FIXME: The current state of Viper is broken, disabling any use. + ##echo -e " -V | Viper" # viper + echo -e " -m | Mail 2 ${LBLUE}MISP${NC}" # mail2 + echo -e " -S | Experimental ssdeep correlations" # ssdeep + echo -e " -A | Install ${YELLOW}all${NC} of the above" # all + space + echo -e " -C | Only do ${YELLOW}pre-install checks and exit${NC}" # pre + space + echo -e " -u | Do an unattended Install, no questions asked" # UNATTENDED + echo -e "${HIDDEN} -U | Attempt and upgrade of selected item${NC}" # UPGRADE + echo -e "${HIDDEN} -N | Nuke this MISP Instance${NC}" # NUKE + echo -e "${HIDDEN} -f | Force test install on current Ubuntu LTS schim, add -B for 18.04 -> 18.10, or -BB 18.10 -> 19.10)${NC}" # FORCE + echo -e "Options can be combined: ${SCRIPT_NAME} -c -D # Will install Core+Dashboard" + space + echo -e "Recommended is either a barebone MISP install (ideal for syncing from other instances) or" + echo -e "MISP + modules - ${SCRIPT_NAME} -c -M" + echo -e "" + echo -e "" + echo -e "Interesting environment variables that get considered are:" + echo -e "" + echo -e "MISP_USER/MISP_PASSWORD # Local username on machine, default: misp/opensslGeneratedPassword" + echo -e "" + echo -e "PATH_TO_MISP # Where MISP will be installed, default: /var/www/MISP (recommended)" + echo -e "" + echo -e "DBHOST/DBNAME # database hostname, MISP database name, default: localhost/misp" + echo -e "DBUSER_ADMIN/DBPASSWORD_ADMIN # MySQL admin user, default: root/opensslGeneratedPassword" + echo -e "DBUSER_MISP/DBPASSWORD_MISP # MISP database user, default: misp/opensslGeneratedPassword" + echo -e "" + echo -e "You need to export the variable(s) to be taken into account. (or specified in-line when invoking INSTALL.sh)" + space +} + +# Check if element is contained in array +containsElement () { + local e match="$1" + shift + for e; do [[ "$e" == "$match" ]] && return 0; done + return 1 +} + +checkOpt () { + # checkOpt feature + containsElement $1 "${options[@]}" +} + +setOpt () { + options=() + for o in $@; do + case "$o" in + ("-c") echo "core"; CORE=1 ;; + ("-V") echo "viper"; VIPER=1 ;; + ("-M") echo "modules"; MODULES=1 ;; + ("-D") echo "dashboard"; DASHBOARD=1 ;; + ("-m") echo "mail2"; MAIL2=1 ;; + ("-S") echo "ssdeep"; SSDEEP=1 ;; + ("-A") echo "all"; ALL=1 ;; + ("-C") echo "pre"; PRE=1 ;; + ("-U") echo "upgrade"; UPGRADE=1 ;; + ("-N") echo "nuke"; NUKE=1 ;; + ("-u") echo "unattended"; UNATTENDED=1 ;; + ("-ni") echo "noninteractive"; NONINTERACTIVE=1 ;; + ("-f") echo "force"; FORCE=1 ;; + (*) echo "$o is not a valid argument"; exit 1 ;; + esac + done +} + +# check if command_exists +command_exists () { + command -v "$@" > /dev/null 2>&1 +} + +# TODO: fix os detection mess +# Try to detect what we are running on +checkCoreOS () { + # lsb_release can exist on any platform. RedHat package: redhat-lsb + LSB_RELEASE=$(which lsb_release > /dev/null ; echo $?) + APT=$(which apt > /dev/null 2>&1; echo -n $?) + APT_GET=$(which apt-get > /dev/null 2>&1; echo $?) + + # debian specific + # /etc/debian_version + ## os-release #generic + # /etc/os-release + + # Redhat checks + if [[ -f "/etc/redhat-release" ]]; then + echo "This is some redhat flavour" + REDHAT=1 + RHfla=$(cat /etc/redhat-release | cut -f 1 -d\ | tr '[:upper:]' '[:lower:]') + fi +} + +# Extract debian flavour +checkFlavour () { + FLAVOUR="" + # Every system that we officially support has /etc/os-release + if [ -r /etc/os-release ]; then + FLAVOUR="$(. /etc/os-release && echo "$ID"| tr '[:upper:]' '[:lower:]')" + fi + + case "${FLAVOUR}" in + ubuntu) + if command_exists lsb_release; then + dist_version="$(lsb_release --codename | cut -f2)" + fi + if [ -z "$dist_version" ] && [ -r /etc/lsb-release ]; then + dist_version="$(. /etc/lsb-release && echo "$DISTRIB_CODENAME")" + fi + ;; + debian|raspbian) + dist_version="$(sed 's/\/.*//' /etc/debian_version | sed 's/\..*//')" + case "$dist_version" in + 10) + dist_version="buster" + ;; + 9) + dist_version="stretch" + ;; + esac + ;; + centos) + if [ -z "$dist_version" ] && [ -r /etc/os-release ]; then + dist_version="$(. /etc/os-release && echo "$VERSION_ID")" + dist_version=${dist_version:0:1} + fi + echo "${FLAVOUR} support is experimental at the moment" + ;; + rhel|ol|sles) + if [ -z "$dist_version" ] && [ -r /etc/os-release ]; then + dist_version="$(. /etc/os-release && echo "$VERSION_ID")" + dist_version=${dist_version:0:1} # Only interested about major version + fi + # Only tested for RHEL 7 so far + echo "${FLAVOUR} support is experimental at the moment" + ;; + *) + if command_exists lsb_release; then + dist_version="$(lsb_release --release | cut -f2)" + fi + if [ -z "$dist_version" ] && [ -r /etc/os-release ]; then + dist_version="$(. /etc/os-release && echo "$VERSION_ID")" + fi + ;; + esac + + # FIXME: The below want to be refactored + if [ "${FLAVOUR}" == "ubuntu" ]; then + RELEASE=$(lsb_release -s -r) + debug "We detected the following Linux flavour: ${YELLOW}$(tr '[:lower:]' '[:upper:]' <<< ${FLAVOUR:0:1})${FLAVOUR:1} ${RELEASE}${NC}" + else + debug "We detected the following Linux flavour: ${YELLOW}$(tr '[:lower:]' '[:upper:]' <<< ${FLAVOUR:0:1})${FLAVOUR:1}${NC}" + fi +} + + +# Check if this is a forked Linux distro +check_forked () { + # Check for lsb_release command existence, it usually exists in forked distros + if command_exists lsb_release; then + # Check if the `-u` option is supported + set +e + lsb_release -a -u > /dev/null 2>&1 + lsb_release_exit_code=$? + set -e + + # Check if the command has exited successfully, it means we're in a forked distro + if [ "$lsb_release_exit_code" = "0" ]; then + # Print info about current distro + cat <<-EOF + You're using '${FLAVOUR}' version '${dist_version}'. +EOF + # Get the upstream release info + FLAVOUR=$(lsb_release -a -u 2>&1 | tr '[:upper:]' '[:lower:]' | grep -E 'id' | cut -d ':' -f 2 | tr -d '[:space:]') + dist_version=$(lsb_release -a -u 2>&1 | tr '[:upper:]' '[:lower:]' | grep -E 'codename' | cut -d ':' -f 2 | tr -d '[:space:]') + + # Print info about upstream distro + cat <<-EOF + Upstream release is '${FLAVOUR}' version '$dist_version'. +EOF + else + if [[ -r /etc/debian_version ]] && [[ "${FLAVOUR}" != "ubuntu" ]] && [[ "${FLAVOUR}" != "raspbian" ]]; then + # We're Debian and don't even know it! + FLAVOUR=debian + dist_version="$(sed 's/\/.*//' /etc/debian_version | sed 's/\..*//')" + case "$dist_version" in + 10) + dist_version="buster" + ;; + 9) + dist_version="stretch" + ;; + 8|'Kali Linux 2') + dist_version="jessie" + ;; + esac + fi + fi + fi +} + +checkInstaller () { + # Workaround: shasum is not available on RHEL, only checking sha512 + if [[ "${FLAVOUR}" == "rhel" ]] || [[ "${FLAVOUR}" == "centos" ]]; then + INSTsum=$(sha512sum ${0} | cut -f1 -d\ ) + /usr/bin/wget --no-cache -q -O /tmp/INSTALL.sh.sha512 https://raw.githubusercontent.com/stevengoossensB/misp-docker/master/web/INSTALL_NODB.sh.sha512 + chsum=$(cat /tmp/INSTALL.sh.sha512) + if [[ "${chsum}" == "${INSTsum}" ]]; then + echo "SHA512 matches" + else + echo "SHA512: ${chsum} does not match the installer sum of: ${INSTsum}" + # exit 1 # uncomment when/if PR is merged + fi + else + # TODO: Implement $FLAVOUR checks and install depending on the platform we are on + if [[ $(which shasum > /dev/null 2>&1 ; echo $?) -ne 0 ]]; then + checkAptLock + sudo apt install libdigest-sha-perl -qyy + fi + # SHAsums to be computed, not the -- notatiation is for ease of use with rhash + SHA_SUMS="--sha1 --sha256 --sha384 --sha512" + for sum in $(echo ${SHA_SUMS} |sed 's/--sha//g'); do + /usr/bin/wget --no-cache -q -O /tmp/INSTALL.sh.sha${sum} https://raw.githubusercontent.com/stevengoossensB/misp-docker/master/web/INSTALL_NODB.sh.sha${sum} + INSTsum=$(shasum -a ${sum} ${0} | cut -f1 -d\ ) + chsum=$(cat /tmp/INSTALL.sh.sha${sum} | cut -f1 -d\ ) + + if [[ "${chsum}" == "${INSTsum}" ]]; then + echo "sha${sum} matches" + else + echo "sha${sum}: ${chsum} does not match the installer sum of: ${INSTsum}" + echo "Delete installer, re-download and please run again." + exit 1 + fi + done + fi +} + +# Extract manufacturer +checkManufacturer () { + if [[ -z $(which dmidecode) ]]; then + checkAptLock + sudo apt install dmidecode -qy + fi + MANUFACTURER=$(sudo dmidecode -s system-manufacturer) + debug ${MANUFACTURER} +} + +# Dynamic horizontal spacer if needed, for autonomeous an no progress bar install, we are static. +space () { + if [[ "$NO_PROGRESS" == "1" ]] || [[ "$PACKER" == "1" ]]; then + echo "--------------------------------------------------------------------------------" + return + fi + # Check terminal width + num=`tput cols` + for i in `seq 1 $num`; do + echo -n "-" + done + echo "" +} + +# Spinner so the user knows something is happening +spin() +{ + if [[ "$NO_PROGRESS" == "1" ]]; then + return + fi + spinner="/|\\-/|\\-" + while : + do + for i in `seq 0 7` + do + echo -n "${spinner:$i:1}" + echo -en "\010" + sleep 0.$i + done + done +} + +# Progress bar +progress () { + progress=$[$progress+$1] + if [[ "$NO_PROGRESS" == "1" ]] || [[ "$PACKER" == "1" ]]; then + echo "progress=${progress}" > /tmp/INSTALL.stat + return + fi + bar="#" + + # Prevent progress of overflowing + if [[ $progress -ge 100 ]]; then + echo -ne "##################################################################################################### (100%)\r" + return + fi + # Display progress + for p in $(seq 1 $progress); do + bar+="#" + echo -ne "$bar ($p%)\r" + done + echo -ne '\n' + echo "progress=${progress}" > /tmp/INSTALL.stat +} + +# Check locale +checkLocale () { + debug "Checking Locale" + # If locale is missing, generate and install a common UTF-8 + if [[ ! -f /etc/default/locale || $(wc -l /etc/default/locale| cut -f 1 -d\ ) -eq "1" ]]; then + checkAptLock + sudo DEBIAN_FRONTEND=noninteractive apt install locales -qy + sudo sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/g' /etc/locale.gen + sudo locale-gen en_US.UTF-8 + sudo update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 + fi +} + +# Simple function to check command exit code +checkFail () { + # '-ne' checks for numerical differences, '==' used for strings + if [[ $2 -ne 0 ]]; then + echo "iAmError: $1" + echo "The last command exited with error code: $2" + exit $2 + fi +} + +ask_o () { + + ANSWER="" + + if [ -z "${1}" ]; then + echo "This function needs at least 1 parameter." + exit 1 + fi + + [ -z "${2}" ] && OPT1="y" || OPT1="${2}" + [ -z "${3}" ] && OPT2="n" || OPT2="${3}" + + while true; do + case "${ANSWER}" in "${OPT1}" | "${OPT2}") break ;; esac + echo -e -n "${1} (${OPT1}/${OPT2}) " + read ANSWER + ANSWER=$(echo "${ANSWER}" | tr '[:upper:]' '[:lower:]') + done + +} + +clean () { + rm /tmp/INSTALL.stat + rm /tmp/INSTALL.sh.* +} + +# Check if misp user is present and if run as root +checkID () { + debug "Checking if run as root and $MISP_USER is present" + if [[ $EUID -eq 0 ]]; then + echo "This script cannot be run as a root" + clean > /dev/null 2>&1 + exit 1 + elif [[ $(id $MISP_USER >/dev/null; echo $?) -ne 0 ]]; then + if [[ "$UNATTENDED" != "1" ]]; then + echo "There is NO user called '$MISP_USER' create a user '$MISP_USER' (y) or continue as $USER (n)? (y/n) " + read ANSWER + ANSWER=$(echo $ANSWER |tr '[:upper:]' '[:lower:]') + INSTALL_USER=${USER} + else + ANSWER="y" + fi + + if [[ $ANSWER == "y" ]]; then + sudo useradd -s /bin/bash -m -G adm,cdrom,sudo,dip,plugdev,www-data,staff $MISP_USER + echo $MISP_USER:$MISP_PASSWORD | sudo chpasswd + echo "User $MISP_USER added, password is: $MISP_PASSWORD" + elif [[ $ANSWER == "n" ]]; then + echo "Using $USER as install user, hope that is what you want." + echo -e "${RED}Adding $USER to groups $WWW_USER and staff${NC}" + MISP_USER=$USER + sudo adduser $MISP_USER staff + sudo adduser $MISP_USER $WWW_USER + else + echo "yes or no was asked, try again." + sudo adduser $MISP_USER staff + sudo adduser $MISP_USER $WWW_USER + exit 1 + fi + else + echo "User ${MISP_USER} exists, skipping creation" + echo -e "${RED}Adding $MISP_USER to groups $WWW_USER and staff${NC}" + sudo adduser $MISP_USER staff + sudo adduser $MISP_USER $WWW_USER + fi + + # FIXME: the below SUDO_CMD check is a duplicate from global variables, try to have just one check + # sudo config to run $LUSER commands + if [[ "$(groups ${MISP_USER} |grep -o 'staff')" == "staff" ]]; then + SUDO_CMD="sudo -H -u ${MISP_USER} -g staff" + else + SUDO_CMD="sudo -H -u ${MISP_USER}" + fi + +} + +# pre-install check to make sure what we will be installing on, is ready and not a half installed system +preInstall () { +# preInstall needs to be able to be called before ANY action. Install/Upgrade/AddTool +# Pre install wants to be the place too where the following is checked and set via ENV_VAR: +# Check if composer is installed and functioning +# Check if misp db is installed (API call would confirm that the DB indeed works) +# Check apache config (Maybe try to talk to the server via api, this would confirm quite a lot) +# Check if workers are running/installed, maybe kick them if they are not +# /var/www/MISP/app/Config/[bootstrap,databases,core,config].php exists +# /var/www/MISP perms are correct (for $SUDO_WWW useage) +# + + # Check if $PATH_TO_MISP exists and is writable by $WWW_USER + [[ -d "$PATH_TO_MISP" ]] && PATH_TO_MISP_EXISTS=1 && echo "$PATH_TO_MISP exists" + + # .git exists and git is working for $WWW_USER + [[ -d "$PATH_TO_MISP/.git" ]] && PATH_TO_GIT_EXISTS=1 && echo "$PATH_TO_MISP/.git exists" && cd $PATH_TO_MISP && $SUDO_WWW git status + + # .gnupg exists and working correctly + [[ -d "$PATH_TO_MISP/.gnupg" ]] && PATH_TO_GNUPG_EXISTS=1 && echo "$PATH_TO_MISP/.gnupg exists" + + + # Extract username, password and dbname + ##cat database.php |grep -v // |grep -e database -e login -e password |tr -d \' |tr -d \ |tr -d , |tr -d \> + DBPASSWORD_MISP=$(cat database.php |grep -v // |grep -e password |tr -d \' |tr -d \ |tr -d , |tr -d \> |cut -f 2 -d=) + DBUSER_MISP=$(cat database.php |grep -v // |grep -e login |tr -d \' |tr -d \ |tr -d , |tr -d \> |cut -f 2 -d=) + DBNAME=$(cat database.php |grep -v // |grep -e database |tr -d \' |tr -d \ |tr -d , |tr -d \> |cut -f 2 -d=) + AUTH_KEY=$(mysql -h $DBHOST --disable-column-names -B -u $DBUSER_MISP -p"$DBPASSWORD_MISP" $DBNAME -e 'SELECT authkey FROM users WHERE role_id=1 LIMIT 1') + + # Check if db exists + [[ -d "/var/lib/mysql/$DBNAME" ]] && MISP_DB_DIR_EXISTS=1 && echo "/var/lib/mysql/$DBNAME exists" + + echo -e "${RED}Place-holder, not implemented yet.${NC}" + exit +} + +# Upgrade function +upgrade () { + headerJSON="application/json" + Acc="Accept:" + Autho="Authorization:" + CT="Content-Type:" + MISP_BASEURL="https://127.0.0.1" + ${SUDO_WWW} sh -c "cd ${PATH_TO_MISP}/app ; php composer.phar update ; php composer.phar self-update" + + for URN in $(echo "galaxies warninglists noticelists objectTemplates taxonomies"); do + curl --header "$Autho $AUTH_KEY" --header "$Acc $headerJSON" --header "$CT $headerJSON" -k -X POST $MISP_BASEURL/$URN/update + done + + echo -e "${RED}Place-holder, not implemented yet.${NC}" + exit +} + +# check is /usr/local/src is RW by misp user +checkUsrLocalSrc () { + echo "" + if [[ -e /usr/local/src ]]; then + WRITEABLE=$(sudo -H -u $MISP_USER touch /usr/local/src 2> /dev/null ; echo $?) + if [[ "$WRITEABLE" == "0" ]]; then + echo "Good, /usr/local/src exists and is writeable as $MISP_USER" + else + # TODO: The below might be shorter, more elegant and more modern + #[[ -n $KALI ]] || [[ -n $UNATTENDED ]] && echo "Just do it" + sudo chmod 2775 /usr/local/src + sudo chown root:staff /usr/local/src + fi + else + echo "/usr/local/src does not exist, creating." + mkdir -p /usr/local/src + sudo chmod 2775 /usr/local/src + # TODO: Better handling /usr/local/src permissions + if [[ "$(cat /etc/group |grep staff > /dev/null 2>&1)" == "0" ]]; then + sudo chown root:staff /usr/local/src + fi + fi +} + +kaliSpaceSaver () { + # Future function in case Kali overlay on LiveCD is full + echo "${RED}Not implement${NC}" +} + +# FIXME: Kali now uses kali/kali instead of root/toor +# Because Kali is l33t we make sure we DO NOT run as root +kaliOnTheR0ckz () { + totalRoot=$(df -k | grep /$ |awk '{ print $2 }') + totalMem=$(cat /proc/meminfo|grep MemTotal |grep -Eo '[0-9]{1,}') + overlay=$(df -kh |grep overlay; echo $?) # if 1 overlay NOT present + + if [[ ${totalRoot} -lt 3059034 ]]; then + echo "(If?) You run Kali in LiveCD mode and we need more overlay disk space." + echo "This is defined by the total memory, you have: ${totalMem}kB which is not enough." + echo "6-8Gb should be fine. (need >3Gb overlayFS)" + exit 1 + fi + + if [[ ${EUID} -eq 0 ]]; then + echo "This script must NOT be run as root" + exit 1 + elif [[ $(id ${MISP_USER} >/dev/null; echo $?) -ne 0 ]]; then + sudo useradd -s /bin/bash -m -G adm,cdrom,sudo,dip,plugdev,www-data,staff ${MISP_USER} + echo ${MISP_USER}:${MISP_PASSWORD} | sudo chpasswd + else + # TODO: Make sure we consider this further down the road + echo "User ${MISP_USER} exists, skipping creation" + fi +} + +setBaseURL () { + debug "Setting Base URL" + + CONN=$(ip -br -o -4 a |grep UP |head -1 |tr -d "UP") + IFACE=$(echo $CONN |awk {'print $1'}) + IP=$(echo $CONN |awk {'print $2'}| cut -f1 -d/) + + [[ -n ${MANUFACTURER} ]] || checkManufacturer + + if [[ "${MANUFACTURER}" != "innotek GmbH" ]] && [[ "$MANUFACTURER" != "VMware, Inc." ]] && [[ "$MANUFACTURER" != "QEMU" ]]; then + debug "We guess that this is a physical machine and cannot reliably guess what the MISP_BASEURL might be." + + if [[ "${UNATTENDED}" != "1" ]]; then + echo "You can now enter your own MISP_BASEURL, if you wish to NOT do that, the MISP_BASEURL will be empty, which will work, but ideally you configure it afterwards." + echo "Do you want to change it now? (y/n) " + read ANSWER + ANSWER=$(echo ${ANSWER} |tr '[:upper:]' '[:lower:]') + if [[ "${ANSWER}" == "y" ]]; then + if [[ ! -z ${IP} ]]; then + echo "It seems you have an interface called ${IFACE} UP with the following IP: ${IP} - FYI" + echo "Thus your Base URL could be: https://${IP}" + fi + echo "Please enter the Base URL, e.g: 'https://example.org'" + echo "" + echo -n "Enter Base URL: " + read MISP_BASEURL + else + MISP_BASEURL='""' + fi + else + MISP_BASEURL="https://misp.local" + # Webserver configuration + FQDN='misp.local' + fi + elif [[ "${KALI}" == "1" ]]; then + MISP_BASEURL="https://misp.local" + # Webserver configuration + FQDN='misp.local' + elif [[ "${MANUFACTURER}" == "innotek GmbH" ]]; then + MISP_BASEURL='https://localhost:8443' + IP=$(ip addr show | awk '$1 == "inet" {gsub(/\/.*$/, "", $2); print $2}' |grep -v "127.0.0.1" |tail -1) + sudo iptables -t nat -A OUTPUT -p tcp --dport 8443 -j DNAT --to ${IP}:443 + # Webserver configuration + FQDN='localhost.localdomain' + elif [[ "${MANUFACTURER}" == "VMware, Inc." ]]; then + MISP_BASEURL='""' + # Webserver configuration + FQDN='misp.local' + else + MISP_BASEURL='""' + # Webserver configuration + FQDN='misp.local' + fi +} + +# Test and install software RNG +installRNG () { + sudo modprobe tpm-rng 2> /dev/null + if [ "$?" -eq "0" ]; then + echo tpm-rng | sudo tee -a /etc/modules + fi + checkAptLock + sudo apt install -qy rng-tools # This might fail on TPM grounds, enable the security chip in your BIOS + sudo service rng-tools start + + if [ "$?" -eq "1" ]; then + sudo apt purge -qy rng-tools + sudo apt install -qy haveged + sudo /etc/init.d/haveged start + fi +} + +# Kali upgrade +kaliUpgrade () { + debug "Running various Kali upgrade tasks" + checkAptLock + sudo DEBIAN_FRONTEND=noninteractive apt update + sudo DEBIAN_FRONTEND=noninteractive apt install --only-upgrade bash libc6 -y + sudo DEBIAN_FRONTEND=noninteractive apt autoremove -y +} + +# Disables sleep +disableSleep () { + gsettings set org.gnome.settings-daemon.plugins.power sleep-inactive-ac-timeout 0 2> /dev/null + gsettings set org.gnome.settings-daemon.plugins.power sleep-inactive-battery-timeout 0 2> /dev/null + gsettings set org.gnome.settings-daemon.plugins.power sleep-inactive-battery-type nothing 2> /dev/null + gsettings set org.gnome.desktop.screensaver lock-enabled false 2> /dev/null + gsettings set org.gnome.desktop.screensaver idle-activation-enabled false 2> /dev/null + + setterm -blank 0 -powersave off -powerdown 0 + xset s 0 0 2> /dev/null + xset dpms 0 0 2> /dev/null + xset dpms force off + xset s off 2> /dev/null + service sleepd stop + kill $(lsof | grep 'sleepd' | awk '{print $2}') + checkAptLock +} + +# Remove alias if present +if [[ $(type -t checkAptLock) == "alias" ]]; then unalias checkAptLock; fi +# Simple function to make sure APT is not locked +checkAptLock () { + SLEEP=3 + if [[ -n ${APT_UPDATED} ]]; then + sudo apt update && APT_UPDATED=1 + fi + while [ "$DONE" != "0" ]; do + sudo apt-get check 2> /dev/null > /dev/null && DONE=0 + sleep $SLEEP + SLEEP=$[$SLEEP+3] + done + unset DONE +} + +# Install Php 7.0 dependencies +installDepsPhp70 () { + debug "Installing PHP 7.0 dependencies" + PHP_ETC_BASE=/etc/php/7.0 + PHP_INI=${PHP_ETC_BASE}/apache2/php.ini + checkAptLock + sudo apt install -qy \ + libapache2-mod-php \ + php php-cli \ + php-dev \ + php-json php-xml php-mysql php-opcache php-readline php-mbstring php-zip \ + php-redis php-gnupg \ + php-gd + + for key in upload_max_filesize post_max_size max_execution_time max_input_time memory_limit + do + sudo sed -i "s/^\($key\).*/\1 = $(eval echo \${$key})/" $PHP_INI + done +} + +# Install Php 7.3 deps +installDepsPhp73 () { + debug "Installing PHP 7.3 dependencies" + PHP_ETC_BASE=/etc/php/7.3 + PHP_INI=${PHP_ETC_BASE}/apache2/php.ini + checkAptLock + if [[ ! -n ${KALI} ]]; then + sudo apt install -qy \ + libapache2-mod-php7.3 \ + php7.3 php7.3-cli \ + php7.3-dev \ + php7.3-json php7.3-xml php7.3-mysql php7.3-opcache php7.3-readline php7.3-mbstring \ + php-redis php-gnupg \ + php-gd + else + sudo apt install -qy \ + libapache2-mod-php7.3 \ + libgpgme-dev \ + php7.3 php7.3-cli \ + php7.3-dev \ + php7.3-json php7.3-xml php7.3-mysql php7.3-opcache php7.3-readline php7.3-mbstring \ + php7.3-gd + sudo pecl channel-update pecl.php.net + #sudo pear config-set php_ini ${PHP_INI} + echo "" |sudo pecl install redis + sudo pecl install gnupg + echo extension=gnupg.so | sudo tee ${PHP_ETC_BASE}/mods-available/gnupg.ini + echo extension=redis.so | sudo tee ${PHP_ETC_BASE}/mods-available/redis.ini + fi +} + +# Installing core dependencies +installDeps () { + debug "Installing core dependencies" + checkAptLock + sudo apt install -qy etckeeper + # Skip dist-upgrade for now, pulls in 500+ updated packages + #sudo apt -y dist-upgrade + gitMail=$(git config --global --get user.email ; echo $?) + if [ "$?" -eq "1" ]; then + git config --global user.email "root@kali.lan" + fi + gitUser=$(git config --global --get user.name ; echo $?) + if [ "$?" -eq "1" ]; then + git config --global user.name "Root User" + fi + + [[ -n $KALI ]] || [[ -n $UNATTENDED ]] && sudo DEBIAN_FRONTEND=noninteractive apt install -qy postfix || sudo apt install -qy postfix + + sudo apt install -qy \ + curl gcc git gnupg-agent make openssl redis-server neovim unzip zip libyara-dev python3-yara python3-redis python3-zmq sqlite3 \ + mariadb-client \ + mariadb-server \ + apache2 apache2-doc apache2-utils \ + python3-dev python3-pip libpq5 libjpeg-dev libfuzzy-dev ruby asciidoctor \ + libxml2-dev libxslt1-dev zlib1g-dev python3-setuptools + + installRNG +} + +# On Kali, the redis start-up script is broken. This tries to fix it. +fixRedis () { + # As of 20190124 redis-server init.d scripts are broken and need to be replaced + sudo mv /etc/init.d/redis-server /etc/init.d/redis-server_`date +%Y%m%d` + + echo '#! /bin/sh +### BEGIN INIT INFO +# Provides: redis-server +# Required-Start: $syslog +# Required-Stop: $syslog +# Should-Start: $local_fs +# Should-Stop: $local_fs +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: redis-server - Persistent key-value db +# Description: redis-server - Persistent key-value db +### END INIT INFO + +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin +DAEMON=/usr/bin/redis-server +DAEMON_ARGS=/etc/redis/redis.conf +NAME=redis-server +DESC=redis-server +PIDFILE=/var/run/redis.pid + +test -x $DAEMON || exit 0 +test -x $DAEMONBOOTSTRAP || exit 0 + +set -e + +case "$1" in + start) + echo -n "Starting $DESC: " + touch $PIDFILE + chown redis:redis $PIDFILE + if start-stop-daemon --start --quiet --umask 007 --pidfile $PIDFILE --chuid redis:redis --exec $DAEMON -- $DAEMON_ARGS + then + echo "$NAME." + else + echo "failed" + fi + ;; + stop) + echo -n "Stopping $DESC: " + if start-stop-daemon --stop --retry 10 --quiet --oknodo --pidfile $PIDFILE --exec $DAEMON + then + echo "$NAME." + else + echo "failed" + fi + rm -f $PIDFILE + ;; + + restart|force-reload) + ${0} stop + ${0} start + ;; + *) + echo "Usage: /etc/init.d/$NAME {start|stop|restart|force-reload}" >&2 + exit 1 + ;; +esac + +exit 0' | sudo tee /etc/init.d/redis-server + sudo chmod 755 /etc/init.d/redis-server + sudo /etc/init.d/redis-server start +} + +# generate MISP apache conf +genApacheConf () { + echo " + ServerAdmin admin@localhost.lu + ServerName misp.local + + Redirect permanent / https://misp.local + + LogLevel warn + ErrorLog /var/log/apache2/misp.local_error.log + CustomLog /var/log/apache2/misp.local_access.log combined + ServerSignature Off + + + + ServerAdmin admin@localhost.lu + ServerName misp.local + DocumentRoot $PATH_TO_MISP/app/webroot + + + Options -Indexes + AllowOverride all + Require all granted + Order allow,deny + allow from all + + + SSLEngine On + SSLCertificateFile /etc/ssl/private/misp.local.crt + SSLCertificateKeyFile /etc/ssl/private/misp.local.key + # SSLCertificateChainFile /etc/ssl/private/misp-chain.crt + + LogLevel warn + ErrorLog /var/log/apache2/misp.local_error.log + CustomLog /var/log/apache2/misp.local_access.log combined + ServerSignature Off + Header set X-Content-Type-Options nosniff + Header set X-Frame-Options DENY + " | sudo tee /etc/apache2/sites-available/misp-ssl.conf +} + +# Add git pull update mechanism to rc.local - TODO: Make this better +gitPullAllRCLOCAL () { + sudo sed -i -e '$i \git_dirs="/usr/local/src/misp-modules /var/www/misp-dashboard /usr/local/src/faup /usr/local/src/mail_to_misp /usr/local/src/misp-modules /usr/local/src/viper /var/www/misp-dashboard"\n' /etc/rc.local + sudo sed -i -e '$i \for d in $git_dirs; do\n' /etc/rc.local + sudo sed -i -e '$i \ echo "Updating ${d}"\n' /etc/rc.local + sudo sed -i -e '$i \ cd $d && sudo git pull &\n' /etc/rc.local + sudo sed -i -e '$i \done\n' /etc/rc.local +} + + +# Main composer function +composer () { + sudo mkdir -p /var/www/.composer ; sudo chown ${WWW_USER}:${WWW_USER} /var/www/.composer + ${SUDO_WWW} sh -c "cd ${PATH_TO_MISP}/app ; php composer.phar install" +} + + +# TODO: FIX somehow the alias of the function does not work +# Composer on php 7.0 does not need any special treatment the provided phar works well +alias composer70=composer +# Composer on php 7.2 does not need any special treatment the provided phar works well +alias composer72=composer +# Composer on php 7.3 does not need any special treatment the provided phar works well +alias composer73=composer + +# TODO: this is probably a useless function +# Enable various core services +enableServices () { + sudo systemctl daemon-reload + sudo systemctl enable --now mysql + sudo systemctl enable --now apache2 + sudo systemctl enable --now redis-server +} + +# TODO: check if this makes sense +# Generate rc.local +genRCLOCAL () { + if [[ ! -e /etc/rc.local ]]; then + echo '#!/bin/sh -e' | tee -a /etc/rc.local + echo 'exit 0' | sudo tee -a /etc/rc.local + chmod u+x /etc/rc.local + fi + + sudo sed -i -e '$i \echo never > /sys/kernel/mm/transparent_hugepage/enabled\n' /etc/rc.local + sudo sed -i -e '$i \echo 1024 > /proc/sys/net/core/somaxconn\n' /etc/rc.local + sudo sed -i -e '$i \sysctl vm.overcommit_memory=1\n' /etc/rc.local + sudo sed -i -e '$i \[ -f /etc/init.d/firstBoot ] && bash /etc/init.d/firstBoot\n' /etc/rc.local +} + +# Run PyMISP tests +runTests () { + echo "url = \"${MISP_BASEURL}\" +key = \"${AUTH_KEY}\"" |sudo tee ${PATH_TO_MISP}/PyMISP/tests/keys.py + sudo chown -R $WWW_USER:$WWW_USER $PATH_TO_MISP/PyMISP/ + + ${SUDO_WWW} sh -c "cd $PATH_TO_MISP/PyMISP && git submodule foreach git pull origin master" + ${SUDO_WWW} ${PATH_TO_MISP}/venv/bin/pip install -e $PATH_TO_MISP/PyMISP/.[fileobjects,neo,openioc,virustotal,pdfexport] + ${SUDO_WWW} sh -c "cd $PATH_TO_MISP/PyMISP && ${PATH_TO_MISP}/venv/bin/python tests/testlive_comprehensive.py" +} + +# Nuke the install, meaning remove all MISP data but no packages, this makes testing the installer faster +nuke () { + echo -e "${RED}YOU ARE ABOUT TO DELETE ALL MISP DATA! Sleeping 10, 9, 8...${NC}" + sleep 10 + sudo rm -rvf /usr/local/src/{misp-modules,viper,mail_to_misp,LIEF,faup} + sudo rm -rvf /var/www/MISP + sudo mysqladmin -h $DBHOST drop misp + sudo mysql -h $DBHOST -e "DROP USER misp@localhost" +} + +# Final function to let the user know what happened +theEnd () { + space + echo "Admin (root) DB Password: $DBPASSWORD_ADMIN" |$SUDO_CMD tee /home/${MISP_USER}/mysql.txt + echo "User (misp) DB Password: $DBPASSWORD_MISP" |$SUDO_CMD tee -a /home/${MISP_USER}/mysql.txt + echo "Authkey: $AUTH_KEY" |$SUDO_CMD tee -a /home/${MISP_USER}/MISP-authkey.txt + + # Commenting out, see: https://github.com/MISP/MISP/issues/5368 + # clear -x + space + echo -e "${LBLUE}MISP${NC} Installed, access here: ${MISP_BASEURL}" + echo + echo "User: admin@admin.test" + echo "Password: admin" + space + ##[[ -n $KALI ]] || [[ -n $DASHBOARD ]] || [[ -n $ALL ]] && echo -e "${LBLUE}MISP${NC} Dashboard, access here: ${MISP_BASEURL}:8001" + ##[[ -n $KALI ]] || [[ -n $DASHBOARD ]] || [[ -n $ALL ]] && space + ##[[ -n $KALI ]] || [[ -n $VIPER ]] || [[ -n $ALL ]] && echo -e "viper-web installed, access here: ${MISP_BASEURL}:8888" + ##[[ -n $KALI ]] || [[ -n $VIPER ]] || [[ -n $ALL ]] && echo -e "viper-cli configured with your ${LBLUE}MISP${NC} ${RED}Site Admin Auth Key${NC}" + ##[[ -n $KALI ]] || [[ -n $VIPER ]] || [[ -n $ALL ]] && echo + ##[[ -n $KALI ]] || [[ -n $VIPER ]] || [[ -n $ALL ]] && echo "User: admin" + ##[[ -n $KALI ]] || [[ -n $VIPER ]] || [[ -n $ALL ]] && echo "Password: Password1234" + ##[[ -n $KALI ]] || [[ -n $VIPER ]] || [[ -n $ALL ]] && space + echo -e "The following files were created and need either ${RED}protection or removal${NC} (${YELLOW}shred${NC} on the CLI)" + echo "/home/${MISP_USER}/mysql.txt" + echo -e "${RED}Contents:${NC}" + cat /home/${MISP_USER}/mysql.txt + echo "/home/${MISP_USER}/MISP-authkey.txt" + echo -e "${RED}Contents:${NC}" + cat /home/${MISP_USER}/MISP-authkey.txt + space + echo -e "The ${RED}LOCAL${NC} system credentials:" + echo "User: ${MISP_USER}" + echo "Password: ${MISP_PASSWORD} # Or the password you used of your custom user" + space + echo "GnuPG Passphrase is: ${GPG_PASSPHRASE}" + space + echo "To enable outgoing mails via postfix set a permissive SMTP server for the domains you want to contact:" + echo + echo "sudo postconf -e 'relayhost = example.com'" + echo "sudo postfix reload" + space + echo -e "Enjoy using ${LBLUE}MISP${NC}. For any issues see here: https://github.com/MISP/MISP/issues" + space + if [[ "$UNATTENDED" == "1" ]]; then + echo -e "${RED}Unattended install!${NC}" + echo -e "This means we guessed the Base URL, it might be wrong, please double check." + space + fi + + if [[ "$PACKER" == "1" ]]; then + echo -e "${RED}This was an Automated Packer install!${NC}" + echo -e "This means we forced an unattended install." + space + fi + + if [[ "$USER" != "$MISP_USER" && "$UNATTENDED" != "1" ]]; then + sudo su - ${MISP_USER} + fi +} +## End Function Section Nothing allowed in .md after this line ## + +aptUpgrade () { + debug "Upgrading system" + checkAptLock + + # If we run in non-interactive mode, make sure we do not stop all of a sudden + if [[ "${PACKER}" == "1" || "${UNATTENDED}" == "1" ]]; then + export DEBIAN_FRONTEND=noninteractive + export DEBIAN_PRIORITY=critical + sudo -E apt-get -qy -o "Dpkg::Options::=--force-confdef" -o "Dpkg::Options::=--force-confold" upgrade + sudo -E apt-get -qy autoclean + else + sudo apt-get upgrade -qy + fi +} + +# check if sudo is installed +checkSudoKeeper () { + echo "Checking for sudo and installing etckeeper" + if [[ ! -f $(which sudo) ]]; then + echo "Please enter your root password below to install etckeeper" + su -c "apt install etckeeper -y" + echo "Please enter your root password below to install sudo" + su -c "apt install sudo -y" + echo "Please enter your root password below to install sudo" + su -c "apt install curl -y" + echo "Please enter your root password below to add ${MISP_USER} to sudo group" + su -c "/usr/sbin/adduser ${MISP_USER} sudo" + echo "We added ${MISP_USER} to group sudo and now we need to log out and in again." + exit + else + sudo apt update + sudo apt install etckeeper -y + fi +} + +installCoreDeps () { + debug "Installing core dependencies" + # Install the dependencies: (some might already be installed) + sudo apt-get install curl gcc git gpg-agent make python python3 openssl redis-server sudo vim zip unzip virtualenv libfuzzy-dev sqlite3 moreutils -qy + + # Install MariaDB (a MySQL fork/alternative) + sudo apt-get install mariadb-client mariadb-server -qy + + # Install Apache2 + sudo apt-get install apache2 apache2-doc apache2-utils -qy + + # install Mitre's STIX and its dependencies by running the following commands: + sudo apt-get install python3-dev python3-pip libxml2-dev libxslt1-dev zlib1g-dev python-setuptools -qy +} + +# Install Php 7.4 dependencies +installDepsPhp74 () { + debug "Installing PHP 7.4 dependencies" + PHP_ETC_BASE=/etc/php/7.4 + PHP_INI=${PHP_ETC_BASE}/apache2/php.ini + checkAptLock + sudo apt install -qy \ + libapache2-mod-php \ + php php-cli \ + php-dev \ + php-json php-xml php-mysql php7.4-opcache php-readline php-mbstring php-zip \ + php-redis php-gnupg \ + php-intl php-bcmath \ + php-gd + + for key in upload_max_filesize post_max_size max_execution_time max_input_time memory_limit + do + sudo sed -i "s/^\($key\).*/\1 = $(eval echo \${$key})/" $PHP_INI + done +} + +# Install Php 7.3 deps +installDepsPhp73 () { + debug "Installing PHP 7.3 dependencies" + PHP_ETC_BASE=/etc/php/7.3 + PHP_INI=${PHP_ETC_BASE}/apache2/php.ini + checkAptLock + if [[ ! -n ${KALI} ]]; then + sudo apt install -qy \ + libapache2-mod-php7.3 \ + php7.3 php7.3-cli \ + php7.3-dev \ + php7.3-json php7.3-xml php7.3-mysql php7.3-opcache php7.3-readline php7.3-mbstring \ + php-redis php-gnupg \ + php-gd + else + sudo apt install -qy \ + libapache2-mod-php7.3 \ + libgpgme-dev \ + php7.3 php7.3-cli \ + php7.3-dev \ + php7.3-json php7.3-xml php7.3-mysql php7.3-opcache php7.3-readline php7.3-mbstring \ + php7.3-gd + sudo pecl channel-update pecl.php.net + #sudo pear config-set php_ini ${PHP_INI} + echo "" |sudo pecl install redis + sudo pecl install gnupg + echo extension=gnupg.so | sudo tee ${PHP_ETC_BASE}/mods-available/gnupg.ini + echo extension=redis.so | sudo tee ${PHP_ETC_BASE}/mods-available/redis.ini + fi +} + +# Install Php 7.2 dependencies +installDepsPhp72 () { + debug "Installing PHP 7.2 dependencies" + PHP_ETC_BASE=/etc/php/7.2 + PHP_INI=${PHP_ETC_BASE}/apache2/php.ini + checkAptLock + sudo apt install -qy \ + libapache2-mod-php \ + php php-cli \ + php-dev \ + php-json php-xml php-mysql php7.2-opcache php-readline php-mbstring php-zip \ + php-redis php-gnupg \ + php-intl php-bcmath \ + php-gd + + for key in upload_max_filesize post_max_size max_execution_time max_input_time memory_limit + do + sudo sed -i "s/^\($key\).*/\1 = $(eval echo \${$key})/" $PHP_INI + done +} + +# Install Php 7.0 dependencies +installDepsPhp70 () { + debug "Installing PHP 7.0 dependencies" + PHP_ETC_BASE=/etc/php/7.0 + PHP_INI=${PHP_ETC_BASE}/apache2/php.ini + checkAptLock + sudo apt install -qy \ + libapache2-mod-php \ + php php-cli \ + php-dev \ + php-json php-xml php-mysql php-opcache php-readline php-mbstring php-zip \ + php-redis php-gnupg \ + php-gd + + for key in upload_max_filesize post_max_size max_execution_time max_input_time memory_limit + do + sudo sed -i "s/^\($key\).*/\1 = $(eval echo \${$key})/" $PHP_INI + done +} + +## 1_prepareDB.sh ## +apacheConfig () { + debug "Generating Apache config, if this hangs, make sure you have enough entropy (install: haveged or wait)" + sudo cp ${PATH_TO_MISP}/INSTALL/apache.24.misp.ssl /etc/apache2/sites-available/misp-ssl.conf + + if [[ ! -z ${MISP_BASEURL} ]] && [[ "$(echo $MISP_BASEURL|cut -f 1 -d :)" == "http" || "$(echo $MISP_BASEURL|cut -f 1 -d :)" == "https" ]]; then + + echo "Potentially replacing misp.local with $MISP_BASEURL in misp-ssl.conf" + + fi + + # If a valid SSL certificate is not already created for the server, + # create a self-signed certificate: + sudo openssl req -newkey rsa:4096 -days 365 -nodes -x509 \ + -subj "/C=${OPENSSL_C}/ST=${OPENSSL_ST}/L=${OPENSSL_L}/O=${OPENSSL_O}/OU=${OPENSSL_OU}/CN=${OPENSSL_CN}/emailAddress=${OPENSSL_EMAILADDRESS}" \ + -keyout /etc/ssl/private/misp.local.key -out /etc/ssl/private/misp.local.crt + + # Enable modules, settings, and default of SSL in Apache + sudo a2dismod status + sudo a2enmod ssl + sudo a2enmod rewrite + sudo a2enmod headers + sudo a2dissite 000-default + sudo a2ensite default-ssl + + # Apply all changes + sudo systemctl restart apache2 + # activate new vhost + sudo a2dissite default-ssl + sudo a2ensite misp-ssl + + # Restart apache + sudo systemctl restart apache2 +} + +installCore () { + debug "Installing ${LBLUE}MISP${NC} core" + # Download MISP using git in the /var/www/ directory. + if [[ ! -d ${PATH_TO_MISP} ]]; then + sudo mkdir ${PATH_TO_MISP} + sudo chown ${WWW_USER}:${WWW_USER} ${PATH_TO_MISP} + false; while [[ $? -ne 0 ]]; do checkAptLock; ${SUDO_WWW} git clone https://github.com/MISP/MISP.git ${PATH_TO_MISP}; done + false; while [[ $? -ne 0 ]]; do checkAptLock; ${SUDO_WWW} git -C ${PATH_TO_MISP} submodule update --progress --init --recursive; done + # Make git ignore filesystem permission differences for submodules + ${SUDO_WWW} git -C ${PATH_TO_MISP} submodule foreach --recursive git config core.filemode false + + # Make git ignore filesystem permission differences + ${SUDO_WWW} git -C ${PATH_TO_MISP} config core.filemode false + + # Create a python3 virtualenv + ${SUDO_WWW} virtualenv -p python3 ${PATH_TO_MISP}/venv + + # make pip happy + sudo mkdir /var/www/.cache/ + sudo chown ${WWW_USER}:${WWW_USER} /var/www/.cache + + for dependency in CybOXProject/python-cybox STIXProject/python-stix MAECProject/python-maec CybOXProject/mixbox; do + false; while [[ $? -ne 0 ]]; do checkAptLock; ${SUDO_WWW} git clone https://github.com/${dependency}.git ${PATH_TO_MISP_SCRIPTS}/${dependency##*/}; done + ${SUDO_WWW} git -C ${PATH_TO_MISP_SCRIPTS}/${dependency##*/} config core.filemode false + ${SUDO_WWW} ${PATH_TO_MISP}/venv/bin/pip install ${PATH_TO_MISP_SCRIPTS}/${dependency##*/} + done + + debug "Install python-stix2" + ${SUDO_WWW} ${PATH_TO_MISP}/venv/bin/pip install ${PATH_TO_MISP}/cti-python-stix2 + + debug "Install PyMISP" + ${SUDO_WWW} ${PATH_TO_MISP}/venv/bin/pip install ${PATH_TO_MISP}/PyMISP + + # FIXME: Remove libfaup etc once the egg has the library baked-in + sudo apt-get install cmake libcaca-dev liblua5.3-dev -y + cd /tmp + false; while [[ $? -ne 0 ]]; do [[ ! -d "faup" ]] && ${SUDO_CMD} git clone https://github.com/stricaud/faup.git faup; done + false; while [[ $? -ne 0 ]]; do [[ ! -d "gtcaca" ]] && ${SUDO_CMD} git clone https://github.com/stricaud/gtcaca.git gtcaca; done + sudo chown -R ${MISP_USER}:${MISP_USER} faup gtcaca + cd gtcaca + ${SUDO_CMD} mkdir -p build + cd build + ${SUDO_CMD} cmake .. && ${SUDO_CMD} make + sudo make install + cd ../../faup + ${SUDO_CMD} mkdir -p build + cd build + ${SUDO_CMD} cmake .. && ${SUDO_CMD} make + sudo make install + sudo ldconfig + + # install pydeep + false; while [[ $? -ne 0 ]]; do checkAptLock; ${SUDO_WWW} ${PATH_TO_MISP}/venv/bin/pip install git+https://github.com/kbandla/pydeep.git; done + + # install lief + ${SUDO_WWW} ${PATH_TO_MISP}/venv/bin/pip install lief + + # install zmq needed by mispzmq + ${SUDO_WWW} ${PATH_TO_MISP}/venv/bin/pip install zmq redis + + # install python-magic + ${SUDO_WWW} ${PATH_TO_MISP}/venv/bin/pip install python-magic + + # install plyara + ${SUDO_WWW} ${PATH_TO_MISP}/venv/bin/pip install plyara + else + debug "Trying to git pull existing install" + ${SUDO_WWW} git pull -C ${PATH_TO_MISP} + false; while [[ $? -ne 0 ]]; do ${SUDO_WWW} git -C ${PATH_TO_MISP} submodule update --progress --init --recursive; done + + ${SUDO_WWW} ${PATH_TO_MISP}/venv/bin/pip install -U setuptools pip lief zmq redis python-magic plyara + for dependency in CybOXProject/python-cybox STIXProject/python-stix MAECProject/python-maec CybOXProject/mixbox; do + false; while [[ $? -ne 0 ]]; do checkAptLock; ${SUDO_WWW} git -C ${PATH_TO_MISP_SCRIPTS}/${dependency##*/} pull; done + ${SUDO_WWW} ${PATH_TO_MISP}/venv/bin/pip install -U ${PATH_TO_MISP_SCRIPTS}/${dependency##*/} + done + + ${SUDO_WWW} ${PATH_TO_MISP}/venv/bin/pip install -U ${PATH_TO_MISP}/cti-python-stix2 + ${SUDO_WWW} ${PATH_TO_MISP}/venv/bin/pip install -U ${PATH_TO_MISP}/PyMISP + false; while [[ $? -ne 0 ]]; do checkAptLock; ${SUDO_WWW} ${PATH_TO_MISP}/venv/bin/pip install -U git+https://github.com/kbandla/pydeep.git; done +fi +} + +installCake () { + debug "Installing CakePHP" + # Make composer cache happy + # /!\ composer on Ubuntu when invoked with sudo -u doesn't set $HOME to /var/www but keeps it /home/misp \!/ + sudo mkdir -p /var/www/.composer ; sudo chown ${WWW_USER}:${WWW_USER} /var/www/.composer + ${SUDO_WWW} sh -c "cd ${PATH_TO_MISP}/app ;php composer.phar install" + + # Enable CakeResque with php-redis + sudo phpenmod redis + sudo phpenmod gnupg + + # To use the scheduler worker for scheduled tasks, do the following: + ${SUDO_WWW} cp -fa ${PATH_TO_MISP}/INSTALL/setup/config.php ${PATH_TO_MISP}/app/Plugin/CakeResque/Config/config.php + + # If you have multiple MISP instances on the same system, don't forget to have a different Redis per MISP instance for the CakeResque workers + # The default Redis port can be updated in Plugin/CakeResque/Config/config.php +} + +# Main function to fix permissions to something sane +permissions () { + debug "Setting permissions" + sudo chown -R ${WWW_USER}:${WWW_USER} ${PATH_TO_MISP} + sudo chmod -R 750 ${PATH_TO_MISP} + sudo chmod -R g+ws ${PATH_TO_MISP}/app/tmp + sudo chmod -R g+ws ${PATH_TO_MISP}/app/files + sudo chmod -R g+ws ${PATH_TO_MISP}/app/files/scripts/tmp +} + +configMISP () { + debug "Generating ${LBLUE}MISP${NC} config files" + # There are 4 sample configuration files in ${PATH_TO_MISP}/app/Config that need to be copied + ${SUDO_WWW} cp -a ${PATH_TO_MISP}/app/Config/bootstrap.default.php ${PATH_TO_MISP}/app/Config/bootstrap.php + ${SUDO_WWW} cp -a ${PATH_TO_MISP}/app/Config/database.default.php ${PATH_TO_MISP}/app/Config/database.php + ${SUDO_WWW} cp -a ${PATH_TO_MISP}/app/Config/core.default.php ${PATH_TO_MISP}/app/Config/core.php + ${SUDO_WWW} cp -a ${PATH_TO_MISP}/app/Config/config.default.php ${PATH_TO_MISP}/app/Config/config.php + + echo " 'Database/Mysql', + //'datasource' => 'Database/Postgres', + 'persistent' => false, + 'host' => '$DBHOST', + 'login' => '$DBUSER_MISP', + 'port' => 3306, // MySQL & MariaDB + //'port' => 5432, // PostgreSQL + 'password' => '$DBPASSWORD_MISP', + 'database' => '$DBNAME', + 'prefix' => '', + 'encoding' => 'utf8', + ); + }" | ${SUDO_WWW} tee ${PATH_TO_MISP}/app/Config/database.php + + # Important! Change the salt key in ${PATH_TO_MISP}/app/Config/config.php + # The salt key must be a string at least 32 bytes long. + # The admin user account will be generated on the first login, make sure that the salt is changed before you create that user + # If you forget to do this step, and you are still dealing with a fresh installation, just alter the salt, + # delete the user from mysql and log in again using the default admin credentials (admin@admin.test / admin) + + # and make sure the file permissions are still OK + sudo chown -R ${WWW_USER}:${WWW_USER} ${PATH_TO_MISP}/app/Config + sudo chmod -R 750 ${PATH_TO_MISP}/app/Config +} + +# Core cake commands to tweak MISP and aleviate some of the configuration pains +# The $RUN_PHP is ONLY set on RHEL/CentOS installs and can thus be ignored +# This file is NOT an excuse to NOT read the settings and familiarize ourselves with them ;) + +coreCAKE () { + debug "Running core Cake commands to set sane defaults for ${LBLUE}MISP${NC}" + + # IF you have logged in prior to running this, it will fail but the fail is NON-blocking + $SUDO_WWW $RUN_PHP -- $CAKE userInit -q + + # This makes sure all Database upgrades are done, without logging in. + $SUDO_WWW $RUN_PHP -- $CAKE Admin runUpdates + + # The default install is Python >=3.6 in a virtualenv, setting accordingly + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.python_bin" "${PATH_TO_MISP}/venv/bin/python" + + # Set default role + # TESTME: The following seem defunct, please test. + # $SUDO_WWW $RUN_PHP -- $CAKE setDefaultRole 3 + + # Tune global time outs + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "Session.autoRegenerate" 0 + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "Session.timeout" 600 + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "Session.cookieTimeout" 3600 + + # Change base url, either with this CLI command or in the UI + $SUDO_WWW $RUN_PHP -- $CAKE Baseurl $MISP_BASEURL + # example: 'baseurl' => 'https://', + # alternatively, you can leave this field empty if you would like to use relative pathing in MISP + # 'baseurl' => '', + # The base url of the application (in the format https://www.mymispinstance.com) as visible externally/by other MISPs. + # MISP will encode this URL in sharing groups when including itself. If this value is not set, the baseurl is used as a fallback. + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.external_baseurl" $MISP_BASEURL + + # Enable GnuPG + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "GnuPG.email" "$GPG_EMAIL_ADDRESS" + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "GnuPG.homedir" "$PATH_TO_MISP/.gnupg" + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "GnuPG.password" "$GPG_PASSPHRASE" + # FIXME: what if we have not gpg binary but a gpg2 one? + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "GnuPG.binary" "$(which gpg)" + + # Enable installer org and tune some configurables + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.host_org_id" 1 + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.email" "info@admin.test" + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.disable_emailing" true + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.contact" "info@admin.test" + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.disablerestalert" true + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.showCorrelationsOnIndex" true + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.default_event_tag_collection" 0 + + # Provisional Cortex tunes + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "Plugin.Cortex_services_enable" false + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "Plugin.Cortex_services_url" "http://127.0.0.1" + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "Plugin.Cortex_services_port" 9000 + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "Plugin.Cortex_timeout" 120 + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "Plugin.Cortex_authkey" "" + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "Plugin.Cortex_ssl_verify_peer" false + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "Plugin.Cortex_ssl_verify_host" false + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "Plugin.Cortex_ssl_allow_self_signed" true + + # Various plugin sightings settings + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "Plugin.Sightings_policy" 0 + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "Plugin.Sightings_anonymise" false + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "Plugin.Sightings_anonymise_as" 1 + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "Plugin.Sightings_range" 365 + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "Plugin.Sightings_sighting_db_enable" false + + # Plugin CustomAuth tuneable + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "Plugin.CustomAuth_disable_logout" false + + # RPZ Plugin settings + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "Plugin.RPZ_policy" "DROP" + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "Plugin.RPZ_walled_garden" "127.0.0.1" + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "Plugin.RPZ_serial" "\$date00" + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "Plugin.RPZ_refresh" "2h" + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "Plugin.RPZ_retry" "30m" + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "Plugin.RPZ_expiry" "30d" + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "Plugin.RPZ_minimum_ttl" "1h" + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "Plugin.RPZ_ttl" "1w" + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "Plugin.RPZ_ns" "localhost." + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "Plugin.RPZ_ns_alt" "" + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "Plugin.RPZ_email" "root.localhost" + + # Force defaults to make MISP Server Settings less RED + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.language" "eng" + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.proposals_block_attributes" false + + # Redis block + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.redis_host" "127.0.0.1" + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.redis_port" 6379 + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.redis_database" 13 + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.redis_password" "" + + # Force defaults to make MISP Server Settings less YELLOW + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.ssdeep_correlation_threshold" 40 + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.extended_alert_subject" false + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.default_event_threat_level" 4 + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.newUserText" "Dear new MISP user,\\n\\nWe would hereby like to welcome you to the \$org MISP community.\\n\\n Use the credentials below to log into MISP at \$misp, where you will be prompted to manually change your password to something of your own choice.\\n\\nUsername: \$username\\nPassword: \$password\\n\\nIf you have any questions, don't hesitate to contact us at: \$contact.\\n\\nBest regards,\\nYour \$org MISP support team" + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.passwordResetText" "Dear MISP user,\\n\\nA password reset has been triggered for your account. Use the below provided temporary password to log into MISP at \$misp, where you will be prompted to manually change your password to something of your own choice.\\n\\nUsername: \$username\\nYour temporary password: \$password\\n\\nIf you have any questions, don't hesitate to contact us at: \$contact.\\n\\nBest regards,\\nYour \$org MISP support team" + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.enableEventBlocklisting" true + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.enableOrgBlocklisting" true + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.log_client_ip" false + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.log_auth" false + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.disableUserSelfManagement" false + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.disable_user_login_change" false + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.disable_user_password_change" false + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.disable_user_add" false + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.block_event_alert" false + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.block_event_alert_tag" "no-alerts=\"true\"" + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.block_old_event_alert" false + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.block_old_event_alert_age" "" + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.block_old_event_alert_by_date" "" + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.incoming_tags_disabled_by_default" false + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.maintenance_message" "Great things are happening! MISP is undergoing maintenance, but will return shortly. You can contact the administration at \$email." + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.footermidleft" "This is an initial install" + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.footermidright" "Please configure and harden accordingly" + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.welcome_text_top" "Initial Install, please configure" + # TODO: Make sure $FLAVOUR is correct + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.welcome_text_bottom" "Welcome to MISP on $FLAVOUR, change this message in MISP Settings" + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.attachments_dir" "$PATH_TO_MISP/app/files" + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.download_attachments_on_load" true + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.title_text" "MISP" + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.terms_download" false + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.showorgalternate" false + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.event_view_filter_fields" "id, uuid, value, comment, type, category, Tag.name" + + # Force defaults to make MISP Server Settings less GREEN + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "debug" 0 + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "Security.auth_enforced" false + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "Security.rest_client_baseurl" "" + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "Security.advanced_authkeys" false + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "Security.password_policy_length" 12 + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "Security.password_policy_complexity" '/^((?=.*\d)|(?=.*\W+))(?![\n])(?=.*[A-Z])(?=.*[a-z]).*$|.{16,}/' + $SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "Security.self_registration_message" "If you would like to send us a registration request, please fill out the form below. Make sure you fill out as much information as possible in order to ease the task of the administrators." + + # It is possible to updateMISP too, only here for reference how to to that on the CLI. + ## $SUDO_WWW $RUN_PHP -- $CAKE Admin updateMISP + + # Set MISP Live + $SUDO_WWW $RUN_PHP -- $CAKE Live $MISP_LIVE +} + +# This updates Galaxies, ObjectTemplates, Warninglists, Noticelists, Templates +updateGOWNT () { + # AUTH_KEY Place holder in case we need to **curl** somehing in the future + # + $SUDO_WWW $RUN_MYSQL -- mysql -h $DBHOST -u $DBUSER_MISP -p$DBPASSWORD_MISP misp -e "SELECT authkey FROM users;" | tail -1 > /tmp/auth.key + AUTH_KEY=$(cat /tmp/auth.key) + rm /tmp/auth.key + + debug "Updating Galaxies, ObjectTemplates, Warninglists, Noticelists and Templates" + # Update the galaxies… + # TODO: Fix updateGalaxies + $SUDO_WWW $RUN_PHP -- $CAKE Admin updateGalaxies + # Updating the taxonomies… + $SUDO_WWW $RUN_PHP -- $CAKE Admin updateTaxonomies + # Updating the warning lists… + $SUDO_WWW $RUN_PHP -- $CAKE Admin updateWarningLists + # Updating the notice lists… + $SUDO_WWW $RUN_PHP -- $CAKE Admin updateNoticeLists + # Updating the object templates… + $SUDO_WWW $RUN_PHP -- $CAKE Admin updateObjectTemplates "1337" +} + +# Generate GnuPG key +setupGnuPG () { + if [ ! -d $PATH_TO_MISP/.gnupg ]; then + # The email address should match the one set in the config.php + # set in the configuration menu in the administration menu configuration file + echo "%echo Generating a default key + Key-Type: default + Key-Length: $GPG_KEY_LENGTH + Subkey-Type: default + Name-Real: $GPG_REAL_NAME + Name-Comment: $GPG_COMMENT + Name-Email: $GPG_EMAIL_ADDRESS + Expire-Date: 0 + Passphrase: $GPG_PASSPHRASE + # Do a commit here, so that we can later print "done" + %commit + %echo done" > /tmp/gen-key-script + + $SUDO_WWW gpg --homedir $PATH_TO_MISP/.gnupg --batch --gen-key /tmp/gen-key-script + + # Export the public key to the webroot + $SUDO_WWW sh -c "gpg --homedir $PATH_TO_MISP/.gnupg --export --armor $GPG_EMAIL_ADDRESS" | $SUDO_WWW tee $PATH_TO_MISP/app/webroot/gpg.asc + fi +} + +logRotation () { + # MISP saves the stdout and stderr of its workers in ${PATH_TO_MISP}/app/tmp/logs + # To rotate these logs install the supplied logrotate script: + sudo cp ${PATH_TO_MISP}/INSTALL/misp.logrotate /etc/logrotate.d/misp + sudo chmod 0640 /etc/logrotate.d/misp +} + +backgroundWorkers () { + debug "Setting up background workers" + # To make the background workers start on boot + sudo chmod +x ${PATH_TO_MISP}/app/Console/worker/start.sh + + if [ ! -e /etc/rc.local ] + then + echo '#!/bin/sh -e' | sudo tee -a /etc/rc.local + echo 'exit 0' | sudo tee -a /etc/rc.local + sudo chmod u+x /etc/rc.local + fi + + echo "[Unit] +Description=MISP background workers +After=network.target + +[Service] +Type=forking +User=${WWW_USER} +Group=${WWW_USER} +ExecStart=${PATH_TO_MISP}/app/Console/worker/start.sh +Restart=always +RestartSec=10 + +[Install] +WantedBy=multi-user.target" | sudo tee /etc/systemd/system/misp-workers.service + + sudo systemctl daemon-reload + sudo systemctl enable --now misp-workers + + # Add the following lines before the last line (exit 0). Make sure that you replace www-data with your apache user: + sudo sed -i -e '$i \echo never > /sys/kernel/mm/transparent_hugepage/enabled\n' /etc/rc.local + sudo sed -i -e '$i \echo 1024 > /proc/sys/net/core/somaxconn\n' /etc/rc.local + sudo sed -i -e '$i \sysctl vm.overcommit_memory=1\n' /etc/rc.local +} + +# Main MISP Modules install function +mispmodules () { + cd /usr/local/src/ + sudo apt-get install cmake libcaca-dev liblua5.3-dev -y + ## TODO: checkUsrLocalSrc in main doc + if [[ ! -d /usr/local/src/misp-modules ]]; then + debug "Cloning misp-modules" + false; while [[ $? -ne 0 ]]; do $SUDO_CMD git clone https://github.com/MISP/misp-modules.git; done + else + false; while [[ $? -ne 0 ]]; do $SUDO_CMD git -C /usr/local/src/misp-modules pull; done + fi + + # Install faup/gtcaca + [[ ! -d "faup" ]] && false; while [[ $? -ne 0 ]]; do $SUDO_CMD git clone https://github.com/stricaud/faup.git faup; done + [[ ! -d "gtcaca" ]] && false; while [[ $? -ne 0 ]]; do $SUDO_CMD git clone https://github.com/stricaud/gtcaca.git gtcaca; done + sudo chown -R ${MISP_USER}:${MISP_USER} faup gtcaca + # Install gtcaca + cd gtcaca + $SUDO_CMD mkdir -p build + cd build + $SUDO_CMD cmake .. && $SUDO_CMD make + sudo make install + cd /usr/local/src/faup + # Install faup + $SUDO_CMD mkdir -p build + cd build + $SUDO_CMD cmake .. && $SUDO_CMD make + sudo make install + sudo ldconfig + + cd /usr/local/src/misp-modules + # some misp-modules dependencies + sudo apt install libpq5 libjpeg-dev tesseract-ocr libpoppler-cpp-dev imagemagick libopencv-dev zbar-tools libzbar0 libzbar-dev libfuzzy-dev -y + # If you build an egg, the user you build it as need write permissions in the CWD + sudo chgrp $WWW_USER . + sudo chmod og+w . + $SUDO_WWW ${PATH_TO_MISP}/venv/bin/pip install -I -r REQUIREMENTS + sudo chgrp staff . + $SUDO_WWW ${PATH_TO_MISP}/venv/bin/pip install -I . + $SUDO_WWW ${PATH_TO_MISP}/venv/bin/pip install censys pyfaup + + # Start misp-modules as a service + sudo cp /usr/local/src/misp-modules/etc/systemd/system/misp-modules.service /etc/systemd/system/ + sudo systemctl daemon-reload + sudo systemctl enable --now misp-modules + + # Sleep 9 seconds to give misp-modules a chance to spawn + sleep 9 + + # Enable Enrichment, set better timeouts + $SUDO_WWW $CAKE Admin setSetting "Plugin.Enrichment_services_enable" true + $SUDO_WWW $CAKE Admin setSetting "Plugin.Enrichment_hover_enable" true + $SUDO_WWW $CAKE Admin setSetting "Plugin.Enrichment_hover_popover_only" false + $SUDO_WWW $CAKE Admin setSetting "Plugin.Enrichment_timeout" 300 + $SUDO_WWW $CAKE Admin setSetting "Plugin.Enrichment_hover_timeout" 150 + # TODO:"Investigate why the next one fails" + #$SUDO_WWW $CAKE Admin setSetting "Plugin.Enrichment_asn_history_enabled" true + $SUDO_WWW $CAKE Admin setSetting "Plugin.Enrichment_cve_enabled" true + $SUDO_WWW $CAKE Admin setSetting "Plugin.Enrichment_dns_enabled" true + $SUDO_WWW $CAKE Admin setSetting "Plugin.Enrichment_btc_steroids_enabled" true + $SUDO_WWW $CAKE Admin setSetting "Plugin.Enrichment_ipasn_enabled" true + $SUDO_WWW $CAKE Admin setSetting "Plugin.Enrichment_yara_syntax_validator_enabled" true + $SUDO_WWW $CAKE Admin setSetting "Plugin.Enrichment_yara_query_enabled" true + $SUDO_WWW $CAKE Admin setSetting "Plugin.Enrichment_pdf_enabled" true + $SUDO_WWW $CAKE Admin setSetting "Plugin.Enrichment_docx_enabled" true + $SUDO_WWW $CAKE Admin setSetting "Plugin.Enrichment_xlsx_enabled" true + $SUDO_WWW $CAKE Admin setSetting "Plugin.Enrichment_pptx_enabled" true + $SUDO_WWW $CAKE Admin setSetting "Plugin.Enrichment_ods_enabled" true + $SUDO_WWW $CAKE Admin setSetting "Plugin.Enrichment_odt_enabled" true + $SUDO_WWW $CAKE Admin setSetting "Plugin.Enrichment_services_url" "http://127.0.0.1" + $SUDO_WWW $CAKE Admin setSetting "Plugin.Enrichment_services_port" 6666 + + # Enable Import modules, set better timeout + $SUDO_WWW $CAKE Admin setSetting "Plugin.Import_services_enable" true + $SUDO_WWW $CAKE Admin setSetting "Plugin.Import_services_url" "http://127.0.0.1" + $SUDO_WWW $CAKE Admin setSetting "Plugin.Import_services_port" 6666 + $SUDO_WWW $CAKE Admin setSetting "Plugin.Import_timeout" 300 + $SUDO_WWW $CAKE Admin setSetting "Plugin.Import_ocr_enabled" true + $SUDO_WWW $CAKE Admin setSetting "Plugin.Import_mispjson_enabled" true + $SUDO_WWW $CAKE Admin setSetting "Plugin.Import_openiocimport_enabled" true + $SUDO_WWW $CAKE Admin setSetting "Plugin.Import_threatanalyzer_import_enabled" true + $SUDO_WWW $CAKE Admin setSetting "Plugin.Import_csvimport_enabled" true + + # Enable Export modules, set better timeout + $SUDO_WWW $CAKE Admin setSetting "Plugin.Export_services_enable" true + $SUDO_WWW $CAKE Admin setSetting "Plugin.Export_services_url" "http://127.0.0.1" + $SUDO_WWW $CAKE Admin setSetting "Plugin.Export_services_port" 6666 + $SUDO_WWW $CAKE Admin setSetting "Plugin.Export_timeout" 300 + $SUDO_WWW $CAKE Admin setSetting "Plugin.Export_pdfexport_enabled" true +} + +# Main MISP Dashboard install function +mispDashboard () { + debug "Install misp-dashboard" + # Install pyzmq to main MISP venv + debug "Installing PyZMQ" + $SUDO_WWW ${PATH_TO_MISP}/venv/bin/pip install pyzmq + cd /var/www + sudo mkdir misp-dashboard + sudo chown $WWW_USER:$WWW_USER misp-dashboard + + false; while [[ $? -ne 0 ]]; do $SUDO_WWW git clone https://github.com/MISP/misp-dashboard.git; done + cd misp-dashboard + sudo -H /var/www/misp-dashboard/install_dependencies.sh + sudo sed -i "s/^host\ =\ localhost/host\ =\ 0.0.0.0/g" /var/www/misp-dashboard/config/config.cfg + sudo sed -i '/Listen 80/a Listen 0.0.0.0:8001' /etc/apache2/ports.conf + sudo apt install libapache2-mod-wsgi-py3 net-tools -y + echo " + ServerAdmin admin@misp.local + ServerName misp.local + + DocumentRoot /var/www/misp-dashboard + + WSGIDaemonProcess misp-dashboard \ + user=misp group=misp \ + python-home=/var/www/misp-dashboard/DASHENV \ + processes=1 \ + threads=15 \ + maximum-requests=5000 \ + listen-backlog=100 \ + queue-timeout=45 \ + socket-timeout=60 \ + connect-timeout=15 \ + request-timeout=60 \ + inactivity-timeout=0 \ + deadlock-timeout=60 \ + graceful-timeout=15 \ + eviction-timeout=0 \ + shutdown-timeout=5 \ + send-buffer-size=0 \ + receive-buffer-size=0 \ + header-buffer-size=0 \ + response-buffer-size=0 \ + server-metrics=Off + + WSGIScriptAlias / /var/www/misp-dashboard/misp-dashboard.wsgi + + + WSGIProcessGroup misp-dashboard + WSGIApplicationGroup %{GLOBAL} + Require all granted + + + LogLevel info + ErrorLog /var/log/apache2/misp-dashboard.local_error.log + CustomLog /var/log/apache2/misp-dashboard.local_access.log combined + ServerSignature Off + " | sudo tee /etc/apache2/sites-available/misp-dashboard.conf + + # Enable misp-dashboard in apache and reload + sudo a2ensite misp-dashboard + sudo systemctl restart apache2 + + # Needs to be started after apache2 is reloaded so the port status check works + $SUDO_WWW bash /var/www/misp-dashboard/start_all.sh + + # Add misp-dashboard to rc.local to start on boot. + sudo sed -i -e '$i \sudo -u www-data bash /var/www/misp-dashboard/start_all.sh > /tmp/misp-dashboard_rc.local.log\n' /etc/rc.local +} + +dashboardCAKE () { + # Enable ZeroMQ for misp-dashboard + $SUDO_WWW $CAKE Admin setSetting "Plugin.ZeroMQ_enable" true + $SUDO_WWW $CAKE Admin setSetting "Plugin.ZeroMQ_event_notifications_enable" true + $SUDO_WWW $CAKE Admin setSetting "Plugin.ZeroMQ_object_notifications_enable" true + $SUDO_WWW $CAKE Admin setSetting "Plugin.ZeroMQ_object_reference_notifications_enable" true + $SUDO_WWW $CAKE Admin setSetting "Plugin.ZeroMQ_attribute_notifications_enable" true + $SUDO_WWW $CAKE Admin setSetting "Plugin.ZeroMQ_sighting_notifications_enable" true + $SUDO_WWW $CAKE Admin setSetting "Plugin.ZeroMQ_user_notifications_enable" true + $SUDO_WWW $CAKE Admin setSetting "Plugin.ZeroMQ_organisation_notifications_enable" true + $SUDO_WWW $CAKE Admin setSetting "Plugin.ZeroMQ_port" 50000 + $SUDO_WWW $CAKE Admin setSetting "Plugin.ZeroMQ_redis_host" "localhost" + $SUDO_WWW $CAKE Admin setSetting "Plugin.ZeroMQ_redis_port" 6379 + $SUDO_WWW $CAKE Admin setSetting "Plugin.ZeroMQ_redis_database" 1 + $SUDO_WWW $CAKE Admin setSetting "Plugin.ZeroMQ_redis_namespace" "mispq" + $SUDO_WWW $CAKE Admin setSetting "Plugin.ZeroMQ_include_attachments" false + $SUDO_WWW $CAKE Admin setSetting "Plugin.ZeroMQ_tag_notifications_enable" false + $SUDO_WWW $CAKE Admin setSetting "Plugin.ZeroMQ_audit_notifications_enable" false +} + +# Main mail2misp install function +mail2misp () { + debug "Installing Mail2${LBLUE}MISP${NC}" + cd /usr/local/src/ + sudo apt-get install cmake libcaca-dev liblua5.3-dev -y + false; while [[ $? -ne 0 ]]; do $SUDO_CMD git clone https://github.com/MISP/mail_to_misp.git; done + ## TODO: The below fails miserably (obviously) if faup/gtcac dirs exist, let's just make the dangerous assumption (for the sake of the installer, that they exist) + ##[[ ! -d "faup" ]] && false; while [[ $? -ne 0 ]]; do $SUDO_CMD git clone https://github.com/stricaud/faup.git faup; done + ##[[ ! -d "gtcaca" ]] && false; while [[ $? -ne 0 ]]; do $SUDO_CMD git clone https://github.com/stricaud/gtcaca.git gtcaca; done + sudo chown -R ${MISP_USER}:${MISP_USER} faup mail_to_misp gtcaca + cd gtcaca + $SUDO_CMD mkdir -p build + cd build + $SUDO_CMD cmake .. && $SUDO_CMD make + sudo make install + cd ../../faup + $SUDO_CMD mkdir -p build + cd build + $SUDO_CMD cmake .. && $SUDO_CMD make + sudo make install + sudo ldconfig + cd ../../mail_to_misp + $SUDO_CMD virtualenv -p python3 venv + $SUDO_CMD ./venv/bin/pip install lief + $SUDO_CMD ./venv/bin/pip install -r requirements.txt + $SUDO_CMD cp mail_to_misp_config.py-example mail_to_misp_config.py + ##$SUDO cp mail_to_misp_config.py-example mail_to_misp_config.py + $SUDO_CMD sed -i "s/^misp_url\ =\ 'YOUR_MISP_URL'/misp_url\ =\ 'https:\/\/localhost'/g" /usr/local/src/mail_to_misp/mail_to_misp_config.py + $SUDO_CMD sed -i "s/^misp_key\ =\ 'YOUR_KEY_HERE'/misp_key\ =\ '${AUTH_KEY}'/g" /usr/local/src/mail_to_misp/mail_to_misp_config.py +} + +ssdeep () { + debug "Install ssdeep 2.14.1" + cd /usr/local/src + $SUDO_CMD wget https://github.com/ssdeep-project/ssdeep/releases/download/release-2.14.1/ssdeep-2.14.1.tar.gz + $SUDO_CMD tar zxvf ssdeep-2.14.1.tar.gz + cd ssdeep-2.14.1 + $SUDO_CMD ./configure --datadir=/usr --prefix=/usr --localstatedir=/var --sysconfdir=/etc + $SUDO_CMD make + sudo make install + + #installing ssdeep_php + sudo pecl channel-update pecl.php.net + sudo pecl install ssdeep + + # You should add "extension=ssdeep.so" to mods-available - Check /etc/php for your current version + echo "extension=ssdeep.so" | sudo tee ${PHP_ETC_BASE}/mods-available/ssdeep.ini + sudo phpenmod ssdeep + sudo service apache2 restart +} + +# viper-web is broken ATM +# Main Viper install function +viper () { + export PATH=$PATH:/home/misp/.local/bin + debug "Installing Viper dependencies" + cd /usr/local/src/ + sudo apt-get install \ + libssl-dev swig python3-ssdeep p7zip-full unrar-free sqlite python3-pyclamd exiftool radare2 \ + python3-magic python3-sqlalchemy python3-prettytable libffi-dev libfreetype6-dev libpng-dev -qy + if [[ -f "/etc/debian_version" ]]; then + if [[ "$(cat /etc/debian_version)" == "9.9" ]]; then + sudo apt-get install libpython3.5-dev -qy + fi + fi + echo "Cloning Viper" + false; while [[ $? -ne 0 ]]; do $SUDO_CMD git clone https://github.com/viper-framework/viper.git; done + false; while [[ $? -ne 0 ]]; do $SUDO_CMD git clone https://github.com/viper-framework/viper-web.git; done + sudo chown -R $MISP_USER:$MISP_USER viper + sudo chown -R $MISP_USER:$MISP_USER viper-web + cd viper + echo "Creating virtualenv" + $SUDO_CMD virtualenv -p python3 venv + echo "Submodule update" + # TODO: Check for current user install permissions + $SUDO_CMD git submodule update --init --recursive + echo "pip install deps" + $SUDO_CMD ./venv/bin/pip install pefile olefile jbxapi Crypto pypdns pypssl r2pipe pdftools virustotal-api SQLAlchemy PrettyTable python-magic scrapy lief + $SUDO_CMD ./venv/bin/pip install . + echo 'update-modules' |/usr/local/src/viper/venv/bin/viper + cd /usr/local/src/viper-web + $SUDO_CMD sed -i '1 s/^.*$/\#!\/usr\/local\/src\/viper\/venv\/bin\/python/' viper-web + $SUDO_CMD /usr/local/src/viper/venv/bin/pip install -r requirements.txt + echo "Launching viper-web" + $SUDO_CMD /usr/local/src/viper-web/viper-web -p 8888 -H 0.0.0.0 & + echo 'PATH="/home/misp/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/local/src/viper:/var/www/MISP/app/Console"' |sudo tee -a /etc/environment + echo ". /etc/environment" >> /home/${MISP_USER}/.profile + + # TODO: Perms, MISP_USER_HOME, nasty hack cuz Kali on R00t + if [ -f /home/${MISP_USER}/.viper/viper.conf ]; then + VIPER_HOME="/home/${MISP_USER}/.viper" + else + VIPER_HOME="${HOME}/.viper" + fi + + echo "Setting misp_url/misp_key" + $SUDO_CMD sed -i "s/^misp_url\ =/misp_url\ =\ http:\/\/localhost/g" ${VIPER_HOME}/viper.conf + $SUDO_CMD sed -i "s/^misp_key\ =/misp_key\ =\ $AUTH_KEY/g" ${VIPER_HOME}/viper.conf + # Reset admin password to: admin/Password1234 + echo "Fixing admin.db with default password" + VIPER_COUNT=0 + while [ "$(sudo sqlite3 ${VIPER_HOME}/admin.db 'UPDATE auth_user SET password="pbkdf2_sha256$100000$iXgEJh8hz7Cf$vfdDAwLX8tko1t0M1TLTtGlxERkNnltUnMhbv56wK/U="'; echo $?)" -ne "0" ]; do + # FIXME This might lead to a race condition, the while loop is sub-par + sudo chown $MISP_USER:$MISP_USER ${VIPER_HOME}/admin.db + echo "Updating viper-web admin password, giving process time to start-up, sleeping 5, 4, 3,…" + sleep 6 + VIPER_COUNT=$[$VIPER_COUNT+1] + if [[ "$VIPER_COUNT" > '10' ]]; then + echo "Something is wrong with updating viper. Continuing without db update." + break + fi + done + + # Add viper-web to rc.local to be started on boot + sudo sed -i -e '$i \sudo -u misp /usr/local/src/viper/viper-web -p 8888 -H 0.0.0.0 > /tmp/viper-web_rc.local.log &\n' /etc/rc.local +} + + +enableReposRHEL () { + sudo subscription-manager refresh + sudo subscription-manager repos --enable rhel-7-server-optional-rpms + sudo subscription-manager repos --enable rhel-7-server-extras-rpms + sudo subscription-manager repos --enable rhel-server-rhscl-7-rpms +} + +centosEPEL () { + # We need some packages from the Extra Packages for Enterprise Linux repository + sudo yum install epel-release -y + + # Since MISP 2.4 PHP 5.5 is a minimal requirement, so we need a newer version than CentOS base provides + # Software Collections is a way do to this, see https://wiki.centos.org/AdditionalResources/Repositories/SCL + sudo yum install centos-release-scl -y +} + +enableEPEL () { + sudo yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm -y +} + +yumInstallCoreDeps () { + # Install the dependencies: + sudo yum install gcc git zip rh-git218 \ + httpd24 \ + mod_ssl \ + rh-redis32 \ + rh-mariadb102 \ + libxslt-devel zlib-devel ssdeep-devel -y + + # Enable and start redis + sudo systemctl enable --now rh-redis32-redis.service + + WWW_USER="apache" + SUDO_WWW="sudo -H -u $WWW_USER" + RUN_PHP="/usr/bin/scl enable rh-php72" + PHP_INI="/etc/opt/rh/rh-php72/php.ini" + # Install PHP 7.2 from SCL, see https://www.softwarecollections.org/en/scls/rhscl/rh-php72/ + sudo yum install rh-php72 rh-php72-php-fpm rh-php72-php-devel \ + rh-php72-php-mysqlnd \ + rh-php72-php-mbstring \ + rh-php72-php-xml \ + rh-php72-php-bcmath \ + rh-php72-php-opcache \ + rh-php72-php-zip \ + rh-php72-php-gd -y + + # Python 3.6 is now available in RHEL 7.7 base + sudo yum install python3 python3-devel -y + + sudo systemctl enable --now rh-php72-php-fpm.service +} + +installCoreRHEL () { + # Download MISP using git in the $PATH_TO_MISP directory. + sudo mkdir -p $(dirname $PATH_TO_MISP) + sudo chown $WWW_USER:$WWW_USER $(dirname $PATH_TO_MISP) + cd $(dirname $PATH_TO_MISP) + $SUDO_WWW git clone https://github.com/MISP/MISP.git + cd $PATH_TO_MISP + ##$SUDO_WWW git checkout tags/$(git describe --tags `git rev-list --tags --max-count=1`) + # if the last shortcut doesn't work, specify the latest version manually + # example: git checkout tags/v2.4.XY + # the message regarding a "detached HEAD state" is expected behaviour + # (you only have to create a new branch, if you want to change stuff and do a pull request for example) + + # Fetch submodules + $SUDO_WWW git submodule update --init --recursive + # Make git ignore filesystem permission differences for submodules + $SUDO_WWW git submodule foreach --recursive git config core.filemode false + # Make git ignore filesystem permission differences + $SUDO_WWW git config core.filemode false + + # Create a python3 virtualenv + sudo pip3 install virtualenv + $SUDO_WWW python3 -m venv $PATH_TO_MISP/venv + sudo mkdir /usr/share/httpd/.cache + sudo chown $WWW_USER:$WWW_USER /usr/share/httpd/.cache + $SUDO_WWW $PATH_TO_MISP/venv/bin/pip install -U pip setuptools + + cd $PATH_TO_MISP/app/files/scripts + $SUDO_WWW git clone https://github.com/CybOXProject/python-cybox.git + $SUDO_WWW git clone https://github.com/STIXProject/python-stix.git + $SUDO_WWW git clone --branch master --single-branch https://github.com/lief-project/LIEF.git lief + $SUDO_WWW git clone https://github.com/CybOXProject/mixbox.git + + # If you umask is has been changed from the default, it is a good idea to reset it to 0022 before installing python modules + UMASK=$(umask) + umask 0022 + + cd $PATH_TO_MISP/app/files/scripts/python-cybox + $SUDO_WWW git config core.filemode false + $SUDO_WWW $PATH_TO_MISP/venv/bin/pip install . + + cd $PATH_TO_MISP/app/files/scripts/python-stix + $SUDO_WWW git config core.filemode false + $SUDO_WWW $PATH_TO_MISP/venv/bin/pip install . + + # install mixbox to accommodate the new STIX dependencies: + cd $PATH_TO_MISP/app/files/scripts/mixbox + $SUDO_WWW git config core.filemode false + $SUDO_WWW $PATH_TO_MISP/venv/bin/pip install . + + # install STIX2.0 library to support STIX 2.0 export: + cd $PATH_TO_MISP/cti-python-stix2 + $SUDO_WWW $PATH_TO_MISP/venv/bin/pip install . + + # install maec + $SUDO_WWW $PATH_TO_MISP/venv/bin/pip install -U maec + + # install zmq + $SUDO_WWW $PATH_TO_MISP/venv/bin/pip install -U zmq + + # install redis + $SUDO_WWW $PATH_TO_MISP/venv/bin/pip install -U redis + + # lief needs manual compilation + sudo yum install devtoolset-7 cmake3 cppcheck libcxx-devel -y + + cd $PATH_TO_MISP/app/files/scripts/lief + $SUDO_WWW git config core.filemode false + $SUDO_WWW mkdir build + cd build + $SUDO_WWW scl enable devtoolset-7 "bash -c 'cmake3 \ + -DLIEF_PYTHON_API=on \ + -DPYTHON_VERSION=3.6 \ + -DPYTHON_EXECUTABLE=$PATH_TO_MISP/venv/bin/python \ + -DLIEF_DOC=off \ + -DCMAKE_BUILD_TYPE=Release \ + ..'" + $SUDO_WWW make -j3 pyLIEF + + if [ $? == 2 ]; then + # In case you get "internal compiler error: Killed (program cc1plus)" + # You ran out of memory. + # Create some swap + sudo dd if=/dev/zero of=/var/swap.img bs=1024k count=4000 + sudo mkswap /var/swap.img + sudo swapon /var/swap.img + # And compile again + $SUDO_WWW make -j3 pyLIEF + sudo swapoff /var/swap.img + sudo rm /var/swap.img + fi + + # The following adds a PYTHONPATH to where the pyLIEF module has been compiled + echo $PATH_TO_MISP/app/files/scripts/lief/build/api/python |$SUDO_WWW tee $PATH_TO_MISP/venv/lib/python3.6/site-packages/lief.pth + + # install magic, pydeep + $SUDO_WWW $PATH_TO_MISP/venv/bin/pip install -U python-magic git+https://github.com/kbandla/pydeep.git plyara + + # install PyMISP + cd $PATH_TO_MISP/PyMISP + $SUDO_WWW $PATH_TO_MISP/venv/bin/pip install -U . + + # FIXME: Remove libfaup etc once the egg has the library baked-in + # BROKEN: This needs to be tested on RHEL/CentOS + ##sudo apt-get install cmake libcaca-dev liblua5.3-dev -y + cd /tmp + [[ ! -d "faup" ]] && $SUDO_CMD git clone https://github.com/stricaud/faup.git faup + [[ ! -d "gtcaca" ]] && $SUDO_CMD git clone https://github.com/stricaud/gtcaca.git gtcaca + sudo chown -R ${MISP_USER}:${MISP_USER} faup gtcaca + cd gtcaca + $SUDO_CMD mkdir -p build + cd build + $SUDO_CMD cmake .. && $SUDO_CMD make + sudo make install + cd ../../faup + $SUDO_CMD mkdir -p build + cd build + $SUDO_CMD cmake .. && $SUDO_CMD make + sudo make install + sudo ldconfig + + # Enable dependencies detection in the diagnostics page + # This allows MISP to detect GnuPG, the Python modules' versions and to read the PHP settings. + # The LD_LIBRARY_PATH setting is needed for rh-git218 to work + echo "env[PATH] = /opt/rh/rh-git218/root/usr/bin:/opt/rh/rh-redis32/root/usr/bin:/opt/rh/rh-php72/root/usr/bin:/usr/local/bin:/usr/bin:/bin" |sudo tee -a /etc/opt/rh/rh-php72/php-fpm.d/www.conf + sudo sed -i.org -e 's/^;\(clear_env = no\)/\1/' /etc/opt/rh/rh-php72/php-fpm.d/www.conf + sudo systemctl restart rh-php72-php-fpm.service + umask $UMASK +} + +installCake_RHEL () +{ + sudo chown -R $WWW_USER:$WWW_USER $PATH_TO_MISP + sudo mkdir /usr/share/httpd/.composer + sudo chown $WWW_USER:$WWW_USER /usr/share/httpd/.composer + cd $PATH_TO_MISP/app + # Update composer.phar (optional) + #EXPECTED_SIGNATURE="$(wget -q -O - https://composer.github.io/installer.sig)" + #$SUDO_WWW $RUN_PHP -- php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" + #$SUDO_WWW $RUN_PHP -- php -r "if (hash_file('SHA384', 'composer-setup.php') === '$EXPECTED_SIGNATURE') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" + #$SUDO_WWW $RUN_PHP "php composer-setup.php" + #$SUDO_WWW $RUN_PHP -- php -r "unlink('composer-setup.php');" + $SUDO_WWW $RUN_PHP "php composer.phar install" + + ## sudo yum install php-redis -y + sudo scl enable rh-php72 'pecl channel-update pecl.php.net' + sudo scl enable rh-php72 'yes no|pecl install redis' + echo "extension=redis.so" |sudo tee /etc/opt/rh/rh-php72/php.d/99-redis.ini + + sudo ln -s /usr/lib64/libfuzzy.so /usr/lib/libfuzzy.so + sudo scl enable rh-php72 'pecl install ssdeep' + echo "extension=ssdeep.so" |sudo tee /etc/opt/rh/rh-php72/php.d/99-ssdeep.ini + + # Install gnupg extension + sudo yum install gpgme-devel -y + sudo scl enable rh-php72 'pecl install gnupg' + echo "extension=gnupg.so" |sudo tee /etc/opt/rh/rh-php72/php.d/99-gnupg.ini + sudo systemctl restart rh-php72-php-fpm.service + + # If you have not yet set a timezone in php.ini + echo 'date.timezone = "Asia/Tokyo"' |sudo tee /etc/opt/rh/rh-php72/php.d/timezone.ini + + # Recommended: Change some PHP settings in /etc/opt/rh/rh-php72/php.ini + # max_execution_time = 300 + # memory_limit = 2048M + # upload_max_filesize = 50M + # post_max_size = 50M + for key in upload_max_filesize post_max_size max_execution_time max_input_time memory_limit + do + sudo sed -i "s/^\($key\).*/\1 = $(eval echo \${$key})/" $PHP_INI + done + sudo systemctl restart rh-php72-php-fpm.service + + # To use the scheduler worker for scheduled tasks, do the following: + sudo cp -fa $PATH_TO_MISP/INSTALL/setup/config.php $PATH_TO_MISP/app/Plugin/CakeResque/Config/config.php +} + +apacheConfig_RHEL () { + # Now configure your apache server with the DocumentRoot $PATH_TO_MISP/app/webroot/ + # A sample vhost can be found in $PATH_TO_MISP/INSTALL/apache.misp.centos7 + + sudo cp $PATH_TO_MISP/INSTALL/apache.misp.centos7.ssl /etc/httpd/conf.d/misp.ssl.conf + #sudo sed -i "s/SetHandler/\#SetHandler/g" /etc/httpd/conf.d/misp.ssl.conf + sudo rm /etc/httpd/conf.d/ssl.conf + sudo chmod 644 /etc/httpd/conf.d/misp.ssl.conf + sudo sed -i '/Listen 80/a Listen 443' /etc/httpd/conf/httpd.conf + + # If a valid SSL certificate is not already created for the server, create a self-signed certificate: + echo "The Common Name used below will be: ${OPENSSL_CN}" + # This will take a rather long time, be ready. (13min on a VM, 8GB Ram, 1 core) + if [[ ! -e "/etc/pki/tls/certs/dhparam.pem" ]]; then + sudo openssl dhparam -out /etc/pki/tls/certs/dhparam.pem 4096 + fi + sudo openssl genrsa -des3 -passout pass:xxxx -out /tmp/misp.local.key 4096 + sudo openssl rsa -passin pass:xxxx -in /tmp/misp.local.key -out /etc/pki/tls/private/misp.local.key + sudo rm /tmp/misp.local.key + sudo openssl req -new -subj "/C=${OPENSSL_C}/ST=${OPENSSL_ST}/L=${OPENSSL_L}/O=${OPENSSL_O}/OU=${OPENSSL_OU}/CN=${OPENSSL_CN}/emailAddress=${OPENSSL_EMAILADDRESS}" -key /etc/pki/tls/private/misp.local.key -out /etc/pki/tls/certs/misp.local.csr + sudo openssl x509 -req -days 365 -in /etc/pki/tls/certs/misp.local.csr -signkey /etc/pki/tls/private/misp.local.key -out /etc/pki/tls/certs/misp.local.crt + sudo ln -s /etc/pki/tls/certs/misp.local.csr /etc/pki/tls/certs/misp-chain.crt + cat /etc/pki/tls/certs/dhparam.pem |sudo tee -a /etc/pki/tls/certs/misp.local.crt + + sudo systemctl restart httpd.service + + # Since SELinux is enabled, we need to allow httpd to write to certain directories + sudo chcon -t httpd_sys_rw_content_t $PATH_TO_MISP/app/files + sudo chcon -t httpd_sys_rw_content_t $PATH_TO_MISP/app/files/terms + sudo chcon -t httpd_sys_rw_content_t $PATH_TO_MISP/app/files/scripts/tmp + sudo chcon -t httpd_sys_rw_content_t $PATH_TO_MISP/app/Plugin/CakeResque/tmp + sudo chcon -t httpd_sys_script_exec_t $PATH_TO_MISP/app/Console/cake + sudo chcon -t httpd_sys_script_exec_t $PATH_TO_MISP/app/Console/worker/*.sh + sudo chcon -t httpd_sys_script_exec_t $PATH_TO_MISP/app/files/scripts/*.py + sudo chcon -t httpd_sys_script_exec_t $PATH_TO_MISP/app/files/scripts/*/*.py + sudo chcon -t httpd_sys_script_exec_t $PATH_TO_MISP/app/files/scripts/lief/build/api/python/lief.so + sudo chcon -t httpd_sys_script_exec_t $PATH_TO_MISP/app/Vendor/pear/crypt_gpg/scripts/crypt-gpg-pinentry + sudo chcon -R -t bin_t $PATH_TO_MISP/venv/bin/* + find $PATH_TO_MISP/venv -type f -name "*.so*" -or -name "*.so.*" | xargs sudo chcon -t lib_t + # Only run these if you want to be able to update MISP from the web interface + sudo chcon -R -t httpd_sys_rw_content_t $PATH_TO_MISP/.git + sudo chcon -R -t httpd_sys_rw_content_t $PATH_TO_MISP/app/tmp + sudo chcon -R -t httpd_sys_rw_content_t $PATH_TO_MISP/app/Lib + sudo chcon -R -t httpd_sys_rw_content_t $PATH_TO_MISP/app/Config + sudo chcon -R -t httpd_sys_rw_content_t $PATH_TO_MISP/app/webroot/img/orgs + sudo chcon -R -t httpd_sys_rw_content_t $PATH_TO_MISP/app/webroot/img/custom + sudo chcon -R -t httpd_sys_rw_content_t $PATH_TO_MISP/app/files/scripts/mispzmq +} + +firewall_RHEL () { + # Allow httpd to connect to the redis server and php-fpm over tcp/ip + sudo setsebool -P httpd_can_network_connect on + + # Allow httpd to send emails from php + sudo setsebool -P httpd_can_sendmail on + + # Enable and start the httpd service + sudo systemctl enable --now httpd.service + + # Open a hole in the iptables firewall + sudo firewall-cmd --zone=public --add-port=80/tcp --permanent + sudo firewall-cmd --zone=public --add-port=443/tcp --permanent + sudo firewall-cmd --reload +} + +# Main function to fix permissions to something sane +permissions_RHEL () { + sudo chown -R $WWW_USER:$WWW_USER $PATH_TO_MISP + ## ? chown -R root:$WWW_USER $PATH_TO_MISP + sudo find $PATH_TO_MISP -type d -exec chmod g=rx {} \; + sudo chmod -R g+r,o= $PATH_TO_MISP + ## **Note :** For updates through the web interface to work, apache must own the $PATH_TO_MISP folder and its subfolders as shown above, which can lead to security issues. If you do not require updates through the web interface to work, you can use the following more restrictive permissions : + sudo chmod -R 750 $PATH_TO_MISP + sudo chmod -R g+xws $PATH_TO_MISP/app/tmp + sudo chmod -R g+ws $PATH_TO_MISP/app/files + sudo chmod -R g+ws $PATH_TO_MISP/app/files/scripts/tmp + sudo chmod -R g+rw $PATH_TO_MISP/venv + sudo chmod -R g+rw $PATH_TO_MISP/.git + sudo chown $WWW_USER:$WWW_USER $PATH_TO_MISP/app/files + sudo chown $WWW_USER:$WWW_USER $PATH_TO_MISP/app/files/terms + sudo chown $WWW_USER:$WWW_USER $PATH_TO_MISP/app/files/scripts/tmp + sudo chown $WWW_USER:$WWW_USER $PATH_TO_MISP/app/Plugin/CakeResque/tmp + sudo chown -R $WWW_USER:$WWW_USER $PATH_TO_MISP/app/Config + sudo chown -R $WWW_USER:$WWW_USER $PATH_TO_MISP/app/tmp + sudo chown -R $WWW_USER:$WWW_USER $PATH_TO_MISP/app/webroot/img/orgs + sudo chown -R $WWW_USER:$WWW_USER $PATH_TO_MISP/app/webroot/img/custom +} + +logRotation_RHEL () { + # MISP saves the stdout and stderr of its workers in $PATH_TO_MISP/app/tmp/logs + # To rotate these logs install the supplied logrotate script: + + sudo cp $PATH_TO_MISP/INSTALL/misp.logrotate /etc/logrotate.d/misp + sudo chmod 0640 /etc/logrotate.d/misp + + # Now make logrotate work under SELinux as well + # Allow logrotate to modify the log files + sudo semanage fcontext -a -t httpd_sys_rw_content_t "$PATH_TO_MISP(/.*)?" + sudo semanage fcontext -a -t httpd_log_t "$PATH_TO_MISP/app/tmp/logs(/.*)?" + sudo chcon -R -t httpd_log_t $PATH_TO_MISP/app/tmp/logs + # Impact of the following: ?!?!?!!?111 + ##sudo restorecon -R $PATH_TO_MISP + + # Allow logrotate to read /var/www + sudo checkmodule -M -m -o /tmp/misplogrotate.mod $PATH_TO_MISP/INSTALL/misplogrotate.te + sudo semodule_package -o /tmp/misplogrotate.pp -m /tmp/misplogrotate.mod + sudo semodule -i /tmp/misplogrotate.pp +} + +configMISP_RHEL () { + # There are 4 sample configuration files in $PATH_TO_MISP/app/Config that need to be copied + $SUDO_WWW cp -a $PATH_TO_MISP/app/Config/bootstrap.default.php $PATH_TO_MISP/app/Config/bootstrap.php + $SUDO_WWW cp -a $PATH_TO_MISP/app/Config/database.default.php $PATH_TO_MISP/app/Config/database.php + $SUDO_WWW cp -a $PATH_TO_MISP/app/Config/core.default.php $PATH_TO_MISP/app/Config/core.php + $SUDO_WWW cp -a $PATH_TO_MISP/app/Config/config.default.php $PATH_TO_MISP/app/Config/config.php + + echo " 'Database/Mysql', + //'datasource' => 'Database/Postgres', + 'persistent' => false, + 'host' => '$DBHOST', + 'login' => '$DBUSER_MISP', + 'port' => 3306, // MySQL & MariaDB + //'port' => 5432, // PostgreSQL + 'password' => '$DBPASSWORD_MISP', + 'database' => '$DBNAME', + 'prefix' => '', + 'encoding' => 'utf8', + ); + }" | $SUDO_WWW tee $PATH_TO_MISP/app/Config/database.php + + # Configure the fields in the newly created files: + # config.php : baseurl (example: 'baseurl' => 'http://misp',) - don't use "localhost" it causes issues when browsing externally + # core.php : Uncomment and set the timezone: `// date_default_timezone_set('UTC');` + # database.php : login, port, password, database + # DATABASE_CONFIG has to be filled + # With the default values provided in section 6, this would look like: + # class DATABASE_CONFIG { + # public $default = array( + # 'datasource' => 'Database/Mysql', + # 'persistent' => false, + # 'host' => 'localhost', + # 'login' => 'misp', // grant usage on *.* to misp@localhost + # 'port' => 3306, + # 'password' => 'XXXXdbpasswordhereXXXXX', // identified by 'XXXXdbpasswordhereXXXXX'; + # 'database' => 'misp', // create database misp; + # 'prefix' => '', + # 'encoding' => 'utf8', + # ); + #} + + # Important! Change the salt key in $PATH_TO_MISP/app/Config/config.php + # The admin user account will be generated on the first login, make sure that the salt is changed before you create that user + # If you forget to do this step, and you are still dealing with a fresh installation, just alter the salt, + # delete the user from mysql and log in again using the default admin credentials (admin@admin.test / admin) + + # If you want to be able to change configuration parameters from the webinterface: + sudo chown $WWW_USER:$WWW_USER $PATH_TO_MISP/app/Config/config.php + sudo chcon -t httpd_sys_rw_content_t $PATH_TO_MISP/app/Config/config.php + + # Generate a GPG encryption key. + cat >/tmp/gen-key-script <