moodle

Moodle is a free and open-source learning management system written in PHP and distributed under the GNU General Public License.

Apache

moodle_headers
# 2/5/2025
    Header always set Referrer-Policy "strict-origin-when-cross-origin"
    Header always set X-Content-Type-Options nosniff
    Header always set X-XSS-Protection "1; mode=block"
# 23/8/2025
    Header always set Permissions-Policy "accelerometer=(), camera=(), gyroscope=(), magnetometer=(), microphone=(), midi=(), usb=(), gamepad=(), serial=()"
    Header always append Content-Security-Policy "frame-ancestors 'self'"
moodle
    AcceptPathInfo On
    RewriteEngine on
    RewriteCond %{HTTP_USER_AGENT} ^(.*)Nmap(.*)$
    RewriteRule .* - [F]
    RewriteCond %{HTTP_USER_AGENT} ^(.*)Chrome/..\.(.*)$
    RewriteRule .* - [F]
    RewriteCond %{HTTP_USER_AGENT} ^(.*)Firefox/..\.(.*)$
    RewriteRule .* - [F]
    RewriteRule /\xef\xbb\xbf	/ [R=301,L,NE]
    RewriteRule "(\/behat\.yml\.dist)" - [L,R=404]
    RewriteRule "(composer\.json)" - [L,R=404]
    RewriteRule "(CONTRIBUTING\.md)" - [L,R=404]
    RewriteRule "(\/environment\.xml)" - [L,R=404]
    RewriteRule "(\/fixtures\/)" - [L,R=404]
    RewriteRule "(\/Gruntfile.js)" - [L,R=404]
    RewriteRule "(\/INSTALL\.txt)" - [L,R=404]
    RewriteRule "(\/install\.xml)" - [L,R=404]
    RewriteRule "(\.lock)" - [L,R=404]
    RewriteRule "(\/moodle_readme)" - [L,R=404]
    RewriteRule "(\/node_modules\/)" - [L,R=404]
    RewriteRule "(\/npm-shrinkwrap.json)" - [L,R=404]
    RewriteRule "\/package\.json" - [L,R=404]
    RewriteRule "(phpunit\.xml\.dist)" - [L,R=404]
    RewriteRule "(\/readme)" - [L,R=404]
    RewriteRule "(\/README)" - [L,R=404]
    RewriteRule "(\/tests\/behat\/)" - [L,R=404]
    RewriteRule "\/TRADEMARK.txt" - [L,R=404]
    RewriteRule "(\/upgrade\.txt)" - [L,R=404]
    RewriteRule "\/UPGRADING\.md" - [L,R=404]
    RewriteRule "(\/vendor\/)" - [L,R=404]
    RewriteRule "(^|/)\.(?!well-known\/)" - [L,R=404]

Audit

https://moodle.cgsecurity.org/report/security/index.php

moodle_check.py
#!/usr/bin/python3
import requests

def check_moodle(s, site):
    r = s.get(site)
    ok = 'Moodle' in r.text and r.status_code == 200
    print(r.url.ljust(32), r.status_code, 'Moodle' if 'Moodle' in r.text else '?', '✅' if ok else '❌')
    assert ok


ua = 'Firefox/123.4'
s = requests.session()
s.headers.update({'User-Agent': ua})

site = 'https://moodle.cgsecurity.org/'
check_moodle(s, site)

for filename in [
    'robots.txt',
    '.well-known/security.txt',
    ]:
    url = site + filename
    status_code = s.get(url).status_code 
    print(filename.ljust(32), status_code, '✅' if status_code == 200 else '❌')

for filename in [
	'behat.yml.dist',
	'composer.json',
	'composer.lock',
	'CONTRIBUTING.md',
	'.eslintrc',
	'.gherkin-lintrc',
	'.gitattributes',
	'Gruntfile.js',
	'INSTALL.txt',
	'.jshintignore',
	'.jshintrc',
	'npm-shrinkwrap.json',
	'.nvmrc',
	'package.json',
	'README.md',
	'.shifter.json',
	'.stylelintrc',
	'TRADEMARK.txt',
	'UPGRADING.md',
]:
    url = site + filename
    status_code = s.get(url).status_code 
    print(filename.ljust(32), status_code, '✅' if status_code in (403, 404) else '❌')
moodle_check.py output
https://moodle.cgsecurity.org/   200 Moodle ✅
robots.txt                       200 ✅
.well-known/security.txt         200 ✅
behat.yml.dist                   404 ✅
composer.json                    404 ✅
composer.lock                    404 ✅
CONTRIBUTING.md                  404 ✅
.eslintrc                        404 ✅
.gherkin-lintrc                  404 ✅
.gitattributes                   404 ✅
Gruntfile.js                     404 ✅
INSTALL.txt                      404 ✅
.jshintignore                    404 ✅
.jshintrc                        404 ✅
npm-shrinkwrap.json              404 ✅
.nvmrc                           404 ✅
package.json                     404 ✅
README.md                        404 ✅
.shifter.json                    404 ✅
.stylelintrc                     404 ✅
TRADEMARK.txt                    404 ✅
UPGRADING.md                     404 ✅