And again about ... LAMP and basic secure do-it-yourself mini-hosting

    Seeing once again the despicable message to Google in response to a question about how to deploy my own LAMP, I decided to write this post. To somehow dilute tons of joyful reports about successful installation from blogs, the essence of which boils down to one aptitude install blah-blah command .

    No, of course, of course, PHP is the most reliable language, and all the site engines written in it are a living embodiment of impenetrable protection against hacking. Then yes - aptitude install apache2 - and you will be happy. Do not forget to leave phpmyadmin at the default address, but put some leaky FTP sieve.

    In general, as it turned out, many people are not even aware that having hacked a site and having the opportunity to execute their PHP code, an attacker on a system with defective settings can at least read almost anything on your system. It is understandable - when working with Linux you get used to it somehow, that by default security is quite adequate. And here is such a hole ...

    In general, this article once again describes banality on the topic of how to deploy LAMP and give access to external users to the files and databases of your sites. Those. how to quickly do mini-hosting with your own hands. However, unlike hosting, we will have at least basic security .

    Those who are tired of the topic of web servers can probably find in the article interesting tricks of multi-user limited access to the server via SFTP.

    And no, this is not yet another article describing the installation of Linux and doing aptitude install apache2. Quite the contrary: in this article I wanted to show the fatal insufficiency of these manipulations and, to put it mildly, the incompetence of those who replicate them on the Internet.


    Everything will be described using the example of Debian.

    First you need to install everything you need (by the way, for Ubuntu phpMyAdmin is better to install from PPA ):

    aptitude install apache2 mysql-server libapache2-mod-php5 ssh
    aptitude install phpmyadmin

    When installing phpMyAdmin, we generate an arbitrary password to connect to the database, otherwise everything is obvious.

    How it will work

    All users who need to access files on the server will have a local account with the ability to access only via SFTP and only in the folder with their sites. In this case, authorization will be supported both by password and by key. Interactive SSH login will not be possible, although if you really need to, it can be enabled, and also with closed access to system files.

    There will be no FTP, although it can be easily screwed. SFTP is more reliable (encryption, the ability to authorize by key), and FTP in this case is elementary redundant and is a fairly large potential security hole.

    Each site will belong to a certain 'account', i.e. under one 'account' there can be several sites. SFTP users are attached to these 'accounts', and no one bothers to connect several users to one 'account'. Further, inside the 'account', everything can be resolved by standard access rights mechanisms in Linux.

    Users and passwords from the database will not depend on system users in any way; database management will occur through standard phpMyAdmin.

    Among other things, sites running on your server will not be able to crawl beyond the boundaries of their working directory and read or change any data that is not related to them.

    A little more about the structure

    All sites will be in directories of the form / var / www / ACCOUNT / sites / SITENAME . ACCOUNT here does not necessarily mean some kind of system user, just some arbitrary identifier.

    System users who will connect via SFTP to edit sites will have / var / www / ACCOUNT / home / USERNAME set as their home directory . Accordingly, depending on the value of ACCOUNT, one or another user will have access to an account. Creating a home directory inside an account is necessary in order to be able to authorize SFTP users by keys.

    For all SFTP users, the main group will be set to www-data (default Apache2 group in deb-based). In addition, all files created both by the user via SFTP and Apache, by default, will have rights 0660 , and directories 0770 . Since Apache and SFTP users have the same group, by default, both the user and the web server can write to any new file or directory, regardless of who created it. What is usually required.

    The databases will use their own, completely separate authorization and access control mechanism. Everything is extremely simple here: we create users and give them rights only to specific databases. Therefore, we will not return to this issue.

    Creating 'accounts' and system users

    Placing a site on a server should start by preparing a place for it and creating a user to work with it. As described above, for the site we need a folder of the form / var / www / ACCOUNT / . As ACCOUNT we use for example 42 . Just 42 . Ok, create the folder:

    mkdir /var/www/42

    In addition, inside the account, we need the home / USERNAME and sites directories . Create them:

    mkdir -p /var/www/42/home/marvin
    mkdir /var/www/42/sites

    For future SFTP configuration , you should immediately make sure that both / var / www / 42 / sites and all subordinate folders belong to root: root and that no one but root has write permissions to them.

    Next we create the user. In order not to get confused with normal, full-fledged server users, SFTP users can be transferred to the UID range from 901 to 999 . If you do not need it, remove the acc. parameters. If you want to log in using only the key, add the --disabled-password parameter . As a result, the command is as follows:

    adduser --home /var/www/42/home/marvin --no-create-home --shell /bin/false --firstuid 901 --lastuid 999 --ingroup www-data marvin

    Installing the shell in / bin / false guarantees us that the user will not be able to log into the system interactively.

    SFTP setup

    SFTP setup will consist in the fact that for all members of the www-data group we will make it so that when entering via SFTP they will immediately go to the sites folder of the “account” in which their HOME directory is located, without the ability to get higher in the directory tree.

    This is done simply. It is enough to add the code to the end of the file / etc / ssh / sshd_config

    # Специальный доступ для пользователей из www-data: chroot в их HOME,
    # установленный umask 007, соответствующий 0660 для файлов и 0770 для каталогов
    Match Group www-data
            AllowTCPForwarding no
            X11Forwarding no
            ChrootDirectory %h/../../sites
            ForceCommand internal-sftp -u 0007

    And poke sshd to update the configuration:

    service ssh reload

    This piece of code for all users from the www-data group, firstly, disables TCP and X11 forwarding (they do not need to have access to your LAN). Secondly, it makes for them when chroot enters sites the folder of their 'account' (for this we needed to make sites folders writable only for root - otherwise chroot does not work). Well, in the third change them on the built-handler SFTP (which does not need a full-fledged environment with Shelley and others), simultaneously telling him to create all the files and folders to the value of umask to 007 . That is, the default rights to new files will be 0660 , and 0770 to directories .

    Configuring Apache and phpMyAdmin

    It is not necessary to specifically configure Apache to provide basic operation. The only thing in Debian is that the PHP5 package comes with an integrated Suhosin patch that enhances security. It will be necessary when configuring the site’s configs, although it is quite possible to do without it.

    And so in general for Apache you only need to change the umask for the created files and folders to the same one that we used to configure SFTP. This is done by adding lines to / etc / apache2 / envvars :

    # umask 007 для создания файлов с разрешениями 0660 и каталогов с 0770
    umask 007

    For minimal phpMyAdmin settings, you just need to change the address where it will be available from indecently stupid / phpmyadmin to something else. To do this, replace the line in the /etc/phpmyadmin/apache.conf file

    Alias /phpmyadmin /usr/share/phpmyadmin

    for example:

    # А мы немного схитрим!
    Alias /вдушу_влазер /usr/share/phpmyadmin

    Remember to restart Apache:

    service apache2 restart

    Adding Sites

    To add sites to your hosting, you need to do two things - firstly, place the site files with the necessary rights on your server, and secondly, create an Apache config for the site. In addition, most often you will need to create a database and configure access rights to it - but this is a trivial operation, so we will not consider it.

    To place files, you need to create a site directory from the root directory in the folder of the desired 'account'. For instance:

    mkdir /var/www/42/sites/

    Further set the desired rights. At a minimum, the SFTP user who will work with this directory must have write permissions. For example, you can do this:

    chown marvin:www-data /var/www/42/sites/
    chmod 0750 /var/www/42/sites/

    Ok, now the user can enter and upload site files. It remains to configure the Apache. To do this, as always, create the settings file in the / etc / apache2 / sites-available directory . The contents of this file for the site with the data in the /var/www/42/sites/ directory should be something like this:

            # Корневая директория сайта
            DocumentRoot /var/www/42/sites/
                    # Тут всякая стандартная хрень по типу
                    #Options FollowSymLinks
                    #AllowOverride All
                            # Запрещаем php вылазить куда ему совершенно не надо
                            php_admin_value open_basedir /var/www/42/sites/
                            # Поскольку вылазить запретили - сохраняем временные файлы и сессии внутри корня сайта
                            php_admin_value upload_tmp_dir /var/www/42/sites/
                            php_admin_value session.save_path /var/www/42/sites/
                            # Отключаем возможность инклуда по URL
                            php_admin_flag allow_url_include off
                            # Отключаем возможность динамической подгрузки модулей PHP
                            php_admin_flag enable_dl off
                            # Отключаем всю лабудень для системных вызовов
                            php_admin_value suhosin.executor.func.blacklist apache_note,apache_setenv,closelog,debugger_off,debugger_on,define_syslog_variables,escapeshellarg,escapeshellcmd,ini_restore,openlog,passthru,pclose,pcntl_exec,popen,proc_close,proc_get_status,proc_nice,proc_open,proc_terminate,shell_exec,syslog,system,url_exec
            # Закрываем, на всякий случай, доступ в temp
                    AllowOverride None
                    Order Deny,Allow
                    Deny from All
            ErrorLog /var/log/apache2/error.log
            # Possible values include: debug, info, notice, warn, error, crit,
            # alert, emerg.
            LogLevel warn
            CustomLog /var/log/apache2/access.log combined

    The important thing here is only the contents of the block . It contains PHP settings, which, firstly, prohibit accessing files outside the root directory of the site ( open_basedir and porting to temp), and secondly, disable two extremely dangerous PHP features ( allow_url_include , enable_dl ) that are still present in modern versions of PHP and may even be included. And finally, thirdly, they prohibit PHP scripts from using a number of functions for interacting with the OS. For example, the execution functions of an arbitrary command. The list of functions is honestly hooked from somewhere on the Internet and does not claim to be universal, although it seems to be sufficient to ensure security.

    A little bit about temp: since we prohibit PHP from accessing files outside the root directory of the site, we need to specify a directory for saving temporary files (files uploaded by users of the site to the server through the standard upload mechanism from the HTML form) and session files inside the root of the site. Naturally, this directory must first be created. In addition, it would be better to explicitly close access to it from the Internet, which is done in the second block of Directory . Otherwise, someone might accidentally get your user sessions.

    If Suhosin is not installed on the server, then instead of suhosin.executor.func.blacklist, you can use the standard PHP disable_functions option . True, you need to specify it in php.ini, i.e. it will act on all sites on your server.

    In addition, the eval function is not disabled in the above settings . Alas, many sites need it for some reason, although it’s still better to turn it off. Pay attention to the options suhosin.executor.disable_eval and suhosin.executor.disable_emodifier all the same Suhosin .

    After you prepare the configuration you need, simply activate the site:


    And don't forget to kick the Apache:

    service apache2 reload

    And of course, you need to upload the files and site database to the server - without them, it is unlikely that anything will work.

    SSH tuning: keys and interactive login

    To access SFTP users by keys, you need to do the same, which is always done: inside the HOME directory, create the .ssh / directory , in it the authorized_keys file , in which to register the public keys for the user.

    In addition, some users can open interactive access to the server. To do this, firstly, prepare the necessary chroot environment in the root folder of the corresponding “account”, at least with an interpreter and all necessary virtual FSs. This is done in a standard way and there is nothing complicated about it.

    Then you can create an additional group for interactive login. For example, ssh-interactive :

    addgroup --gid 900 ssh-interactive

    Add the necessary users to it, simultaneously changing their SHELL to full-fledged bash:

    usermod -a -G ssh-interactive --shell /bin/bash marvin

    And prescribe specific settings for this group in sshd_config . To do this, you need to modify the Match directive related to www-data , adding ! Ssh-interactive to it so that it does not apply to users of this group:

    Match Group www-data,!ssh-interactive

    And after it add another Match directive :

    # Интерактивный вход по SSH для доступа к коду сайтов
    Match Group www-data,ssh-interactive
            AllowTCPForwarding no
            X11Forwarding no
            ChrootDirectory %h/../../

    The only problem is that for members of the ssh-interactive umask group it will no longer be set to 007. You can fix this by adding the corresponding parameter in the global settings of the sftp subsystem in sshd_config . By the way, it is unlikely you will want to drag openssh components into the chroot environment, so you can at the same time change the external sftp handler to the internal implementation:

    Subsystem sftp internal-sftp -u 0007

    More about SFTP configuration:


    I have always been interested in the question - is there somewhere on the official resources a complete list with a description of all the PHP functions that can somehow give the script access to the components and files of the system. The above list is honestly taken from the Internet, so if anyone shares a link to the list of functions, I will be very grateful.

    Well and yes - if there are any comments about what else can be done minimally to ensure the security of the simplest hosting - write.

    Only registered users can participate in the survey. Please come in.

    Do you restrict PHP to even using open_basedir?

    • 28.1% Yes 167
    • 42.8% No 254
    • 10.9% No, I use more powerful and reliable mechanisms 65
    • 18% No, I do not use PHP 107

    Also popular now: