Module: check_mk
Branch: master
Commit: 6d3e2053bec133feececea674d4baf45d43f88f2
URL:
http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=6d3e2053bec133…
Author: Lars Michelsen <lm(a)mathias-kettner.de>
Date: Wed Feb 20 07:47:21 2019 +0100
7174 SEC Apache: Disable TRACE and OPTIONS method
The similar TRACK method is not supported by the site apache at all, so
it does not have to be disabled.
A lot of guides recommend to also disable the OPTIONS method for
production servers. This HTTP method basically reports which HTTP
Methods that are allowed on the web server. In reality, this is rarely
used for legitimate purposes, but it may grant a potential attacker a
little bit of help and it can be considered a shortcut to find another
hole. For this reason we also disabled the OPTIONS method.
CMK-1639
Change-Id: I57a0b47ba8f7fb2ae0d974ed5383afe56c5418af
---
.werks/7174 | 22 ++++++++++++++++
.../skel/etc/apache/conf.d/security.conf | 13 ++++++++++
tests/integration/omd/test_web_access.py | 21 +++++++++++++++-
tests/testlib/__init__.py | 29 ++++++----------------
4 files changed, 62 insertions(+), 23 deletions(-)
diff --git a/.werks/7174 b/.werks/7174
new file mode 100644
index 0000000..7154308
--- /dev/null
+++ b/.werks/7174
@@ -0,0 +1,22 @@
+Title: Apache: Disable TRACE and OPTIONS methods
+Level: 1
+Component: omd
+Compatible: compat
+Edition: cre
+Version: 1.6.0i1
+Date: 1550645011
+Class: security
+
+The HTTP method TRACE makes some kind of reflection attacks possible and is not
+used at all. It has been enabled for the site apache using the option
+<tt>TraceEnable Off</tt> in etc/apache/conf.d/security.conf.
+
+The similar TRACK method is not supported by the site apache at all, so it does
+not have to be disabled.
+
+A lot of guides recommend to also disable the OPTIONS method for production
+servers. This HTTP method basically reports which HTTP Methods that are
+allowed on the web server. In reality, this is rarely used for legitimate
+purposes, but it may grant a potential attacker a little bit of help and it
+can be considered a shortcut to find another hole. For this reason we also
+disabled the OPTIONS method.
diff --git a/omd/packages/apache-omd/skel/etc/apache/conf.d/security.conf
b/omd/packages/apache-omd/skel/etc/apache/conf.d/security.conf
index 54635fd..a334f3e 100644
--- a/omd/packages/apache-omd/skel/etc/apache/conf.d/security.conf
+++ b/omd/packages/apache-omd/skel/etc/apache/conf.d/security.conf
@@ -43,3 +43,16 @@
# Provide minimal information about the running software version and platform to clients
ServerTokens Prod
+
+# Disable TRACE request method to prevent some kind of reflection attack
+TraceEnable Off
+
+# This has been added to disable the OPTIONS method globally, but it also disables all
other
+# methods than GET, POST, HEAD. We may need to adapt this in the future once we use
other
+# methods
+<Directory "/">
+ <LimitExcept GET POST HEAD>
+ order deny,allow
+ deny from all
+ </LimitExcept>
+</Directory>
diff --git a/tests/integration/omd/test_web_access.py
b/tests/integration/omd/test_web_access.py
index ddcebd5..77426d1 100644
--- a/tests/integration/omd/test_web_access.py
+++ b/tests/integration/omd/test_web_access.py
@@ -1,7 +1,8 @@
#!/usr/bin/env python
# encoding: utf-8
-from testlib import CMKWebSession, web
+from testlib import CMKWebSession
+
def test_www_dir(site):
web = CMKWebSession(site)
@@ -82,3 +83,21 @@ def test_cmk_ajax_graph_images(site):
web = CMKWebSession(site)
response = web.get("/%s/check_mk/ajax_graph_images.py" % site.id)
assert response.text == ""
+
+
+def test_trace_disabled(site):
+ web = CMKWebSession(site)
+ # TRACE is disabled by using "TraceEnable Off" in apache config
+ web._request("TRACE", "/", expected_code=405)
+
+
+def test_track_disabled(site):
+ web = CMKWebSession(site)
+ # TRACE is not supported by apache at all by apache, so there is no need to
+ # disable this. The HTTP code is just different from TRACE.
+ web._request("TRACK", "/", expected_code=403)
+
+
+def test_options_disabled(site):
+ web = CMKWebSession(site)
+ web._request("OPTIONS", "/", expected_code=403)
diff --git a/tests/testlib/__init__.py b/tests/testlib/__init__.py
index 7c30f6f..f4fb541 100644
--- a/tests/testlib/__init__.py
+++ b/tests/testlib/__init__.py
@@ -976,11 +976,6 @@ class WebSession(requests.Session):
if expect_redirect:
kwargs["allow_redirects"] = False
- if method == "post":
- func = super(WebSession, self).post
- else:
- func = super(WebSession, self).get
-
# May raise "requests.exceptions.ConnectionError: ('Connection
aborted.', BadStatusLine("''",))"
# suddenly without known reason. This may be related to some
# apache or HTTP/1.1 issue when working with keepalive connections. See
@@ -988,10 +983,10 @@ class WebSession(requests.Session):
#
https://github.com/mikem23/keepalive-race
# Trying to workaround this by trying the problematic request a second time.
try:
- response = func(url, **kwargs)
+ response = super(WebSession, self).request(method, url, **kwargs)
except requests.ConnectionError as e:
if allow_retry and "Connection aborted" in "%s" % e:
- response = func(url, **kwargs)
+ response = super(WebSession, self).request(method, url, **kwargs)
else:
raise
@@ -1506,9 +1501,7 @@ class CMKWebSession(WebSession):
def get_site(self, site_id):
result = self._api_request(
"webapi.py?action=get_site&request_format=python&output_format=python",
- {"request": json.dumps({
- "site_id": site_id
- })},
+ {"request": json.dumps({"site_id": site_id})},
output_format="python")
assert result != None
@@ -1523,9 +1516,7 @@ class CMKWebSession(WebSession):
def delete_site(self, site_id):
result = self._api_request(
"webapi.py?action=delete_site&output_format=python",
- {"request": json.dumps({
- "site_id": site_id
- })},
+ {"request": json.dumps({"site_id": site_id})},
output_format="python")
assert result is None
@@ -1571,24 +1562,18 @@ class CMKWebSession(WebSession):
def add_htpasswd_users(self, users):
result = self._api_request("webapi.py?action=add_users",
- {"request": json.dumps({
- "users": users
- })})
+ {"request": json.dumps({"users":
users})})
assert result is None
def edit_htpasswd_users(self, users):
result = self._api_request("webapi.py?action=edit_users",
- {"request": json.dumps({
- "users": users
- })})
+ {"request": json.dumps({"users":
users})})
assert result is None
def delete_htpasswd_users(self, userlist):
result = self._api_request("webapi.py?action=delete_users", {
- "request": json.dumps({
- "users": userlist
- }),
+ "request": json.dumps({"users": userlist}),
})
assert result is None