Пример #1
0
def entropy_pool():
    # More Secure Random Entropy Pool (WIP)
    response = General.answer('Do you want More Secure Random Entropy Pool (WIP)?')
    check_attempt = 0
    if not response: return
    General.run_cmd('apt install rng-tools -y')
    General.run_cmd('echo "HRNGDEVICE=/dev/urandom" >> /etc/default/rng-tools')
    General.run_cmd('systemctl start rng-tools')
Пример #2
0
def proc():
    # Securing /proc | /proc mounted with hidepid=2 so users can only see information about their processes
    error = 'Fatal Error: PROC will have to be configured manually'
    f_ntp_conf = "/etc/ntp.conf"
    response = General.answer('Securing /proc so users can only see information about their processes?')


    if not response: return
    General.output_message('Configuring proc')

    if not os.path.exists(f_ntp_conf):
        General.error_message(f"could not localte the file {f_ntp_conf}. Exiting /proc configuration.")
        return

    with open(f_ntp_conf, 'a') as file:
        file.write(f'''
       # added by debian9_Hardening.py on {datetime.today().strftime('%Y-%m-%d')} @ {datetime.now().strftime(
            '%H:%M:%S')}       
       proc     /proc     proc     defaults,hidepid=2     0     0
               ''')
Пример #3
0
def auditd(EMAIL):

    f_audit_rules = '/etc/audit/audit.rules'
    f_audit_report = '/etc/cron.d/audit-report'

    if not General.answer('Do you want to install and configure auditd?'):
        return

    General.run_cmd('apt install auditd -y')
    General.output_message('Configuring Audit')
    General.run_cmd(
        f'wget -q https://raw.githubusercontent.com/Neo23x0/auditd/master/audit.rules -O {f_audit_rules}'
    )
    General.run_cmd('systemctl restart auditd')
    with open(f_audit_report, 'w') as file:
        file.write(f'''
        MAILTO={EMAIL}
        1 0   * * *     root  /sbin/aureport -k -ts yesterday 00:00:00 -te yesterday 23:59:59
                    ''')
Пример #4
0
def ntp():
    # installing NTP client and keeping server time in-sync

    error = 'Fatal Error: NTP will have to be configured manually'
    response = General.answer(
        'Install NTP client and keeping server time in-sinc ?')
    check_attempt = 0
    f_ntp_conf = '/etc/ntp.conf'
    if not response: return

    General.run_cmd('apt install ntp -y')

    if not os.path.exists(f_ntp_conf):
        General.error_message(
            f"could not localte the file {f_ntp_conf}. Exiting ntp configuration."
        )
        return

    General.output_message('Configuring NTP')
    with open(f_ntp_conf, 'w') as file:
        file.write(f'''
    # added by debian9_Hardening.py on {datetime.today().strftime('%Y-%m-%d')} @ {datetime.now().strftime('%H:%M:%S')}        
    driftfile /var/lib/ntp/ntp.drift
    statistics loopstats peerstats clockstats
    filegen loopstats file loopstats type day enable
    filegen peerstats file peerstats type day enable
    filegen clockstats file clockstats type day enable
    restrict -4 default kod notrap nomodify nopeer noquery limited
    restrict -6 default kod notrap nomodify nopeer noquery limited
    restrict 127.0.0.1
    restrict ::1
    restrict source notrap nomodify noquery
    pool pool.ntp.org iburst
            ''')

    General.run_cmd('service ntp restart')
Пример #5
0
def logwatch(EMAIL):
    # logwatch - system log analyzer and reporter

    f_logwatch = '/etc/cron.daily/00logwatch'

    if not General.answer('Do you want to install and configure logwatch?'):
        return

    General.run_cmd('apt install logwatch -y')
    with open(f_logwatch, 'w') as file:
        file.write(f'''
    #!/bin/bash

    #Check if removed-but-not-purged
    test -x /usr/share/logwatch/scripts/logwatch.pl || exit 0

    #execute
    /usr/sbin/logwatch --output mail --format html --mailto {EMAIL} --range yesterday --service all
    ''')

    General.warning_message(
        'Restarting firewall Maybe existing ssh connections will be stopped\n')
    General.run_cmd('ufw --force enable')
