Mappen, bestanden & rechten 2020 (WordPress)

Uit De Vliegende Brigade
Ga naar: navigatie, zoeken

Hoe stel je rechten op bestanden en mappen rondom een WordPress-installatie, op de juiste manier in?

Vraagstukken

Dit is een checklist van dingen die ik niet zeker weet, en die ik regelmatig tegenkom als het over dit onderwerp gaat:

  • Plugins update ik middels de WP CLI. Brengt dat een risico met zich mee dat het Apache-proces te veel rechten krijgt?
  • Hoe verhelp ik foutmeldingen rondom WordFence?
  • Hoe zorg ik ervoor dat rechten veilig zijn ingesteld?
  • Wie moet de eigenaar van bestanden en mappen worden? Ikzelf? (liever niet, want ik ben binnen afzienbare termijn niet meer de enige die de betreffende webservers onderhoud) www_data? Iets anders?
  • Hoe zit het met groups? Moet ik daar iets mee?
  • Waarom vindt de WP CLI het zo'n slechte zaak als je een commando als root wilt geven?
  • Wat zijn ACL's, en moet ik daar iets mee [1]?
  • Als www-data eigenaar is, hoe zorg ik ervoor dat ik zelf nog mormaal met die bestanden kan werken? Iets met groups? Iets met su? Iets met ACL's?
  • Moet ik iets met setuid, setgid en/of sticky bits? Ik vermoed dat dit is, hoe je met FTP bestanden upload naar een account op een shared server, zonder dat er problemen ontstaan tav. de rechten op die ge-uploade bestanden.

Vereisten

Veilig

Belangrijk dat rechten op een veilige manier zijn ingesteld. Met veilig wordt bedoeld, dat hackers zo min mogelijk kans maken, en dat incidenten niet escaleren.

  • Doorgaans kunnen hackers een systeem binnendringen dankzij zwakheden in een onderdeel van WordPress, en daar ben ik machteloos over
  • Waar ik niét machteloos over ben: Maatregelen treffen zodat zo'n incident niet escaleert. Dat is waar dit hoofdstuk over gaat.

Werkbaar

Ik had ooit (2018?) een ingenieus systeem bedacht, maar het bleek niet te werken, omdat ik dan steeds met su dingen moest doen, ofzo.

Zelf kunnen updaten

Ik zou het erg prettig vinden als ik sites nog steeds kan updaten met een eigen script dat WP CLI aanroept.

Wat - Principes

Verschillende instellingen gedurende installatie & operationale activiteiten?

  • Iets wat ik al langer vermoedde: Tijdens installatie van een site, heb je andere instellingen nodig dan wanneer de site operationeel is.
  • Dit kun je een stap verder nemen: Verschillende instellingen gedurende bijwerken van een site, en wanneer de site operationeel is.

Gebruiker: Apache

Er zijn maar twee gebruikers. De eerste daarvan is Apache. Dat is hetzelfde als de site-bezoeker, of PHP. Wat Apache wel of niet moet kunnen, is afhankelijk van wie je het vraagt en de gekozen oplossing. Mijn indruk:

  • Alle mappen & bestanden kunnen lezen
  • Onder Uploads mappen aamaken, lezen & schrijven
  • Misschien kunnen schrijven (bv. voor automatische updates en configureren van WordFence).

Gebruiker: Beheerders

De tweede groep van gebruikers, betreft beheerders of developers. Zij loggen in via SSH. Ze hebben beiden sudo-rechten, maar su root is niet mogelijk. Eventueel su naar een ander (niet-root)-account, zou geen probleem zijn. Deze developers/beheerders hebben toegang tot alle virtuele hosts.

Ze moeten ongeveer alles kunnen, zonder dat dat heel ingewikkeld wordt (bv. als je cd niet mag gebruiken, worden dingen heel lastig, omdat je cd niet kunt doen als sudo cd, omdat je daarna als gebruiker 'opeens' op een verboden plek bent aangeland).

Owner vs. group

