How to test which Apache modules are loaded in a shared hosting environment. It can be hard to tell but I think I have found a nice light way. Particularly for shared hosts that are strongly protecting against information leakage on their systems.
Hell my shared host even had “mod_access_compat” disabled. So I can’t even run file allow,deny directives. Admittedly those directives are really confusing and redirects may be easier. I only confirmed that thanks to the code below.
Of course in a shared hosting environment you don’t have access to the apache binary or apachectl so this won’t work:
apachectl -M
apache2ctl -M
ls /etc/apache2
ls /etc/apache2/mods-enabled/
As for PHP options my host had phpinfo() restricted in its output and apache_get_modules() disabled… So I had to look for other options and managed to patch together the .htaccess and PHP combination below. After trying other options like setting a redirect inside of an IfModule statement.
I believe the only requirements for this to work are an enabled mod_env, a working PHP and maybe Apache?
(Of course the server config must have set `AllowOverride` to enable .htaccess to have effect.)
(Which would be typical in a shared hosting environment but by default in Debian it would be off)
(Further in Debian we would need to enable mod_php or configure php5-cgi)
I have tested this on a local Apache server and a shared host with various modules enabled/disabled and it seems to do what is says on the tin ๐
– Create these files in a web server directory.
– Remember to set permissions and executable rights where required.
– Hit the server with a web browser.
.htaccess:
<IfModule mod_env.c> SetEnv MOD_ENV On <IfModule mod_rewrite.c> SetEnv MOD_REWRITE On </IfModule> <IfModule mod_alias.c> SetEnv MOD_ALIAS On </IfModule> <IfModule mod_access_compat.c> SetEnv MOD_ACCESS_COMPAT On </IfModule> <IfModule mod_cgi.c> SetEnv MOD_CGI On </IfModule> <IfModule mod_fcgid.c> SetEnv MOD_FCGID On </IfModule> <IfModule mod_fastcgi.c> SetEnv MOD_FASTCGI On </IfModule> <IfModule mod_wsgi.c> SetEnv MOD_WSGI On </IfModule> <IfModule mod_php4.c> SetEnv MOD_PHP4 On </IfModule> <IfModule mod_php5.c> SetEnv MOD_PHP5 On </IfModule> <IfModule mod_python.c> SetEnv MOD_PYTHON On </IfModule> </IfModule> |
module_check.php:
<?php $mod_env = getenv('MOD_ENV')=='On' ? 'On' : 'Off' ; $mod_rewrite = getenv('MOD_REWRITE')=='On' ? 'On' : 'Off' ; $mod_alias = getenv('MOD_ALIAS')=='On' ? 'On' : 'Off' ; $mod_access_compat = getenv('MOD_ACCESS_COMPAT')=='On' ? 'On' : 'Off' ; $mod_cgi = getenv('MOD_CGI')=='On' ? 'On' : 'Off' ; $mod_fcgid = getenv('MOD_FCGID')=='On' ? 'On' : 'Off' ; $mod_fastcgi = getenv('MOD_FASTCGI')=='On' ? 'On' : 'Off' ; $mod_wsgi = getenv('MOD_WSGI')=='On' ? 'On' : 'Off' ; $mod_php4 = getenv('MOD_PHP4')=='On' ? 'On' : 'Off' ; $mod_php5 = getenv('MOD_PHP5')=='On' ? 'On' : 'Off' ; $mod_python = getenv('MOD_PYTHON')=='On' ? 'On' : 'Off' ; ?> <?php echo "mod_env: $mod_env<br /><br />"; echo "If mod_env is off then none of the following are valid.<br /><br />"; echo "mod_rewrite: $mod_rewrite<br />"; echo "mod_alias: $mod_alias<br />"; echo "mod_access_compat: $mod_access_compat<br />"; echo "mod_cgi: $mod_cgi<br />"; echo "mod_fcgid: $mod_fcgid<br />"; echo "mod_fastcgi: $mod_fastcgi<br />"; echo "mod_wsgi: $mod_wsgi<br />"; echo "mod_php4: $mod_php4<br />"; echo "mod_php5: $mod_php5<br />"; echo "mod_python: $mod_python<br />"; ?> |
Test in a web browser:
http://example.com/module_check.php
As you can see it’s very easy to understand. If mod_env is loaded then we can set some environment variables for each of the modules that are found to be loaded. The PHP script then grabs and echo’s those variables. Giving an easy to read summary of module status.
This would be easy to extend or modify to any module that you are interested in checking.
Errors. If you see something like this in the web browser then PHP is not being run.
"; echo "If mod_env is off then none of the following are valid. "; echo "mod_rewrite: $mod_rewrite "; echo "mod_cgi: $mod_cgi "; echo "mod_fcgid: $mod_fcgid "; echo "mod_fastcgi: $mod_fastcgi "; echo "mod_wsgi: $mod_wsgi "; echo "mod_php4: $mod_php4 "; echo "mod_php5: $mod_php5 "; echo "mod_python: $mod_python "; ?> |
Hope this help you as much as it helped me ๐
You probably want remove the files from the web server once you know which Apache modules are loaded.
Very nice. Thanks
Hi,
Thank you for posting this.
I tried to get it to work in my shared hosting, but no luck.
Is it still up-to-date in 2020?
Hi Pedro,
Yes it’s still relevant and dependent on the requirements stated so far as I know.
Thanks. That helped me a lot. Here’s a slightly improved all-in-one solution as a single .php file that creates the content of the required .htaccess file
Apache mods
function selectText(el) {
var sel = window.getSelection();
var range = document.createRange();
range.selectNodeContents(el);
sel.removeAllRanges();
sel.addRange(range);
}
'MOD_ACCESS_COMPAT',
'mod_actions' => 'MOD_ACTIONS',
'mod_alias' => 'MOD_ALIAS',
'mod_allowmethods' => 'MOD_ALLOWMETHODS',
'mod_asis' => 'MOD_ASIS',
'mod_auth_basic' => 'MOD_AUTH_BASIC',
'mod_auth_digest' => 'MOD_AUTH_DIGEST',
'mod_auth_form' => 'MOD_AUTH_FORM',
'mod_authn_anon' => 'MOD_AUTHN_ANON',
'mod_authn_core' => 'MOD_AUTHN_CORE',
'mod_authn_dbd' => 'MOD_AUTHN_DBD',
'mod_authn_dbm' => 'MOD_AUTHN_DBM',
'mod_authn_file' => 'MOD_AUTHN_FILE',
'mod_authn_socache' => 'MOD_AUTHN_SOCACHE',
'mod_authnz_external' => 'MOD_AUTHNZ_EXTERNAL',
'mod_authnz_fcgi' => 'MOD_AUTHNZ_FCGI',
'mod_authnz_ldap' => 'MOD_AUTHNZ_LDAP',
'mod_authz_core' => 'MOD_AUTHZ_CORE',
'mod_authz_dbd' => 'MOD_AUTHZ_DBD',
'mod_authz_dbm' => 'MOD_AUTHZ_DBM',
'mod_authz_groupfile' => 'MOD_AUTHZ_GROUPFILE',
'mod_authz_host' => 'MOD_AUTHZ_HOST',
'mod_authz_owner' => 'MOD_AUTHZ_OWNER',
'mod_authz_user' => 'MOD_AUTHZ_USER',
'mod_authz_svn' => 'MOD_AUTHZ_SVN',
'mod_autoindex' => 'MOD_AUTOINDEX',
'mod_brotli' => 'MOD_BROTLI',
'mod_buffer' => 'MOD_BUFFER',
'mod_cache' => 'MOD_CACHE',
'mod_cache_disk' => 'MOD_CACHE_DISK',
'mod_cache_socache' => 'MOD_CACHE_SOCACHE',
'mod_cern_meta' => 'MOD_CERN_META',
'mod_cgi' => 'MOD_CGI',
'mod_cgid' => 'MOD_CGID',
'mod_charset_lite' => 'MOD_CHARSET_LITE',
'mod_data' => 'MOD_DATA',
'mod_dav' => 'MOD_DAV',
'mod_dav_fs' => 'MOD_DAV_FS',
'mod_dav_lock' => 'MOD_DAV_LOCK',
'mod_dav_svn' => 'MOD_DAV_SVN',
'mod_dbd' => 'MOD_DBD',
'mod_deflate' => 'MOD_DEFLATE',
'mod_dialup' => 'MOD_DIALUP',
'mod_dir' => 'MOD_DIR',
'mod_dumpio' => 'MOD_DUMPIO',
'mod_echo' => 'MOD_ECHO',
'mod_env' => 'MOD_ENV',
'mod_evasive' => 'MOD_EVASIVE',
'mod_example_hooks' => 'MOD_EXAMPLE_HOOKS',
'mod_expires' => 'MOD_EXPIRES',
'mod_ext_filter' => 'MOD_EXT_FILTER',
'mod_file_cache' => 'MOD_FILE_CACHE',
'mod_filter' => 'MOD_FILTER',
'mod_gnutls' => 'MOD_GNUTLS',
'mod_headers' => 'MOD_HEADERS',
'mod_heartbeat' => 'MOD_HEARTBEAT',
'mod_heartmonitor' => 'MOD_HEARTMONITOR',
'mod_honeypot' => 'MOD_HONEYPOT',
'mod_http2' => 'MOD_HTTP2',
'mod_ident' => 'MOD_IDENT',
'mod_imagemap' => 'MOD_IMAGEMAP',
'mod_include' => 'MOD_INCLUDE',
'mod_info' => 'MOD_INFO',
'mod_isapi' => 'MOD_ISAPI',
'mod_ipblock' => 'MOD_IPBLOCK',
'mod_jk' => 'MOD_JK',
'mod_lbmethod_bybusyness' => 'MOD_LBMETHOD_BYBUSYNESS',
'mod_lbmethod_byrequests' => 'MOD_LBMETHOD_BYREQUESTS',
'mod_lbmethod_bytraffic' => 'MOD_LBMETHOD_BYTRAFFIC',
'mod_lbmethod_heartbeat' => 'MOD_LBMETHOD_HEARTBEAT',
'mod_ldap' => 'MOD_LDAP',
'mod_lisp' => 'MOD_LISP',
'mod_log_config' => 'MOD_LOG_CONFIG',
'mod_log_debug' => 'MOD_LOG_DEBUG',
'mod_log_forensic' => 'MOD_LOG_FORENSIC',
'mod_logio' => 'MOD_LOGIO',
'mod_lua' => 'MOD_LUA',
'mod_access' => 'MOD_ACCESS',
'mod_aspdotnet' => 'MOD_ASPDOTNET',
'mod_auth' => 'MOD_AUTH',
'mod_auth_anon' => 'MOD_AUTH_ANON',
'mod_auth_db' => 'MOD_AUTH_DB',
'mod_auth_dbm' => 'MOD_AUTH_DBM',
'mod_auth_kerb' => 'MOD_AUTH_KERB',
'mod_auth_ldap' => 'MOD_AUTH_LDAP',
'mod_auth_oid' => 'MOD_AUTH_OID',
'mod_authn_alias' => 'MOD_AUTHN_ALIAS',
'mod_authn_default' => 'MOD_AUTHN_DEFAULT',
'mod_authnz_mysql' => 'MOD_AUTHNZ_MYSQL',
'mod_backhand' => 'MOD_BACKHAND',
'mod_balancer' => 'MOD_BALANCER',
'mod_bandwidth' => 'MOD_BANDWIDTH',
'mod_bonjour' => 'MOD_BONJOUR',
'mod_bw' => 'MOD_BW',
'mod_bwlimited' => 'MOD_BWLIMITED',
'mod_c' => 'MOD_C',
'mod_celerity' => 'MOD_CELERITY',
'mod_cidrblock' => 'MOD_CIDRBLOCK',
'mod_csrf' => 'MOD_CSRF',
'mod_define' => 'MOD_DEFINE',
'mod_disk_cache' => 'MOD_DISK_CACHE',
'mod_example' => 'MOD_EXAMPLE',
'mod_extract' => 'MOD_EXTRACT',
'mod_fcgid' => 'MOD_FCGID',
'mod_fastcgi' => 'MOD_FASTCGI',
'mod_flvx' => 'MOD_FLVX',
'mod_frontpage' => 'MOD_FRONTPAGE',
'mod_geoip' => 'MOD_GEOIP',
'mod_gzip' => 'MOD_GZIP',
'mod_h264_streaming' => 'MOD_H264_STREAMING',
'mod_ibm_ssl' => 'MOD_IBM_SSL',
'mod_imap' => 'MOD_IMAP',
'mod_macro' => 'MOD_MACRO',
'mod_maxminddb' => 'MOD_MAXMINDDB',
'mod_mem_cache' => 'MOD_MEM_CACHE',
'mod_mime' => 'MOD_MIME',
'mod_mime_magic' => 'MOD_MIME_MAGIC',
'mod_mono' => 'MOD_MONO',
'mod_musicindex' => 'MOD_MUSICINDEX',
'mod_mysql' => 'MOD_MYSQL',
'mod_negotiation' => 'MOD_NEGOTIATION',
'mod_nsf' => 'MOD_NSF',
'mod_nss' => 'MOD_NSS',
'mod_ntlm' => 'MOD_NTLM',
'mod_ntlm_winbind' => 'MOD_NTLM_WINBIND',
'mod_ntlm2' => 'MOD_NTLM2',
'mod_nw_ssl' => 'MOD_NW_SSL',
'mod_oc4j' => 'MOD_OC4J',
'mod_openpgp' => 'MOD_OPENPGP',
'mod_ossl' => 'MOD_OSSL',
'mod_owa' => 'MOD_OWA',
'mod_pagespeed' => 'MOD_PAGESPEED',
'mod_parrot' => 'MOD_PARROT',
'mod_perl' => 'MOD_PERL',
'mod_php' => 'MOD_PHP',
'mod_psgi' => 'MOD_PSGI',
'mod_python' => 'MOD_PYTHON',
'mod_proxy' => 'MOD_PROXY',
'mod_proxy_connect' => 'MOD_PROXY_CONNECT',
'mod_proxy_fcgi' => 'MOD_PROXY_FCGI',
'mod_proxy_ftp' => 'MOD_PROXY_FTP',
'mod_proxy_html' => 'MOD_PROXY_HTML',
'mod_proxy_http' => 'MOD_PROXY_HTTP',
'mod_qos' => 'MOD_QOS',
'mod_r' => 'MOD_R',
'mod_rails' => 'MOD_RAILS',
'mod_rewrite' => 'MOD_REWRITE',
'mod_rivet' => 'MOD_RIVET',
'mod_ruby' => 'MOD_RUBY',
'mod_security' => 'MOD_SECURITY',
'mod_setenvif' => 'MOD_SETENVIF',
'mod_setenvifplus' => 'MOD_SETENVIFPLUS',
'mod_so' => 'MOD_SO',
'mod_spambot' => 'MOD_SPAMBOT',
'mod_spamhaus' => 'MOD_SPAMHAUS',
'mod_speling' => 'MOD_SPELING',
'mod_ssl' => 'MOD_SSL',
'mod_sslcrl' => 'MOD_SSLCRL',
'mod_sspi' => 'MOD_SSPI',
'mod_status' => 'MOD_STATUS',
'mod_substitute' => 'MOD_SUBSTITUTE',
'mod_suexec' => 'MOD_SUEXEC',
'mod_suphp' => 'MOD_SUPHP',
'mod_throttle' => 'MOD_THROTTLE',
'mod_tidy' => 'MOD_TIDY',
'mod_tile' => 'MOD_TILE',
'mod_torcheck' => 'MOD_TORCHECK',
'mod_unique_id' => 'MOD_UNIQUE_ID',
'mod_upload' => 'MOD_UPLOAD',
'mod_uploader' => 'MOD_UPLOADER',
'mod_userdir' => 'MOD_USERDIR',
'mod_usertrack' => 'MOD_USERTRACK',
'mod_version' => 'MOD_VERSION',
'mod_vhost_alias' => 'MOD_VHOST_ALIAS',
'mod_virgule' => 'MOD_VIRGULE',
'mod_vmd' => 'MOD_VMD',
'mod_whitelist' => 'MOD_WHITELIST',
'mod_wl' => 'MOD_WL',
'mod_wl_20' => 'MOD_WL_20',
'mod_wl_22' => 'MOD_WL_22',
'mod_wl_24' => 'MOD_WL_24',
'mod_wsgi' => 'MOD_WSGI',
'mod_xsendfile' => 'MOD_XSENDFILE',
'mod_xml2enc' => 'MOD_XML2ENC',
'mod_xml' => 'MOD_XML',
'mod_xslt' => 'MOD_XSLT',
'mod_xml_curl' => 'MOD_XML_CURL',
'mod_xmlrpc' => 'MOD_XMLRPC',
'mod_xrv' => 'MOD_XRV',
'mod_zlib' => 'MOD_ZLIB',
];
$colors = [
'On' => '#20CC20',
'Off' => '#CC2020',
];
$mod_env = getenv('MOD_ENV') == 'On' ? 'On' : 'Off';
$modStatusContent = [];
$htaccessContent = [];
echo "mod_env: $mod_env";
echo "If mod_env is off then none of the following are valid.";
echo "\nStatus of mods\n";
foreach ($mods as $modName => $modEnv) {
$enabled = getenv($modEnv) ?: 'Off';
$modStatusContent[$enabled][] = "$modName: $enabled";
$htaccessContent[] = "<IfModule {$modName}.c>";
$htaccessContent[] = " SetEnv {$modEnv} On";
$htaccessContent[] = "</IfModule>";
}
echo implode("\n", $modStatusContent['On'] ?? []);
echo implode("\n", $modStatusContent['Off'] ?? []);
echo "\n";
$htaccess = implode("\n", $htaccessContent);
echo <<<HTML
.htaccess
{$htaccess}
HTML;
?>
I haven’t tried this but it looks good, thanks for sharing Dominik.