Uploaded image for project: 'Moodle'
  1. Moodle
  2. MDL-69333

Reduce ability to fingerprint a server with a htaccess-dist / nginx file / docs

    XMLWordPrintable

    Details

    • Testing Instructions:
      Hide

      Apache

      1) You will need to setup a moodle in a way where you can quickly hack on the different web server level settings. Because of this I've opted to use apache with .htaccess files turned on as its the fastest. Full instructions for each web server will be in the docs wiki and not here.

      2) Run composer so its files for the unit tests are present:

      php composer.phar install

      https://docs.moodle.org/dev/PHPUnit#Installation_of_PHPUnit_via_Composer

      3) Have the node modules files present:

      npm install

      https://docs.moodle.org/dev/NPM

      4) Visit this report page /report/security/index.php?detail=core_publicpaths

      5) Confirm that most of the report is red errors

      6) Setup a .htaccess file with the following contents in the root of your moodle. It is mostly commented out, uncomment each line by line and confirm each set of test urls turns green.

       

      # This turns directory indexes on, by default it is usually off but we
      # want to see the failure state first.
      Options +Indexes
       
      # This sends all missing files to moodle to render nicely, see MDL-56041
      ErrorDocument 404 /error/index.php
       
      # This sends any 403 from apache through to the same page, but also
      # overrides the http status with 404 instead for better security.
      ErrorDocument 403 /error/index.php?code=404
       
      RewriteEngine On
       
      # RewriteRule "(\/vendor\/)" - [F]
      # RewriteRule "(\/node_modules\/)" - [F]
      # RewriteRule "(^|/)\.(?!well-known\/)" - [F]
      # RewriteRule "(composer\.json)" - [F]
      # RewriteRule "(\.lock)" - [F]
      # RewriteRule "(\/environment.xml)" - [F]
      # Options -Indexes
      # RewriteRule "(\/install.xml)" - [F]
      # RewriteRule "(\/README)" - [F]
      # RewriteRule "(\/readme)" - [F]
      # RewriteRule "(\/moodle_readme)" - [F]
      # RewriteRule "(\/upgrade\.txt)" - [F]
      # RewriteRule "(phpunit\.xml\.dist)" - [F]
      # RewriteRule "(\/tests\/behat\/)" - [F]
      # RewriteRule "(\/fixtures\/)" - [F]
      

      7) If you run your sites at localhost/master/ or localhost/s39/ etc, change the ErrorDocument path to /master/error/index.php?code=404 or whatever your site path is.

       

      8) Once everything is green, the check over all should also be green

       

      NGINX

      The test steps above are the same but the config is condensed into a single rule set. This is much closer to what a prod site should look like:

      /etc/nginx/sites-enabled/default

          error_page 404 /error/index.php;    error_page 403 =404 /error/index.php;
       
          # Hide all dot files but allow "Well-Known URIs" as per RFC 5785
          location ~ /\.(?!well-known).* {
              return 404;
          }
       
          # This should be after the php fpm rule and very close to the last nginx ruleset.
          # Don't allow direct access to various internal files. See MDL-69333
          location ~ (/vendor/|/node_modules/|composer\.json|/readme|/README|readme\.txt|/upgrade\.txt|db/install\.xml|/fixtures/|/behat/|phpunit\.xml|\.lock|environment\.xml) {
              deny all;
              return 404;
          }
      
      

       

      Show
      Apache 1) You will need to setup a moodle in a way where you can quickly hack on the different web server level settings. Because of this I've opted to use apache with .htaccess files turned on as its the fastest. Full instructions for each web server will be in the docs wiki and not here. 2) Run composer so its files for the unit tests are present: php composer.phar install https://docs.moodle.org/dev/PHPUnit#Installation_of_PHPUnit_via_Composer 3) Have the node modules files present: npm install https://docs.moodle.org/dev/NPM 4) Visit this report page /report/security/index.php?detail=core_publicpaths 5) Confirm that most of the report is red errors 6) Setup a .htaccess file with the following contents in the root of your moodle. It is mostly commented out, uncomment each line by line and confirm each set of test urls turns green.   # This turns directory indexes on, by default it is usually off but we # want to see the failure state first. Options +Indexes   # This sends all missing files to moodle to render nicely, see MDL-56041 ErrorDocument 404 /error/index.php   # This sends any 403 from apache through to the same page, but also # overrides the http status with 404 instead for better security. ErrorDocument 403 /error/index.php?code=404   RewriteEngine On   # RewriteRule "(\/vendor\/)" - [F] # RewriteRule "(\/node_modules\/)" - [F] # RewriteRule "(^|/)\.(?!well-known\/)" - [F] # RewriteRule "(composer\.json)" - [F] # RewriteRule "(\.lock)" - [F] # RewriteRule "(\/environment.xml)" - [F] # Options -Indexes # RewriteRule "(\/install.xml)" - [F] # RewriteRule "(\/README)" - [F] # RewriteRule "(\/readme)" - [F] # RewriteRule "(\/moodle_readme)" - [F] # RewriteRule "(\/upgrade\.txt)" - [F] # RewriteRule "(phpunit\.xml\.dist)" - [F] # RewriteRule "(\/tests\/behat\/)" - [F] # RewriteRule "(\/fixtures\/)" - [F] 7) If you run your sites at localhost/master/ or localhost/s39/ etc, change the ErrorDocument path to /master/error/index.php?code=404 or whatever your site path is.   8) Once everything is green, the check over all should also be green   NGINX The test steps above are the same but the config is condensed into a single rule set. This is much closer to what a prod site should look like: /etc/nginx/sites-enabled/default error_page 404 /error/index.php; error_page 403 =404 /error/index.php;   # Hide all dot files but allow "Well-Known URIs" as per RFC 5785 location ~ /\.(?!well-known).* { return 404; }   # This should be after the php fpm rule and very close to the last nginx ruleset. # Don't allow direct access to various internal files. See MDL-69333 location ~ (/vendor/|/node_modules/|composer\.json|/readme|/README|readme\.txt|/upgrade\.txt|db/install\.xml|/fixtures/|/behat/|phpunit\.xml|\.lock|environment\.xml) { deny all; return 404; }  
    • Affected Branches:
      MOODLE_311_STABLE
    • Fixed Branches:
      MOODLE_311_STABLE
    • Pull 3.11 Branch:
      MDL-69333-fingerprint-checks-MOODLE_311_STABLE
    • Pull Master Branch:
      MDL-69333-fingerprint-checks

      Description

      I've flagged this as a security issue just in case. There are bunch of ways to sniff details of a moodle to both indirectly find out its version which you can then match against CVE's if it is old. Or in some cases you can sniff some internals like db xml files.

      I its easy to tell that moodle.org is on 3.9.1 as of Jul 21:

      https://moodle.org/lib/upgrade.txt

       

      Or in some cases you might have a proprietary / 3rd party plugin and you can see it's DB structure:

      https://moodle.org/local/plugins/db/install.xml

       

      I'm proposing a couple things:

      1) we should check for these similar to the node and composer vendor files in the security check report. But unlike those we need to test if they are accessible, not if they exist. I actually think it is more correct to test all of them using curl and not file_exists

      2) document a .htaccess file / nginx config which forbids access to these. I think shipping a .htaccess file in the root dir is probably not useful as a) won't work for nginx and b) it is likely to break existing files managed outside of git. So either something like .htaccess-dist in git, or perhaps just wiki docs

      3) As we will have the check in place from 1) above, the app is aware of what paths are ok and not. There is potentially scope for a more generic single rewrite rule which then delegates to a script inside moodle which does the checks. That would be more maintainable and auto update from git as the rules improve rather than relying on admins keeping up to date with an evolving wiki doc.

      ie something vaguely related to MDL-56041, we forward for example all .xml files to something like /error/check-access.php and it does the check and then serves the file or not. I'm the fence around this one.

       

      Docs page that should get updates:

      https://docs.moodle.org/39/en/Nginx

      https://docs.moodle.org/39/en/Apache

      https://docs.moodle.org/39/en/Internet_Information_Services

      https://docs.moodle.org/39/en/Installing_Moodle#Set_up_your_server

      https://docs.moodle.org/39/en/Installing_AMP

       

       

       

        Attachments

        1. readme present.png
          readme present.png
          8 kB
        2. screenshot-1.png
          screenshot-1.png
          67 kB
        3. Selection_443.png
          Selection_443.png
          86 kB
        4. Undefined indexes.png
          Undefined indexes.png
          107 kB

          Issue Links

            Activity

              People

              Assignee:
              brendanheywood Brendan Heywood
              Reporter:
              brendanheywood Brendan Heywood
              Peer reviewer:
              Peter Burnett
              Integrator:
              Jake Dallimore
              Tester:
              David Mudrák (@mudrd8mz)
              Participants:
              Component watchers:
              Andrew Nicols, Dongsheng Cai, Huong Nguyen, Jun Pataleta, Michael Hawkins, Shamim Rezaie, Simey Lameze
              Votes:
              2 Vote for this issue
              Watchers:
              12 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved:
                Fix Release Date:
                10/May/21

                  Time Tracking

                  Estimated:
                  Original Estimate - 0 minutes
                  0m
                  Remaining:
                  Remaining Estimate - 0 minutes
                  0m
                  Logged:
                  Time Spent - 4 hours
                  4h