Check_apache_security

Script: check_apache_security

Check if

  • Http version is 2 or higher
  • Security headers are set

Requirements

  • Apache httpd
  • sudo permissions on apache binary (/usr/sbin/apache2 on Debian or /sbin/httpd on Redhat like systems)
  • curl
  • Linux (tested on Debian 11+12, Alma Linux, Rocky Linux)

Sudo permissions for Debian:

icingaclient ALL=(ALL) NOPASSWD: /usr/sbin/apache2

… and Redhat like distribtions:

icingaclient ALL=(ALL) NOPASSWD: /sbin/httpd

Standalone installation

From this repository you need next to this script:

  • inc_pluginfunctions shared function for all IML checks written in bash

Syntax

______________________________________________________________________

CHECK_APACHE_SECURITY
v0.6

(c) Institute for Medical Education - University of Bern
Licence: GNU GPL 3

https://os-docs.iml.unibe.ch/icinga-checks/Checks/check_apache_security.html
______________________________________________________________________

The check tests
- http security headers
- http version 2 or above

It switches to critical if 
- http version is too old or 
- no security header was set

SYNTAX:

    check_apache_security [OPTIONS] [URL [... URL_N]]

OPTIONS:

    -h, --help             show this help.

    -b, --binary <FILE>    Custom Apache httpd binary
    -p, --port <NUMBER>    SSL port to check; default: 443
    -r, --noresponse       hide response header
    -s, --nosecurity       hide found security headers
    -x, --exclude <VHOST>  Exclude vhost from analysis of http2
                           of security headers. Only its result
                           is shown.

PARAMETERS:

    List of override urls.
    A given url will be handled only if it matches a found servername.

EXAMPLES:

    check_apache_security
        Full expanded view with tested webs and found headers

    check_apache_security -r -s
        Minimal view

    check_apache_security -r -x cug.example.com
        Long view with security but no response header.
        The vhost 'cug.example.com' will be tested as well and shown
        but non http response or missing security header have no
        impact in the result of the check.

Examples

Default view

By default check_apache_requests You get an output with

  • Status line with result status, number of webs and number of webs with errors
  • A short status for each web as a single line
  • A detailed section for each tested web showing
    • tested url (https://[servername] or given override url)
    • http version and status code
    • security headers
    • all headers
    • ip address (it comes from ping command - it isn’t a complete value of DNS)
OK: Apache: Websites: 1 - Errors: 0

testweb.iml.unibe.ch - HTTP/2 200  -> version 2 (OK) ... security headers: 5 (OK) - IP 130.92.__.__ (OK)


>>>>> Details:

--- https://testweb.iml.unibe.ch/ 
- HTTP/2 200  --> version 2 - (OK) 
- security headers: 5 (OK) 
    content-security-policy: frame-ancestors 'self'
    x-content-type-options: nosniff
    feature-policy: sync-xhr 'self'
    referrer-policy: strict-origin-when-cross-origin
    strict-transport-security: max-age=63072000; includeSubDomains; preload
- all headers:
    HTTP/2 200 
    content-security-policy: frame-ancestors 'self'
    x-content-type-options: nosniff
    x-xss-protection: 1; mode=block
    feature-policy: sync-xhr 'self'
    referrer-policy: strict-origin-when-cross-origin
    strict-transport-security: max-age=63072000; includeSubDomains; preload
    content-type: text/html; charset=UTF-8
    date: Tue, 11 Nov 2025 16:05:00 GMT
    server: Apache
- IP: 130.92.___.___

Minimal view

You can remove the whole detail secion with removing both header types using -s -r

check_apache_requests -r -s

Output example:

CRITICAL: Apache: Websites: 2 - Errors: 1

www.example.com - HTTP/2 200  -> version 2 (OK) ... security headers: 0 (CRITICAL) No security header was found - IP 130.92.__.__ (OK)
blog.example.com - HTTP/2 200  -> version 2 (OK) ... security headers: 5 (OK) - IP 130.92.__.__ (OK)

Remark: You don’t see the used override url here.

Override url

By default https://[servername] is tested. If it is a redirect page eg. to a login on another url using a 40x status then maybe you have no redirect here, but on another url. Curl doesn’t follow the lovcation header. You must set a url for this hostname to override the default url.

check_apache_requests "https://www.example.com/somewhere/else/index.php"

If you have multiple vhosts on your machine the given url will override the vhost for “www.example.com” only.

Exclude vhosts with errors

If you have a protected web protected from / the check might fail when urls offer only 40x errors without security header. With the exclude option -x [VHOST] you get all vhosts in the output but don’t get a negative result coming from the exclude vhost.

check_apache_requests -x www.example.com

The host is marked with SKIPPED markers in the output.

OK: Apache: Websites: 2 - Errors: 0

www.example.com - HTTP/2 200  -> version 2 ... security headers: 0 - SKIPPED 
blog.example.com - HTTP/2 200  -> version 2 (OK) ... security headers: 5 (OK) 

(...)