Пример #6
0
def lynis():

    if not General.answer(
            'Do you want install Lynis for upgrade your security level?'):
        return

    General.run_cmd('git clone https://github.com/CISOfy/lynis /opt/lynis')
    General.output_message('Lynis installed in > /opt/lynis')
    General.output_message('Running lynis scan..')
    output = str(
        subprocess.check_output(['./lynis', 'audit', 'system', '-Q'],
                                cwd="/opt/lynis",
                                stderr=subprocess.STDOUT), 'utf-8')
    General.output_message('Scan completed')
    output = General.remove_ansi_escape(output)
    lynis_output_sections = dict()
    output = output.split('[+]')

    for section in output:
        if ('------------------------------------') in section:
            section = section.split('------------------------------------')
            if section[0].strip() == 'Plugins (phase 2)':
                section[1] = section[1].split(
                    '================================================================================'
                )
                lynis_output_sections[
                    section[0].strip()] = section[1][0].strip()
                section[1][1] = section[1][1].split('Suggestions')
                section[1][1][1] = section[1][1][1].split(
                    '----------------------------')
                lynis_output_sections['Suggestions'] = section[1][1][1][1]
            else:
                lynis_output_sections[section[0].strip()] = section[1].strip()

    if ('Kernel Hardening' in lynis_output_sections):
        section = lynis_output_sections['Kernel Hardening']

        section = section.split('-')
        for line in section:
            line = line.strip()
            if '[ DIFFERENT ]' in line:
                line = line.split()
                for word in line:
                    if ')' in word:
                        word = word.strip('()exp: ')
                        if len(word) == 1:
                            word = word[0]
                        elif len(word) == 2:
                            word = word[1]
                        elif len(word) == 3:
                            word = word[2]
                        print(f'sysctl -w {line[0].strip()}={word}')
                        General.run_cmd(f'sysctl -w {line[0].strip()}={word}')

    print('\n\n\n')
    if ('Suggestions' in lynis_output_sections):
        suggestions = lynis_output_sections['Suggestions'].split('*')
        suggestions_list = []
        for suggestion in suggestions:
            suggestion = suggestion.split('\n')
            suggestions_list.append(suggestion[0].strip())

        if 'Protect rescue.service by using sulogin [BOOT-5260]' in suggestions_list:
            task = 'BOOT-5260'
            General.output_message(f'Configuring {task}')
            with open('/usr/lib/systemd/system/rescue.service', 'r') as file:
                lines = file.readlines()
                for index, line in enumerate(lines):
                    if 'ExecStart' in line.strip().split('='):
                        lines[index] = 'ExecStart=-/usr/sbin/sulogin'

            with open('/usr/lib/systemd/system/rescue.service', 'w') as f_w:

                for line in lines:
                    f_w.write(line)
            General.output_message(f'{task}')

        if 'Determine priority for available kernel update [KRNL-5788]' in suggestions_list:

            # https://phoenixnap.com/kb/how-to-update-kernel-ubuntu

            task = 'KRNL-5788'
            General.output_message(f'Configuring {task}')
            General.run_cmd('apt-get update')
            General.output_message('System updated')
            General.run_cmd('apt-get dist-upgrade')

        if 'Configure minimum password age in /etc/login.defs [AUTH-9286]' in suggestions_list or\
                'Configure maximum password age in /etc/login.defs [AUTH-9286]' in suggestions_list or \
                'Default umask in /etc/login.defs could be more strict like 027 [AUTH-9328]' in suggestions_list:
            task = 'AUTH-9286'
            General.change_lines(
                '/etc/login.defs',
                _1=['UMASK		022', 'UMASK		027\n'],
                _2=['PASS_MAX_DAYS	99999', 'PASS_MAX_DAYS   30\n'],
                _3=['PASS_MIN_DAYS	0', 'PASS_MIN_DAYS   1\n'],
                _4=['PASS_WARN_AGE   7', 'PASS_WARN_AGE   7\n'],
            )
            General.output_message(f'Configuring {task}')
        else:
            General.error_message(
                'Something went wrong, cannot analize lynis scan output')
Пример #7
0
def rkhunter(EMAIL):

    # Rootkit Detection With Rkhunter
    f_rkhunter_conf = '/etc/rkhunter.conf'
    if not General.answer('Do you want to install and configure rkhunter?'):
        return

    General.run_cmd('apt install rkhunter -y')
    General.error_message(
        '[ALERT] If this is the first installation select yes to the three questions you will be asked to answer '
    )
    time.sleep(5)
    General.output_message('Configuring rkhunter..')
    General.change_lines(
        f_rkhunter_conf,
        _1=['UPDATE_MIRRORS=0', 'UPDATE_MIRRORS=1\n'],
        _2=['MIRRORS_MODE=1', 'MIRRORS_MODE=0\n'],
        _3=['#MAIL-ON-WARNING=root', f'MAIL-ON-WARNING={EMAIL}\n'],
        _4=['#COPY_LOG_ON_ERROR=0', 'COPY_LOG_ON_ERROR=1\n'],
        _5=['#PKGMGR=NONE', 'PKGMGR=DPKG\n'],
        _6=['#PHALANX2_DIRTEST=0', 'PHALANX2_DIRTEST=1\n'],
        _7=['#USE_LOCKING=0', 'USE_LOCKING=1\n'],
        _8=[
            '#SHOW_SUMMARY_WARNINGS_NUMBER=0',
            'SHOW_SUMMARY_WARNINGS_NUMBER=1\n'
        ],
        _9=['WEB_CMD="/bin/false"', 'WEB_CMD=""\n'])
    subprocess.check_call(['dpkg-reconfigure', 'rkhunter'],
                          stderr=subprocess.STDOUT)
    General.run_cmd('rkhunter --propupd', 'rkhunter --update')
    General.output_message('Rkhunter Done')
Пример #8
0
def clamAv(EMAIL):
    # Anti-Virus Scanning With ClamAV

    f_clam_conf = '/etc/clamav/freshclam.conf'

    if not General.answer('Do you want to use ClamAV for Anti-virus Scanning with root permissions?'): return

    General.run_cmd('apt install clamav clamav-freshclam -y')
    General.change_lines(
        f_clam_conf,
        _1=[
            '# Check for new database 24 times a day',
            '# Check for new database 1 times a day\n'
        ],
        _2=[
            'Checks 24',
            'Checks 1\n'
        ]
    )
    General.run_cmd('freshclam -v')




    user = ''
    while True:
        user = General.input_message(
            "Using clamscan as root is dangerous because if a file is in fact a virus there is risk that it could use the root privileges.\n"
            "You can create another user by writing [U] \nPlease chose a user that can run clamscan"
        )
        if UsersConfig.user_exists(user): break
        if user.upper() == 'U':
            UsersConfig.create_users()
        else:
            General.error_message("User doesn't exists")
            General.output_message('For create a new user type [U]')


    dir_to_scan = ''
    all_directories_exists = False
    while not all_directories_exists:
        all_directories_exists = True
        dir_to_scan = General.input_message('Which direcotry should be scanned by clamAV? (ex. /var/www /var/vmail): ')
        for dir in dir_to_scan.split():
            if not os.path.exists(dir):
                General.error_message(f"The directory {dir} doesn't exists, select another path")
                all_directories_exists = False
    General.output_message('Configuration Anti-virus Scanning tools..')

    f_clam_daily = f'/home/{user}/clamscan_daily.sh'

    with open(f_clam_daily, 'w') as file:
        file.write(f'''
    #!/bin/bash
    LOGFILE="/var/log/clamav/clamav-$(date +'%Y-%m-%d').log";
    EMAIL_MSG="Please see the log file attached.";
    EMAIL_FROM="''' + EMAIL + '''";
    DIRTOSCAN="''' + dir_to_scan + '''";

    for S in ${DIRTOSCAN}; do
     DIRSIZE=$(du -sh "$S" 2>/dev/null | cut -f1);

     echo "Starting a daily scan of "$S" directory.
     Amount of data to be scanned is "$DIRSIZE".";

     clamscan -ri "$S" >> "$LOGFILE";

     # get the value of "Infected lines"
     MALWARE=$(tail "$LOGFILE"|grep Infected|cut -d" " -f3);

     # if the value is not equal to zero, send an email with the log file attached
     if [ "$MALWARE" -ne "0" ];then
     # using heirloom-mailx below
     echo "$EMAIL_MSG"|mail -A "$LOGFILE" -s "Malware Found" "$EMAIL_FROM";
    fi 
    done

    exit 0
                    ''')

    General.run_cmd('chmod 0755 /root/clamscan_daily.sh')
    General.run_cmd('ln /root/clamscan_daily.sh /etc/cron.daily/clamscan_daily')
    General.run_cmd('service clamav-freshclam start')
    if not General.answer("Do you want to run the virus scan on the given directories now? This can take some time"): return
    General.output_message('Running first scan for check if all is ok')
    subprocess.run(['clamscan', '-r', dir_to_scan])
