Protect against XML DOS attacks

Only XML content from authenticated users is parsed.
This commit is contained in:
Unrud 2020-01-19 18:39:31 +01:00
parent 562d3aacec
commit e11661ff3e
3 changed files with 6 additions and 4 deletions

View File

@ -37,6 +37,7 @@ import zlib
from http import client from http import client
from xml.etree import ElementTree as ET from xml.etree import ElementTree as ET
import defusedxml.ElementTree as DefusedET
import pkg_resources import pkg_resources
from radicale import (auth, httputils, log, pathutils, rights, storage, web, from radicale import (auth, httputils, log, pathutils, rights, storage, web,
@ -355,7 +356,7 @@ class Application(
if not content: if not content:
return None return None
try: try:
xml_content = ET.fromstring(content) xml_content = DefusedET.fromstring(content)
except ET.ParseError as e: except ET.ParseError as e:
logger.debug("Request content (Invalid XML):\n%s", content) logger.debug("Request content (Invalid XML):\n%s", content)
raise RuntimeError("Failed to parse XML: %s" % e) from e raise RuntimeError("Failed to parse XML: %s" % e) from e

View File

@ -26,9 +26,9 @@ import posixpath
import shutil import shutil
import sys import sys
import tempfile import tempfile
import xml.etree.ElementTree as ET
from functools import partial from functools import partial
import defusedxml.ElementTree as DefusedET
import pytest import pytest
from radicale import Application, config, storage from radicale import Application, config, storage
@ -1161,7 +1161,7 @@ class BaseRequestsMixIn:
if sync_token and status == 409: if sync_token and status == 409:
return None, None return None, None
assert status == 207 assert status == 207
xml = ET.fromstring(answer) xml = DefusedET.fromstring(answer)
sync_token = xml.find("{DAV:}sync-token").text.strip() sync_token = xml.find("{DAV:}sync-token").text.strip()
assert sync_token assert sync_token
return sync_token, xml return sync_token, xml

View File

@ -73,7 +73,8 @@ setup(
exclude=["*.tests", "*.tests.*", "tests.*", "tests"]), exclude=["*.tests", "*.tests.*", "tests.*", "tests"]),
package_data={"radicale": WEB_FILES}, package_data={"radicale": WEB_FILES},
entry_points={"console_scripts": ["radicale = radicale.__main__:run"]}, entry_points={"console_scripts": ["radicale = radicale.__main__:run"]},
install_requires=["passlib", "vobject>=0.9.6", "python-dateutil>=2.7.3"], install_requires=["defusedxml", "passlib", "vobject>=0.9.6",
"python-dateutil>=2.7.3"],
setup_requires=pytest_runner, setup_requires=pytest_runner,
tests_require=tests_require, tests_require=tests_require,
extras_require={ extras_require={