Nu komt de truuk [2]: Je hebt twee soorten accounts (Apache & Beheerders), en die moeten verschillende rechten krijgen. De standaardmanier om dat te doen:

  • Eigenaar: Maak de ene soort eigenaar van de bestanden en mappen
  • Groep: Maak de andere soort lid van een groep waar deze bestanden en mappen bijhoren.

Maar wie wordt wat? Daar zijn verschillende ideeën over. Het speelt ook een rol als je bv. Plesk gebruikt. Zie het volgende hoofdstuk voor details.

Websites mogen zichzelf niet updaten

Tegenwoordig update WordPress zichzelf standaard automatisch. Dat impliceert dat WordPress (eigenlijk uiteraard Apache) schrijfrechten heeft op z'n eigen installatie. Dat vind ik een slecht idee: Een beveiligingsincident zou daardoor gemakkelijk kunnen escaleren.

Online kon ik daar niets over vinden. Ik vond daar wel een hoop mensen die dit een slecht idee vinden om een hele andere reden: Ze willen de controle behouden wanneer WordPress (of bv. WooCommerce, of welk onderdeel van WordPress dan ook) wordt bijgewerkt. JaapdeWit.com heeft om die reden automatische updates uitgeschakeld.

Hoe - Implementatie

Apache is eigenaar - Beheerders zitten in een groep

Mijn oplossing:

Entiteit Wat?
Apache Eigenaar (www-data)
Beheerders Groep (www-admin)

Redenen voor deze keuzes:

  • Het is vrijwel onvermijdelijk dat Apache submappen gaat aanmaken onder uploads, dus een systeem waarbij Apache niet eigenaar is van bestanden, wordt inconsistent
  • Op het moment dat er meerdere beheerders zijn, wordt het raar als verschillende beheerders eigenaar worden van verschillende mappen en bestanden
  • Deze aanpak werd hier gesuggereerd voor systemen met meerdere virtuele hosts.

Rechten Apache

Operatie Opmerkingen
Bestanden & mappen lezen
  • Dit geldt in beginsel voor alle mappen & bestanden
  • Dit geldt ook voor PHP-bestanden: Een PHP-script geldt niet als een executable (omdat er een interpretator aan te pas komt ofzo). PHP-scripts hoeven dus niet de eigenschap executable te hebben
  • In bepaalde mappen mogen PHP-bestanden niet geëxecuteerd worden. Daar heeft Apache oplossingen voor (zie verderop).
  • Onduidelijk of dit ook geldt voor de 'eigen' mappen die ik soms aanmaak binnen een installatie om locale upload-bestanden te parkeren of database-kopiën tijdelijk naar toe te schrijven: Er wordt alleen maar iets gedaan met die mappen en bestanden nav. scripts die door mezelf worden aangeroepen en die niet door Apache worden aangeroepen → Testen.
Mappen lezen & executeren
  • Dit geldt in beginsel voor alle mappen binnen de virtual host
  • Zie opmerking over 'eigen' mappen hierboven.
Uploads:
  • Submappen aanmaken
  • Bestanden lezen & schrijven
Ook schrijven, ivm. uploaden nieuwe bestanden
Overige schrijfrechten? Ik ben er geen fan van, dat Apache ook onder meer omstandigheden kan schrijven. Bv.:
  • Tijdens installatie WordFence, wil deze een PHP-bestand aanmaken
  • WordPress kunnen updaten via de site.

Ik denk dat dit het risico nogal verhoogt op escalatie bij een incident. Een tussenoplossing: Tijdens rechten verruimen, en daarna weer dichtzetten.

Rechten beheerders

Beheerders kunnen alles. Dus zoiets als sudo chmod -R g+rwxX vanuit de root van een installatie. Als je per se wilt, kun je hiervan x nog weglaten: Doorgaans heb je geen bash-bestanden in een WordPress-installatie (en voor PHP heb je x ook niet nodig).

Complicaties ivm. beperkte rechten