Пример #9
0
def aide(EMAIL):
    # File/Folder Integrity Monitoring With AID

    f_aide = '/etc/default/aide'

    if not main.answer('Do you want Monitoring  File/Folder Integrity With AIDE?'): return

    main.run_cmd('apt install aide -y')
    main.output_message('Configuration File/Folder Monitoring tools..')
    main.change_lines(
        f_aide,
        _1=[
            'MAILTO=root',
            f'MAILTO={EMAIL}\n'
        ],
        _2=[
            '#CRON_DAILY_RUN=yes',
            'CRON_DAILY_RUN=yes\n'
        ]
    )

    main.output_message(
        "Aide, for work, needs to create a new database and install it"
        "\nThis process requires time..."
    )

    main.run_cmd_interactive("aideinit -y -f")
    main.run_cmd("cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db")
    main.run_cmd("update-aide.conf")
    main.run_cmd("cp /var/lib/aide/aide.conf.autogenerated /etc/aide/aide.conf")
Пример #10
0
- SSH KEYS SETUP ( not covered in the script ) : https://www.digitalocean.com/community/tutorials/how-to-set-up-ssh-keys-on-ubuntu-20-04
- ADDING USERS
"""

import sys
import os
import traceback

sys.path.insert(
    0, os.path.abspath(__file__ +
                       "/../../"))  # add the current module to sys.path

from SSLock import General, UsersConfig, Mail, SSHConfig, Nvidia, Ntp, Proc, EntropyPool, Ufw, Fail2Ban, Aide, ClamAv, Maldet, \
    RkHunter, Logwatch, Audit, Psad, Alerts, Lynis, WordpresServerSetup, WPVirtualHostSetup

if General.internet_on(): print("Internet connection active")
# Installing non present packages

# Checking if script runs as root
General.output_message('Script is running as root?...')
if os.geteuid() != 0:
    General.error_message(
        "You need to have root privileges to run this script.\nRe-run the script using 'sudo'. Exiting..."
    )
    exit()

General.output_message('YES')

# Store global informations
EMAIL_ENABLE = General.answer(
    "To receive notifications from the system and for the correct configuration of some tools, email and Exim4 will"
Пример #11
0
def autamated_email_allerts(EMAIL_ENABLE, EMAIL):

    f_exm_conf = '/etc/exim4/update-exim4.conf.conf'
    file_path_1 = '/etc/exim4/passwd.client'
    f_exim_localmacros = '/etc/exim4/exim4.conf.localmacros'
    f_exim_template = '/etc/exim4/exim4.conf.template'
    f_exim_autogenerated = '/var/lib/exim4/config.autogenerated'

    # if not EMAIL_ENABLE: return

    General.run_cmd('apt install exim4 openssl ca-certificates -y')
    General.output_message('Editing configuration files..')
    General.run_cmd('chown root:Debian-exim /etc/exim4/passwd.client')
    General.run_cmd('chown 640 /etc/exim4/passwd.client')

    if not os.path.exists('/usr/share/doc/exim4-base/examples/exim-gencert'):
        General.run_cmd('bash /usr/share/doc/exim4-base/examples/exim-gencert')

    with open(f_exim_localmacros, 'w') as file:
            file.write('''
    MAIN_TLS_ENABLE = 1
    REMOTE_SMTP_SMARTHOST_HOSTS_REQUIRE_TLS = *
    TLS_ON_CONNECT_PORTS = 465
    REQUIRE_PROTOCOL = smtps
    IGNORE_SMTP_LINE_LENGTH_LIMIT = true
                ''')

    General.run_cmd(f'wget -q https://raw.githubusercontent.com/TheeBlind/Exim4_Gmail_conf/master/nconf/config.autogenerated -O {f_exim_autogenerated}')
    General.run_cmd(f'wget -q https://raw.githubusercontent.com/TheeBlind/Exim4_Gmail_conf/master/nconf/exim4.conf.template -O {f_exim_template}')
    General.run_cmd(f'wget -q https://raw.githubusercontent.com/TheeBlind/Exim4_Gmail_conf/master/nconf/update-exim4.conf.conf -O {f_exm_conf}')
    local_ip = subprocess.check_output(['hostname', '-I'], stderr=subprocess.STDOUT)
    local_ip = str(local_ip).strip("b'n\\ ")
    General.change_lines(f_exim_template,
                         _1=[
            '* changeme Ffrs',
            f"* {local_ip}@{General.USER}.{General.HOSTNAME} Ffrs\n"
        ])

    General.change_lines(
        f_exim_autogenerated,
            _1=[
            '* chengeme Ffrs',
            f"* {local_ip}@{General.USER}.{General.HOSTNAME} Ffrs\n"
        ])
    General.run_cmd('update-exim4.conf')
    General.run_cmd('systemctl restart exim4')

    General.run_cmd(f"""echo "Automatic SSlock notification test, if you received this mail, you can go ahead in the setup. if you have received this mail by mistake, please delete it." | mail -s 'Test!' {EMAIL}""")
    General.output_message('Mail setup Completed')
    response = General.answer(f'We have sent a test mail to the address {EMAIL}. Have you recived it?\nCheck the spam folder!')
    if not response:
        General.output_message(
"""
If you received no mail you can check the exim4 logs for investigate about the problem
> sudo cat /var/log/exim4/mainlog
> sudo cat /var/log/exim4/paniclog
> check if something is blocking port 25 out
""")
        time.sleep(5)
Пример #12
0
def fail2ban(EMAIL):

    # Application Intrusion Detection And Prevention With Fail2Ban
    f_f2b_jail = '/etc/fail2ban/jail.local'
    if not General.answer('Do you want to install and configure Fail2Ban?'):
        return

    General.run_cmd('apt install fail2ban -y')
    General.run_cmd('systemctl start fail2ban', 'systemctl enable fail2ban')
    General.output_message("fail2ban is running")

    with open(f_f2b_jail, 'w') as file:
        lan_segment = General.input_message(
            'What is you lan segment? (ex. 192.168.1.1/24) :')
        file.write(f'''
    [DEFAULT]
    # the IP address range we want to ignore
    ignoreip = 127.0.0.1/8 {lan_segment}

    # who to send e-mail to
    destemail = {EMAIL}

    # who is the email from
    sender = {General.USER}.{General.HOSTNAME}.{EMAIL}

    # since we're using exim4 to send emails
    mta = mail

    # get email alerts
    action = %(action_mwl)s
                ''')

    General.output_message('Configuring Intrusion and detection tools')

    if not General.answer(
            'Do You need a jail for SSH that tells fail2ban to look at SSH logs and use ufw to ban/unban IPs ?'
    ):
        return

    with open(f_f2b_jail, 'a') as jail_file:
        jail_file.write('''
    [sshd]
    enabled = true
    banaction = ufw
    port = ssh
    filter = sshd
    logpath = %(sshd_log)s
    maxretry = 5
    ''')

    General.run_cmd('fail2ban-client start', 'fail2ban-client reload')
    General.output_message("Tools reloaded")
    General.run_cmd('systemctl restart fail2ban')
Пример #13
0
def alerts(EMAIL):
    # Automatic Security Updates and Alerts

    f_alerts_upgrades = '/etc/apt/apt.conf.d/51myunattended-upgrades'
    f_alerts_conf = '/etc/apticron/apticron.conf'

    if not General.answer(
            'Do you want Automatic Security Updates and Alerts? (unattended-upgrades)'
    ):
        return

    General.run_cmd(
        'apt install unattended-upgrades apt-listchanges apticron -y')

    General.output_message('Configuring Security Updates and Alerts..')
    with open(f_alerts_upgrades, 'w') as file:
        file.write('''
    // Enable the update/upgrade script (0=disable)
    APT::Periodic::Enable "1";

    // Do "apt-get update" automatically every n-days (0=disable)
    APT::Periodic::Update-Package-Lists "1";

    // Do "apt-get upgrade --download-only" every n-days (0=disable)
    APT::Periodic::Download-Upgradeable-Packages "1";

    // Do "apt-get autoclean" every n-days (0=disable)
    APT::Periodic::AutocleanInterval "7";

    // Send report mail to root
    //     0:  no report             (or null string)
    //     1:  progress report       (actually any string)
    //     2:  + command outputs     (remove -qq, remove 2>/dev/null, add -d)
    //     3:  + trace on    APT::Periodic::Verbose "2";
    APT::Periodic::Unattended-Upgrade "1";

    // Automatically upgrade packages from these
    Unattended-Upgrade::Origins-Pattern {
          "o=Debian,a=stable";
          "o=Debian,a=stable-updates";
          "origin=Debian,codename=${distro_codename},label=Debian-Security";
    };

    // You can specify your own packages to NOT automatically upgrade here
    Unattended-Upgrade::Package-Blacklist {
    };

    // Run dpkg --force-confold --configure -a if a unclean dpkg state is detected to true to ensure that updates get installed even when the system got interrupted during a previous run
    Unattended-Upgrade::AutoFixInterruptedDpkg "true";

    //Perform the upgrade when the machine is running because we wont be shutting our server down often
    Unattended-Upgrade::InstallOnShutdown "false";

    // Send an email to this address with information about the packages upgraded.
    Unattended-Upgrade::Mail "''' + EMAIL + '''";

    // Always send an e-mail
    Unattended-Upgrade::MailOnlyOnError "false";

    // Remove all unused dependencies after the upgrade has finished
    Unattended-Upgrade::Remove-Unused-Dependencies "true";

    // Remove any new unused dependencies after the upgrade has finished
    Unattended-Upgrade::Remove-New-Unused-Dependencies "true";

    // Automatically reboot WITHOUT CONFIRMATION if the file /var/run/reboot-required is found after the upgrade.
    Unattended-Upgrade::Automatic-Reboot "true";

    // Automatically reboot even if users are logged in.
    Unattended-Upgrade::Automatic-Reboot-WithUsers "true";
                    ''')

    with open(f_alerts_conf, 'w') as file:
        file.write(f'''
    EMAIL="{EMAIL}"
    NOTIFY_NO_UPDATES="1"           
                ''')
Пример #14
0
def wpVirtualHost(EMAIL):

    ####################################################
    # SETUP APACHE VIRTUALHOST ( FOR MULTIPLE WEBSITES )
    ####################################################

    General.output_message("-- Creation of apache2 Virtual Host --")
    DOMAIN_FULL = General.input_message("Insert a domain[ domain.(com/.it/.org/etc..) ] ")
    DOMAIN = '.'.join(DOMAIN_FULL.split(".")[:-1]) if len(DOMAIN_FULL.split(".")) > 2 else DOMAIN_FULL.split(".")[0]
    General.run_cmd(f"mkdir /var/www/{DOMAIN}")  # create a directory for the virtual host
    General.run_cmd(f"chown -R $USER:$USER /var/www/{DOMAIN}")  # assign the directory to $USER
    General.run_cmd(f"chmod -R 755 /var/www/{DOMAIN}")  # be sure that permissions are correct

    f_apache_domain_conf = f'/etc/apache2/sites-available/{DOMAIN}.conf'
    with open(f_apache_domain_conf, 'w') as file:
        file.write(
"""
<VirtualHost *:80>
    ServerAdmin """ + EMAIL + """
    ServerName """ + DOMAIN_FULL + """
    ServerAlias www.""" + DOMAIN_FULL + """
    DocumentRoot /var/www/""" + DOMAIN + """
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost> 
<Directory /var/www/""" + DOMAIN + """/>
    AllowOverride All
