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 ✅