Probleem (2): Zo uit het probleem zich
Probleem (2): Eigenaar+groep is strompf, en other mag nix, niet eens lezen

Oh oh:

Probleem (1): Ik kan niet uploaden naar Apache-mappen

De eerste complicatie: Regelmatig maakt Apache nieuwe upload-submappen aan, bv. bij de eerste update in een nieuwe maand. Voorbeeld:

drwxrwx---  5 www-data www-admin    4096 mrt  3 11:07 ./
drwxrwx--- 12 www-data www-admin    4096 feb 29 18:55 ../
drwxrwx---  2 www-data www-admin   65536 jan 27 11:34 01/
drwxrwx---  2 www-data www-admin 2293760 feb 29 23:10 02/
drwxrwx---  2 www-data www-data     4096 mrt  3 11:07 03/

Nu kan ik zelf niet meer via scripts bestanden uploaden, want ik heb geen schrijfrechten tot map 03. Voorbeeld van een foutmelding:

   Line 287 - Error returned while sideloading image 01 http://example.com/hiero/blub.jpg
   The error: WP_Error Object
(
    [errors] => Array
        (
            [upload_error] => Array
                (
                    [0] => The uploaded file could not be moved to wp-content/uploads/2020/03.
                )
        )
    [error_data] => Array
        (
        )
)

Probleem (2): Apache kan mijn uploads niet lezen

Dit probleem is er ook de andere kant op: Als ik mbv. een script via de API afbeeldingen upload, dan kan Apache die afbeeldingen niet lezen: Eigenaar en groep zijn steeds strompf

Probleem (3): Updates maken mij eigenaar & groep

Dit is wat er gebeurt in de map wp-content/plugins na een update van Yoast via de CLI (dus door mij, niet door Apache):

dr-xrwx---  6 www-data www-admin 4096 dec 12 14:27 woocommerce-pdf-ips-templates/
dr-xrwx---  8 www-data www-admin 4096 dec 12 14:27 woocommerce-pip/
dr-xrwx---  5 www-data www-admin 4096 dec 12 14:27 woocommerce-quantity-increment/
dr-xrwx--- 14 www-data www-admin 4096 feb 29 23:15 wordfence/
drwxrwxr-x 16 strompf  strompf   4096 mrt  3 17:00 wordpress-seo/
dr-xrwx---  5 www-data www-admin 4096 jan 16 16:25 wp-mail-smtp/
dr-xrwx---  7 www-data www-admin 4096 dec 12 14:27 wp-sync-db-1.6/
dr-xrwx---  6 www-data www-admin 4096 dec 12 14:27 wp-sync-db-media-files-master/

De site ondervindt er geen last van, want others kan lezen+executeren, maar een schoonheidsprijs verdient het niet.

Oplossingen

  1. Maak beheerders ook lid van www-data - Simpele oplossing voor het eerste probleem, het maakt het leven iets gemakkelijker, en het verzwakt de beveiliging niet
  2. Incorporeer in upload-scripts code om eigenaar+groep aan te passen na upload
  3. Extra (niet toegepast): Gebruik su in upload-scripts, zodat Apache het upload.
  4. Voer update-scripts uit met su, zodat Apache het upload. Probleem: Groep moet dan alsnog worden aangepast
  5. Voer na updates een script uit om eigenaarschap+groep bij te werken

De eerste twee dingen hierboven heb ik toegepast. Hoe de tweede oplossing eruit ziet in m'n ImProc-routine:

Ergens bovenaan het script staat dit. De reden dat ik het jaar selecteer, en niet in een keer de hele map uploads doe: Daar staan onduidelijke dingen van WordFence in, en ik heb geen zin in complicaties:

upload_path_this_year=$site_path"/wp-content/uploads/"$(date +'%Y')

De eigenlijke code:

################################################################################################
# Upload images & associate with products as thumbnails
################################################################################################
#
echo "Upload images..."
#
# Upload!
##########################################################
#
php -f ./Subroutines/images-import-and-associate-with-products.php "$site_path" "$site_url" "$product_table" "quiet"