</Directory>
""")

    General.run_cmd(f"sudo a2ensite {DOMAIN}.conf")  # Enable the new configuration ( you can enable as many different configs as you want )
    General.run_cmd(f"sudo a2dissite 000-default.conf")  # Disable the default configuration
    General.run_cmd("sudo a2enmod rewrite")
    General.run_cmd("sudo systemctl restart apache2")  # restart apache
    # Test apache configs
    # sudo apachectl -t -D DUMP_VHOSTS
    # sudo apachectl configtest

    # Add SSL to apache virtualhost
    General.run_cmd("apt install certbot python3-certbot-apache -y")
    General.run_cmd("mkdir /var/lib/letsencrypt")
    General.run_cmd("chmod -R o+rx /var/lib/letsencrypt")
    General.output_message("""
-- Certbot configuration --
If questions are promp type the following answers:
> Terms of service: A
> Share mail address: N
> redirect HTTP traffic to HTTPS: 2
> If the validation of the domain go wrong just exit the script and investigate on the problem.
  You can restart the script on the same domain and it will work correctly""")
    General.run_cmd_interactive(f"sudo certbot --apache -d {DOMAIN_FULL} -d www.{DOMAIN_FULL}") # runs interactive certbot configuration
    General.output_message('If certbot failed chek the apache2 logs ( Ubuntu: /var/log/apache2/error.log ) ')

    # wordpress virtualhost setup
    General.output_message("-- Configuring wordpress Db --")
    DB_NAME = General.input_message("Database Name ")
    DB_USER = General.input_message("Database User Name ")

    DB_USER_PASS = General.sensitive_input_message("Database User Password ")

    General.run_cmd(
        f""" mysql -e " CREATE DATABASE {DB_NAME} DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci; " """,
        f""" mysql -e " CREATE USER '{DB_USER}'@'localhost' IDENTIFIED BY '{DB_USER_PASS}'; " """,
        f""" mysql -e " GRANT ALL PRIVILEGES ON {DB_NAME}.* TO '{DB_USER}'@'localhost'; " """,
        """ mysql -e " FLUSH PRIVILEGES; " """
    )

    if(not os.path.exists('/tmp/wordpress')):
        General.output_message("\n-- WORDPRESS DOWNLOAD --")
        General.run_cmd("wget -P /tmp 'https://wordpress.org/latest.tar.gz' ")
        General.run_cmd("tar -C /tmp -zxvf /tmp/latest.tar.gz")
        General.run_cmd("touch /tmp/wordpress/.htaccess")
        General.run_cmd("cp /tmp/wordpress/wp-config-sample.php /tmp/wordpress/wp-config.php")
        General.run_cmd("mkdir /tmp/wordpress/wp-content/upgrade")

    General.run_cmd(f"cp -a /tmp/wordpress/. /var/www/{DOMAIN}")
    General.run_cmd(f"chown -R www-data:www-data /var/www/{DOMAIN}")
    General.run_cmd("find /var/www/" + DOMAIN + "/ -type d -exec chmod 750 {} \;")
    General.run_cmd("find /var/www/" + DOMAIN + "/ -type f -exec chmod 640 {} \;")
    f_wp_domain_config = f"/var/www/{DOMAIN}/wp-config.php"

    General.run_cmd("apt install curl -y")

    OUTPUT_KEYS = General.output_run_cmd("curl -s https://api.wordpress.org/secret-key/1.1/salt/").decode(
        "utf-8").split("');")
    for key in OUTPUT_KEYS:
        if key.strip() == '': OUTPUT_KEYS.remove(key)
    OUTPUT_KEYS_DICT = dict()
    for index, key in enumerate(OUTPUT_KEYS):
        index += 1
        OUTPUT_KEYS_DICT["_" + str(index)] = [
            '( '.join(key.split(",")[0].split('(')).strip() + ',',
            key.strip() + "');\n"
        ]
    General.change_lines(
        f_wp_domain_config,
        **OUTPUT_KEYS_DICT
    )
    General.change_lines(
        f_wp_domain_config,
        _1=["define( 'DB_NAME',", f"define( 'DB_NAME', '{DB_NAME}');"],
        _2=["define( 'DB_USER',", f"define( 'DB_USER', '{DB_USER}');"],
        _3=["define( 'DB_PASSWORD',", f"define( 'DB_PASSWORD', '{DB_USER_PASS}');"],
    )
    General.insert_lines(
        f_wp_domain_config,
        "define( 'FS_METHOD', 'direct');",
        index_surplus=1,
        anchor_line=f"define( 'DB_PASSWORD', 'DB_USER_PASS');"
    )


    General.output_message('-- INFO --')
    General.output_message(f" > Finish the WP GUI installation going to https://{DOMAIN}")
    General.output_message(" > We did a setup for SSL certificate with Let’s Encrypt CERTBOT, THis Certificate expire")
    General.output_message("   after 90 days, A Bot that automatic does the renewal is also installed, Check that ")
    General.output_message("   it is working by typing 'sudo systemctl status certbot.timer' ")
    General.output_message(" > For check that PHP was installed sucesfully and it is working correctly do this steps: ")
    General.output_message(f"    - sudo nano /var/www/{DOMAIN}/info.php")
    General.output_message("    - Add the following line to the file '<?php phpinfo(); ?>' ")
    General.output_message(f"    - Visit this link 'http://{DOMAIN_FULL}/info.php'")
    General.output_message(f"    If a table with php information was displayed and nothing went wrong remove the file\n"
                           f"    previously created 'sudo rm /var/www/{DOMAIN}/info.php'")
    time.sleep(5)
Пример #15
0
def setup(EMAIL):
    f_apache2_dir_conf = '/etc/apache2/mods-enabled/dir.conf'
    if not General.answer('Do you want to setup a wordpress server?'): return
    General.output_message("-- Starting LMAP Stack SETUP --")
    # Download LAMP Stack LINUX - APACHE - MYSQL - PHP

    # APACHE DOWNLOAD
    General.run_cmd('apt install apache2 -y')
    General.run_cmd('ufw allow in "Apache Full"')

    # MYSQL DOWNLOAD
    General.run_cmd('apt install mysql-server -y')
    # run mysql_secure_installation ( automated )
    General.output_message("\n-- MYSQL SETUP --")
    MYSQL_ROOT_PASS = General.sensitive_input_message(
        "[MYSQL] Set root password")

    # Make sure that NOBODY can access the server without a password
    # Kill the anonymous users
    # Because our hostname varies we'll use some Bash magic here.
    # Kill off the demo database
    # Make our changes take effect
    # Any subsequent tries to run queries this way will get access denied because lack of usr/pwd param

    General.run_cmd(
        f""" mysql -e " ALTER USER 'root'@'localhost' IDENTIFIED BY '{MYSQL_ROOT_PASS}'; " """,
        """ mysql -e " DELETE FROM mysql.user WHERE user='' AND host='localhost'; " """,
        """ mysql -e " DROP USER ''@'$(hostname)'; " """,
        """ mysql -e " DROP DATABASE test; " """,
        """ mysql -e " FLUSH PRIVILEGES; " """)

    # PHP DOWNLOAD
    # php.ini : /etc/php/7.4/apache2/php.ini
    General.output_message("\n-- PHP SETUP --")
    General.run_cmd("apt install php libapache2-mod-php php-mysql -y")
    with open(f_apache2_dir_conf, 'w') as file:
        file.write("""
