Configuring a global auto_prepend_file for ISPProtect BanDaemon and beyond

Discussion in 'Tips/Tricks/Mods' started by Steveorevo, May 26, 2022.

  1. Steveorevo

    Steveorevo Member

    I have an ISPConfig 3.2 running Nginx on Ubuntu 20 and I'd like to have all clients and their subsequent websites to prepend a PHP file for various reasons, including a future ISPProtect BanDaemon installation. I can configure an individual prepend.php file that does what I want inside each client say at:

    Code:
    /var/www/www.example.com/web/prepend.php
    
    This works as long as I use the relative path in ISPConfig's Website -> Options -> Custom php.ini settings:

    Code:
    auto_prepend_file = prepend.php 
    
    However, if I include the full path, such as:

    Code:
    auto_prepend_file = /var/www/www.example.com/web/prepend.php
    
    I receive an error 500, with the error.log reading:

    PHP Warning: include(): open_basedir restriction in effect. File(/var/www/www.example.comm/web/prepend.php) is not within the allowed path(s): (/var/www/clients/client22/web14/web:/var/www/clients/client22/web14/private:/var/www/clients/client22/web14/tmp:/var/www/www.example.com/web:/srv/www/www.example.com/web:/usr/share/php5:/usr/share/php:/tmp:/usr/share/phpmyadmin:/etc/phpmyadmin:/var/lib/phpmyadmin:/dev/random:/dev/urandom)...

    PHP Warning: include(/var/www/www.example.com/index.php): Failed to open stream: Operation not permitted...

    Clearly /var/www/www.example.com/web/prepend.php is in /var/www/www.example.com/web so the error is wrong; the read error appears to be from chroot. If I turn off ISPConfig's Website -> Options -> chroot PHP-FPM, it works with no "open_basedir" error logged. But then I lose chroot isolation on the PHP-FPM process. open_basedir is still in effect preventing execution of other client .php files but I'm not sure about PHP shell execute access.

    Is there anyway I can have a common open_basedir and chroot accessible (preferably read-only) folder to force a prepend.php script in all websites regardless of clients and while preserving client/website isolation? This will be needed for ISPProtect's BanDaemon and other stuff Id like to always execute with PHP scripts. I've seen similar requests with "forced ads" on older systems but those articles appear to be dated. I'm not familiar with chroot configuration, so any tips my way would be greatly appreciated. Thanks!
     
  2. Steveorevo

    Steveorevo Member

    It looks like I can accomplish this with a "hard link" using jk_cp (Jailkit copy). I did the following:
    Code:
    jk_cp -k /var/www/clients/client22/web14 /usr/share/php/test.php
    
    And now my /usr/share/php/test.php file is reflected "globally" in all clients that have the hard link. When I change the contents of test.php, it's reflected everywhere. Also, auto_prepend_file doesn't seem to complain and the "chroot PHP-FPM" option is still turned on.

    Success!!! :)

    It's from my understanding that not all files are hard linked; some are copied? When I do a jk_check I see that some files are different sized and complains that they are "out of date" (i.e. mysqldump, etc). Is this because my apt update/upgrade has caused my jails to fall out of sync? :eek: If so, how do I re-sync them? I tried to do a jk_update but I get this error:
    Code:
    jk_update -j /var/www/clients/client22/web14
    Traceback (most recent call last):
      File "/usr/sbin/jk_update", line 290, in <module>
        main()
      File "/usr/sbin/jk_update", line 272, in main
        if (not config.has_key('hardlink')):
    AttributeError: 'dict' object has no attribute 'has_key'
    
     
    Last edited: May 26, 2022
  3. Jesse Norell

    Jesse Norell ISPConfig Developer Staff Member ISPConfig Developer

    Using hardlinks is a quick way to undo much to all of the benefits of using chroot in the first place. Eg. chroot's main purpose is to isolate code running under one website from the other websites, and you just setup a single php script that is not just accessible to every site, but actually setup to run automatically by every site. All that is needed is a way to to get write access to the file, or trick something into writing to it for you, or change file ownership, and you have total compromise of all your sites.

    If you want autoprepend set for every site, I would just tweak the vhost template and regenerate sites. Another option if all your sites use chroot mode php-fpm and there are no vhost aliases or subdomain aliases is try the /web path for the script. You might also try creating a symlink underneath the chroot, something like
    Code:
    mkdir -p /var/www/clients/client22/web14/var/www/clients/client22/
    ln -s ../../../../web /var/www/clients/client22/web14/var/www/clients/client22/web14
    
    One other thing to keep in mind is some sites already use autoprepend, in particular wordpress with the wordfence plugin uses that to setup their waf to run.
     
  4. Steveorevo

    Steveorevo Member

    WordFence and BanDaemon will compete with each other, along with forced ads, and other code I'd like prepend; I'm planning on porting a prepend manager to list the files and priorities for prepends by an administrator. I've already authored similar for other hosting environments.

    Yes, for hardlinks, I figured as I stumbled across the comments about security in source; the tradeoff here is one file gets realtime updates with no need to re-sync. But the "weakest link" in the chain is potential problem. It would be ideal if I could get jk_update to work? Is the error message I get for jk_update normal? I've read the docs and not sure if I'm getting the syntax right. Shouldn't ISPConfig update jailkits to reflect OS changes after updates/upgrades? I noticed my mysqldump and other binaries are not the same in jails as they are in root.
    Code:
    jk_update -j /var/www/clients/client22/web14
    Traceback (most recent call last):
      File "/usr/sbin/jk_update", line 290, in <module>
       main()
      File "/usr/sbin/jk_update", line 272, in main
       if (not config.has_key('hardlink')):
    AttributeError: 'dict' object has no attribute 'has_key'
    
     
  5. Jesse Norell

    Jesse Norell ISPConfig Developer Staff Member ISPConfig Developer

    Perhaps, or just setup a script which copies the file to all locations when you change it.
    It is a known bug in jailkit, so "normal" in the sense that your jailkit version is expected to exhibit that behavior. :) Fixed in version 2.22.
    Yes, but it uses jk_update, and yours is broken. Maybe look for a backports version or install from source, there are additional fixes you should apply in version 2.23, so just update to that (currently the latest release).
     
    Steveorevo likes this.

Share This Page