# Update owner + group
##########################################################
#
# * Otherwise, Apache can't read stuff
# * Can't do this without "sudo"
#
sudo chown -R www-data "$upload_path_this_year"
sudo chgrp -R www-admin "$upload_path_this_year"

Casus: Ontwikkelomgeving (feb. 2020)

Groep aanmaken & configureren

Groep aanmaken en mezelf aan die groep toevoegen:

sudo groupadd www-admin
sudo usermod -a -G www-admin strompf

Waarbij:

  • -a - Add
  • -G - Group'

Update-script: Bestanden & mappen

#
# wp_set_rights - Location: "Scripts" (Dell2016) - Strompf, March 2020
###################################################################################
# Close everything
###################################################################################
#
# Because differential commands are used further on
#
sudo chmod -R 000 /var/www


###################################################################################
# Maak www-data owner of /var/www and below
###################################################################################
#
sudo chown -vR www-data /var/www


###################################################################################
# Maak grp www-admin van de inhoud van de mappen
###################################################################################
#
sudo chgrp -R www-admin /var/www


###################################################################################
# Rights Apache
###################################################################################
#
# Starting point: Apache can read files & execute folders
##########################################################
#
sudo chmod -R u+rX /var/www


# Upload directories: Apache can write as well
##########################################################
#
sudo chmod -R u+rwX /var/www/example01.com/wp-content/uploads
sudo chmod -R u+rwX /var/www/example02.com/wp-content/uploads
sudo chmod -R u+rwX /var/www/example03.com/wp-content/uploads
sudo chmod -R u+rwX /var/www/example04.com/wp-content/uploads

###################################################################################
# Group mag alles
###################################################################################
#
sudo chmod -R g+rwxX /var/www

Let op: Speciale zaken zoals upload-mappen en die WordPress-firewall, zijn hier nog niet geregeld.

PHP disablen in uploads

Dat kan door in .htaccess te zetten: php_flag engine off, maar ik vind het prettiger om dit dit de virtuele host-definitie te doen. Dit werkt trouwens recursief (dus in alle submappen is php ook uitgeschakeld). Voorbeeld:

<VirtualHost *:80>

        ServerName example.com
        ServerAlias www.example.com
        DirectoryIndex index.php index.html index.htm
        DocumentRoot /var/www/example.com

        <Directory /var/www/example.com>
                AllowOverride All
                Require all granted
                RewriteEngine on
                RewriteBase /
                RewriteCond %{REQUEST_FILENAME} !-f
                RewriteCond %{REQUEST_FILENAME} !-d
                RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
        </Directory>

        # HIER ONTBREEKT EEN PRIVÉ-MAP

        <Directory /var/www/example.com/wp-admin/css>
                php_admin_value engine Off
        </Directory>


        <Directory /var/www/example.com/wp-admin/images>
                php_admin_value engine Off
        </Directory>


        <Directory /var/www/example.com/wp-admin/js>
                php_admin_value engine Off
        </Directory>


        <Directory /var/www/example.com/wp-content/languages>
                php_admin_value engine Off
        </Directory>


        <Directory /var/www/example.com/wp-content/updraft>
                php_admin_value engine Off
        </Directory>


        <Directory /var/www/example.com/wp-content/uploads>
                php_admin_value engine Off
        </Directory>


        LogLevel warn
        ErrorLog /var/log/apache2/error.log
        CustomLog /var/log/apache2/access.log vhost_combined

</VirtualHost>

Updaten via CLI geen probleem!

En nu de uitsmijter: In tegenstelling tot wat ik verwachtte, kan ik de site nog steeds prima via de CLI bijwerken (wp plugin update --all && wp theme update --all && wp language core update && wp core update && wp wc update). Waarschijnlijk is dat, omdat ik degene ben die die commando's geeft, en niet de site en dus Apache: Ik kan dit wel (want www-admin-groep), maar Apache niet - Heel goed.

Zie ook

Bronnen

Complete oplossingen

Overig