<IfModule mod_dir.c>
    DirectoryIndex index.php index.html index.cgi index.pl index.xhtml index.htm
</IfModule>
""")
    General.run_cmd("sudo apt update -y")
    General.run_cmd(
        "sudo apt install php-curl php-gd php-mbstring php-xml php-xmlrpc php-soap php-intl php-zip -y"
    )
    General.run_cmd("sudo systemctl restart apache2")
    General.run_cmd("systemctl restart apache2")

    # WORDPRESS DOWNLOAD
    General.output_message("\n-- WORDPRESS DOWNLOAD --")
    General.run_cmd("wget -P /tmp 'https://wordpress.org/latest.tar.gz' ")
    General.run_cmd("tar -C /tmp -zxvf /tmp/latest.tar.gz")
    General.run_cmd("touch /tmp/wordpress/.htaccess")
    General.run_cmd(
        "cp /tmp/wordpress/wp-config-sample.php /tmp/wordpress/wp-config.php")
    General.run_cmd("mkdir /tmp/wordpress/wp-content/upgrade")
Пример #16
0
def ssh(SSH_ENABLE, EMAIL_ENABLE, SSH_PORT, EMAIL):

    f_ssh_config = '/etc/ssh/sshd_config'
    if not SSH_ENABLE or not EMAIL_ENABLE: return
    General.run_cmd("apt install ssh -y")
    options_list = [
        'Port', 'ClientAliveCountMax', 'ClientAliveInterval', 'LoginGraceTime',
        'MaxAuthTries', 'MaxSessions', 'MaxStartups', 'PasswordAuthentication',
        'AllowGroups', 'PermitRootLogin'
    ]

    for option in options_list:
        status1 = General.check_lines_in_file(f_ssh_config, option)
        status2 = General.check_lines_in_file(f_ssh_config, '#' + option)
        if not status1 and not status2:
            with open(f_ssh_config, 'a') as file:
                file.write(option + '\n')

    generate_key = General.answer('Do you want enable ssh for some users?')
    if generate_key:
        generate_root_key = General.answer(
            f'Do you also want to enable ssh for Current user [{General.USER}] ? '
        )
        if generate_root_key:
            key_path = f'/{General.USER}/.ssh/id_rsa'
            if not os.path.exists(key_path):
                key_pass = General.input_message(
                    'Enter a passphrase for the key (empty for no passphrase):'
                )
                General.run_cmd(
                    f'ssh-keygen -C "{EMAIL}" -b 2048 -t rsa -f {key_path} -q -N "{key_pass}"'
                )
                General.warning_message(
                    f'[ALERT] your private key has been sent by email to {EMAIL}, please retrieve and save it, after destroy the email\n'
                )
                time.sleep(3)
                General.run_cmd(
                    f'echo " DANGER here you will find your private key attached for your device, destroy this mail and its contents instantly." | mail -s "Private key for: {General.USER} on {General.HOSTNAME}" {EMAIL} -A {key_path}'
                )
            else:
                General.error_message(
                    'A key pair for the current user yet exists')
        else:
            General.change_lines(
                f_ssh_config,
                _19=['#PermitRootLogin yes', 'PermitRootLogin no\n'],
                _20=['PermitRootLogin yes', 'PermitRootLogin no\n'])

        General.run_cmd('groupadd sshusers')
        General.output_message("which user do you want to have ssh enabled?")
        while True:
            user = General.input_message("User to enable ssh  [S to skip]: ")
            if user.upper() in ['S', 'SKIP']: break

            if not UsersConfig.user_exists(user):
                General.error_message("User doesn't exists")
            else:
                General.run_cmd(f'usermod -a -G sshusers {user}')
                generate_key_for_user = General.answer(
                    f'[{user}] Do you want a ssh key pair for this user?')
                if generate_key_for_user:
                    key_path = f'/home/{user}/.ssh/id_rsa'
                    if not os.path.exists(f'/home/{user}/.ssh'):
                        os.mkdir(f'/home/{user}/.ssh')
                    if not os.path.exists(key_path):
                        key_pass = General.input_message(
                            'Enter a passphrase for the key (empty for no passphrase):'
                        )
                        General.run_cmd(
                            f'ssh-keygen -C "{EMAIL}" -b 2048 -t rsa -f {key_path} -q -N "{key_pass}"'
                        )
                        General.warning_message(
                            f'[ALERT] your private key has been sent by email to {EMAIL}, please retrieve and save it, after destroy the email\n'
                        )
                        time.sleep(3)
                        General.run_cmd(
                            f'echo " DANGER here you will find your private key attached for your device, destroy this mail and its contents instantly." | mail -s "Private key for: {user} on {General.HOSTNAME}" {EMAIL} -A {key_path}'
                        )
                    else:
                        General.error_message(
                            f'A key pair for the user "{user}" yet exists')

        General.change_lines(
            f_ssh_config,
            _1=['Port', f"Port {SSH_PORT}\n"],
            _2=['#Port', f"Port {SSH_PORT}\n"],
            _3=['ClientAliveCountMax', "ClientAliveCountMax 0\n"],
            _4=['#ClientAliveCountMax', "ClientAliveCountMax 0\n"],
            _5=['ClientAliveInterval', "ClientAliveInterval 300\n"],
            _6=['#ClientAliveInterval', "ClientAliveInterval 300\n"],
            _7=['LoginGraceTime', "LoginGraceTime 30\n"],
            _8=['#LoginGraceTime', "LoginGraceTime 30\n"],
            _9=['MaxAuthTries', "MaxAuthTries 2\n"],
            _10=['#MaxAuthTries', "MaxAuthTries 2\n"],
            _11=['MaxSessions', "MaxSessions 2\n"],
            _12=['#MaxSessions', "MaxSessions 2\n"],
            _13=['MaxStartups', "MaxStartups 2\n"],
            _14=['#MaxStartups', "MaxStartups 2\n"],
            _15=['PasswordAuthentication', "PasswordAuthentication no\n"],
            _16=['#PasswordAuthentication', "PasswordAuthentication no\n"],
            _17=['AllowGroups', "AllowGroups sshusers\n"],
            _18=['#AllowGroups', "AllowGroups sshusers\n"],
        )

        General.output_message('These changes have been made to the config')
        General.warning_message('/etc/ssh/sshd_config')
        General.output_message(
            f'''If u need more advanced options feel free to modify it.
    - Port                      {SSH_PORT};
    - ClientAliveCountMax                0;
    - ClientAliveInterval              300;
    - LoginGraceTime                    30;
    - MaxAuthTries                       2;
    - MaxSessions                        2;
    - MaxStartups                        2;
    - PasswordAuthentication            no;
    - AllowGroups                 sshusers;
    - PermitRootLogin                   no;
''')

        General.output_message(
            'removing all Diffie-Hellman keys that are less than 3072 bits long'
        )
        General.run_cmd(
            "awk '$5 >= 3071' /etc/ssh/moduli | sudo tee /etc/ssh/moduli.tmp")
        General.run_cmd('mv /etc/ssh/moduli.tmp /etc/ssh/moduli')

        response = General.answer('do you want to enable 2FA/MFA for SSH?')
        if response:
            General.warning_message(
                'Note: a user will only need to enter their 2FA/MFA code if they are logging on with their password but not if they are using SSH public/private keys.\n'
            )
            General.run_cmd('apt install libpam-google-authenticator -y')
            General.warning_message(
                '\n[ALERT]  Notice this can not run as root, at the next machine restart RUN "google-authenticator"\n'
            )
            time.sleep(5)
            General.output_message(
                'Select default option (y in most cases) for all the questions it asks and remember to save the emergency scratch codes.'
            )
            time.sleep(2)
            General.run_cmd(
                'echo -e "\nauth       required     pam_google_authenticator.so nullok         # added by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")" | tee -a /etc/pam.d/sshd'
            )
Пример #17
0
def nvidia_drivers():
    # Installation invidia driver
    response = General.answer('Do you need nvidia drivers?')
    if not response: return
    General.output_message('Since the nvidia-driver package in Debian is proprietary, we need to enable contrib and non-free component in /etc/apt/sources.list file')
    General.run_cmd('apt install software-properties-common')
    General.run_cmd('add-apt-repository contrib')
    General.run_cmd('add-apt-repository non-free')
    General.run_cmd('apt update -y')
    General.run_cmd('apt install nvidia-driver -y')
Пример #18
0
def ufw(SSH_ENABLE, SSH_PORT):
    # Firewall With UFW

    f_ufw_smtptls = '/etc/ufw/applications.d/smtptls'

    if not General.answer('Do you want install and configure UFW?'): return

    General.run_cmd('apt install ufw -y')
    General.run_cmd(
        'ufw default deny outgoing comment "deny all outgoing traffic"',
        'ufw default deny incoming comment "deny all incoming traffic"',
        'ufw allow out 53 comment "allow DNS calls out"',
        'ufw allow out 123 comment "allow NTP out"',
        'ufw allow out http comment "allow HTTP traffic out"',
        'ufw allow out https comment "allow HTTPS traffic out"',
        'ufw allow out whois comment "allow whois"',
        'ufw allow out 25 comment "allow MAIL out"')
    with open(f_ufw_smtptls, 'w') as file:
        file.write('''
[SMTPTLS]
title=SMTP through TLS
description=This opens up the TLS port 465 for use with SMPT to send e-mails.
ports=465/tcp
            ''')
    General.run_cmd(
        'ufw allow out smtptls comment "open TLS port 465 for use with SMPT to send e-mails"'
    )
    General.output_message('''
The following ufw rules have been entered automatically:
- deny all outgoing traffic
- deny all incoming traffic
- allow DNS calls out-
- allow NTP out
- allow HTTP traffic out
- allow HTTPS traffic out
- allow whois
- allow SMPT out
- allow MAIL out
''')
    # ufw ssh rules
    if SSH_ENABLE and General.answer('(UFW) Do  you need ssh rule?'):
        General.run_cmd(
            f'ufw limit in {SSH_PORT} comment "allow SSH connections in"')
        General.output_message('Added Rules')

    # ufw ftp out rule
    if General.answer('(UFW) Do you need ftp out rule?'):
        General.run_cmd('ufw allow out ftp comment "allow FTP traffic out"')
        General.output_message('Added Rules')

    # ufw dhcp rule
    if General.answer('(UFW) Are you using DHCP?'):
        General.run_cmd(
            'ufw allow out 68 comment "allow the DHCP client to update"')
        General.output_message('Added Rules')

    # ufw http/https rule
    if General.answer(
            '(UFW) Do you nedd to allow http/https ( yes for websites servers ) ?'
    ):
        General.run_cmd('ufw allow http comment "allow http traffic update"')
        General.run_cmd('ufw allow https comment "allow https traffic update"')
        General.output_message('Added Rules')

    General.output_message('Starting Firewall')
    General.warning_message('Maybe existing ssh connections will be stopped\n')
    General.warning_message(
        'sometimes the next cmd get stuck so press ENTER after 1 minute')
    General.run_cmd('ufw --force enable')
Пример #19
0
def psad(EMAIL):
    # iptables Intrusion Detection And Prevention with

    f_psad_conf = '/etc/psad/psad.conf'
    f_before_rules = '/etc/ufw/before.rules'
    f_before6_rules = '/etc/ufw/before6.rules'

    if not General.answer('Do you want to install and configure psad?'): return

    General.run_cmd('apt install psad -y')
    homenet = General.input_message('Type your Home net: ex(192.168.1.1/24) ')
    General.output_message('Configuring psad')
    General.change_lines(
        f_psad_conf,
        _1=[
            'EMAIL_ADDRESSES             root@localhost;',
            f'EMAIL_ADDRESSES             {EMAIL};\n'
        ],
        _2=[
            'HOSTNAME                     _CHANGEME_;',
            f'HOSTNAME                   {General.HOSTNAME};\n'
        ],
        _3=[
            'ENABLE_AUTO_IDS             N;',
            'ENABLE_AUTO_IDS             Y;\n'
        ],
        _4=[
            'HOME_NET                    any;',
            f'HOME_NET                    {homenet};\n'
        ],
        _5=[
            'PORT_RANGE_SCAN_THRESHOLD   1;',
            'PORT_RANGE_SCAN_THRESHOLD   2;\n'
        ],
        _6=[
            'ENABLE_MAC_ADDR_REPORTING   N;',
            'ENABLE_MAC_ADDR_REPORTING   Y;\n'
        ],
        _7=[
            'ALERT_ALL                   Y;',
            'ALERT_ALL                   N;\n'
        ])

    General.output_message(f'''
These changes have been made to the config '/etc/psad/psad.conf'.
If u need more advanced options feel free to modify it.
    - EMAIL_ADDRESSES             {EMAIL};
    - HOSTNAME                   {General.HOSTNAME};
    - ENABLE_AUTO_IDS             Y;
    - HOME_NET                    {homenet};
    - PORT_RANGE_SCAN_THRESHOLD   2;
    - ENABLE_MAC_ADDR_REPORTING   Y;
    - ALERT_ALL                   N;

                ''')

    with open(f_before_rules, 'r') as file:
        lines = file.readlines()
        text = file.read()
        if not (General.check_lines_in_file(
                f_before_rules, '# log all traffic so psad can analyze',
                '-A INPUT -j LOG --log-tcp-options --log-prefix "[IPTABLES]"',
                '-A FORWARD -j LOG --log-tcp-options --log-prefix "[IPTABLES]"'
        )):

            for index, line in enumerate(lines):
                if line.strip() == "COMMIT":
                    lines.insert(
                        index - 2,
                        '# log all traffic so psad can analyze\n-A INPUT -j LOG --log-tcp-options --log-prefix "[IPTABLES]"\n-A FORWARD -j LOG --log-tcp-options --log-prefix "[IPTABLES]"'
                    )
                    break
            with open(f_before_rules, 'w') as file:
                for line in lines:
                    file.write(line)

    with open(f_before6_rules, 'r') as file:
        lines = file.readlines()
        text = file.read()
        if not (General.check_lines_in_file(
                f_before_rules, '# log all traffic so psad can analyze',
                '-A INPUT -j LOG --log-tcp-options --log-prefix "[IPTABLES]"',
                '-A FORWARD -j LOG --log-tcp-options --log-prefix "[IPTABLES]"'
        )):
            for index, line in enumerate(lines):
                if line.strip() == "COMMIT":
                    lines.insert(
                        index - 2,
                        '# log all traffic so psad can analyze\n-A INPUT -j LOG --log-tcp-options --log-prefix "[IPTABLES]"\n-A FORWARD -j LOG --log-tcp-options --log-prefix "[IPTABLES]"'
                    )
                    break
            with open(f_before6_rules, 'w') as file:
                for line in lines:
                    file.write(line)

    General.warning_message('Restarting psad and Firewall..\n')
    General.warning_message('Maybe existing ssh connections will be stopped\n')
    General.run_cmd('ufw --force enable')
    General.run_cmd('ufw reload')
    subprocess.check_call(['psad', '-R'],
                          stdout=subprocess.PIPE,
                          stderr=subprocess.STDOUT)
    General.run_cmd('psad --sig-update')
    General.run_cmd('psad -H')
    General.output_message('Done')
Пример #20
0
def maldet(EMAIL):
    # Anti-Virus Scanning With Maldet

    dir_path = '/usr/local/src/'

    if not General.answer(
            'Do you want to use Maldet for Anti-virus Scanning?'):
        return

    General.run_cmd(
        f'wget -q http://www.rfxn.com/downloads/maldetect-current.tar.gz -P {dir_path}'
    )
    General.output_message("Maldet Downloaded")
    tarfile = '/usr/local/src/maldetect-current.tar.gz'
    path = '/usr/local/src/'
    retcode = subprocess.call(['tar', '-xvf', tarfile, '-C', path],
                              stdout=subprocess.PIPE,
                              stderr=subprocess.STDOUT)

    for elem in listdir(dir_path):
        if ('maldetect-' in elem) and (not 'maldetect-current' in elem):
            maldect_path = dir_path + elem
            file_path = f'{maldect_path}/files/conf.maldet'
            General.run_cmd(f'sh {maldect_path}/install.sh')
            General.output_message('Maldet Installed')
            General.output_message('Configuring Maldet..')
            General.change_lines(
                file_path,
                _1=['email_alert="0"', 'email_alert="1"\n'],
                _2=['email_addr="*****@*****.**"', f'email_alert="{EMAIL}"\n'],
                _3=['email_ignore_clean="1"', 'email_ignore_clean="0"\n'])
            break