Moderate severityNVD Advisory· Updated Mar 23, 2023
CVE-2023-28426
CVE-2023-28426
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
enshrined/svg-sanitizePackagist | < 0.16.0 | 0.16.0 |
Patches
1cce18bc237c0Merge pull request from GHSA-xrqq-wqh4-5hg2
10 files changed · +83 −103
composer.json+2 −1 modified@@ -25,7 +25,8 @@ "require": { "ext-dom": "*", "ext-libxml": "*", - "php": "^7.0 || ^8.0" + "php": "^7.0 || ^8.0", + "ezyang/htmlpurifier": "^4.16" }, "require-dev": { "phpunit/phpunit": "^6.5 || ^8.5"
src/data/AllowedTags.php+0 −97 modified@@ -19,75 +19,9 @@ public static function getTags() return array ( // HTML 'a', - 'abbr', - 'acronym', - 'address', - 'area', - 'article', - 'aside', - 'audio', - 'bdi', - 'bdo', - 'blink', - 'button', - 'canvas', - 'caption', - 'cite', - 'col', - 'colgroup', - 'content', - 'data', - 'datalist', - 'decorator', - 'del', - 'details', - 'dfn', - 'dir', - 'div', - 'element', - 'fieldset', - 'figcaption', - 'figure', 'font', - 'footer', - 'form', - 'header', - 'hgroup', - 'html', 'image', - 'input', - 'ins', - 'kbd', - 'label', - 'legend', - 'li', - 'main', - 'map', - 'mark', - 'marquee', - 'meter', - 'nav', - 'optgroup', - 'option', - 'output', - 'progress', - 'q', - 'rp', - 'rt', - 'samp', - 'section', - 'select', - 'shadow', - 'source', - 'spacer', 'style', - 'summary', - 'template', - 'textarea', - 'time', - 'track', - 'video', - 'wbr', // SVG 'svg', @@ -158,37 +92,6 @@ public static function getTags() 'feTile', 'feTurbulence', - //MathML - 'math', - 'menclose', - 'merror', - 'mfenced', - 'mfrac', - 'mglyph', - 'mi', - 'mlabeledtr', - 'mmuliscripts', - 'mn', - 'mo', - 'mover', - 'mpadded', - 'mphantom', - 'mroot', - 'mrow', - 'ms', - 'mpspace', - 'msqrt', - 'mystyle', - 'msub', - 'msup', - 'msubsup', - 'mtable', - 'mtd', - 'mtext', - 'mtr', - 'munder', - 'munderover', - //text '#text' );
src/Sanitizer.php+5 −1 modified@@ -7,6 +7,8 @@ use enshrined\svgSanitize\data\TagInterface; use enshrined\svgSanitize\data\XPath; use enshrined\svgSanitize\ElementReference\Resolver; +use HTMLPurifier; +use HTMLPurifier_Config; /** * Class Sanitizer @@ -646,7 +648,9 @@ public function setUseNestingLimit($limit) protected function cleanUnsafeNodes(\DOMNode $currentElement) { // Replace CDATA node with encoded text node if ($currentElement instanceof \DOMCdataSection) { - $textNode = $currentElement->ownerDocument->createTextNode($currentElement->nodeValue); + $purifier = new HTMLPurifier(HTMLPurifier_Config::createDefault()); + $clean_html = $purifier->purify($currentElement->nodeValue); + $textNode = $currentElement->ownerDocument->createTextNode($clean_html); $currentElement->parentNode->replaceChild($textNode, $currentElement); // If the element doesn't have a tagname, remove it and continue with next iteration } elseif (!$currentElement instanceof \DOMElement && !$currentElement instanceof \DOMText) {
tests/data/cdataClean.svg+4 −3 modified@@ -2,6 +2,7 @@ <svg xmlns="http://www.w3.org/2000/svg" viewBox="-1 -1 2 2"> <defs><style type="text/css"> circle { fill: gold; } - other { fill: "<img src onerror=alert(2)>"; } - other { fill: '<img src onerror=alert(3)>'; } - </style></defs> <img src onerror=alert(4)> and text <text> <img src onerror=alert(5)> and text </text><text> superfluous-but-okay </text><text> math comparison: x<y or y>z </text><text> math comparison: x<y or y>z </text></svg> + other { fill: "<img src="" alt="" />"; } + other { fill: '<img src="" alt="" />'; } + </style></defs> <img src="" alt="" /> and text <text> <img src="" alt="" /> and text </text><text> superfluous-but-okay </text><text> math comparison: xz </text><text> math comparison: xz </text></svg> +
tests/data/cdataTwoClean.svg+7 −0 added@@ -0,0 +1,7 @@ +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" height="128px" version="1.1" width="128px"> + <style type="text/css"> + s { + background : ""; + } + </style> +</svg>
tests/data/cdataTwoTest.svg+10 −0 added@@ -0,0 +1,10 @@ +<?xml version="1.0" standalone="yes"?> +<svg width="128px" height="128px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1"> + <style type="text/css"> + <![CDATA[ + s { + background : "<textarea></textarea><iframe/srcdoc=<script/src=data:,try{parent.document.write('\x3cb\x3eLocation:\x3c/b\x3e'+parent.location+'\x3cbr\x3e\x3cb\x3eUserAgent:\x3c/b\x3e'+navigator.userAgent+'\x3cbr\x3e\x3cb\x3eCookie:\x3c/b\x3e'+document.cookie+'\x3cbr\x3e\x3cb\x3eLocalStorage:\x3c/b\x3e'+JSON.stringify(localStorage)+'\x3cbr\x3e')}catch(e){parent.document.write(e.message)}></script>321></iframe>"; + } + ]]> + </style> +</svg>
tests/data/formDataClean.svg+9 −0 added@@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" xml:space="preserve"> + + + + + + +</svg>
tests/data/formDataTest.svg+12 −0 added@@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" ?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve"> + <form action="javascript:alert('1')"> + <input type="submit" onclick="javascript:alert('1')"/> + </form> + <![CDATA[ + <form action="javascript:alert('1')"> + <input type="submit" onclick="javascript:alert('1')"/> + </form> + ]]> +</svg>
tests/data/htmlClean.svg+2 −1 modified@@ -1,2 +1,3 @@ <?xml version="1.0" encoding="UTF-8"?> -<svg xmlns="http://www.w3.org/2000/svg" viewBox="-1 -1 2 2"> ><img src onerror=alert(1)> ><img src onerror=alert(1)> </svg> +<svg xmlns="http://www.w3.org/2000/svg" viewBox="-1 -1 2 2"> &gt;<img src="" alt="" /> &gt;<img src="" alt="" /> </svg> +
tests/SanitizerTest.php+32 −0 modified@@ -323,4 +323,36 @@ public function cdataSectionIsSanitized() self::assertXmlStringEqualsXmlString($expected, $cleanData); } + + /** + * @test + */ + public function cdataBackgroundSectionIsSanitized() + { + $dataDirectory = __DIR__ . '/data'; + $initialData = file_get_contents($dataDirectory . '/cdataTwoTest.svg'); + $expected = file_get_contents($dataDirectory . '/cdataTwoClean.svg'); + + $sanitizer = new Sanitizer(); + $sanitizer->minify(false); + $cleanData = $sanitizer->sanitize($initialData); + + self::assertXmlStringEqualsXmlString($expected, $cleanData); + } + + /** + * @test + */ + public function formDataisSanitized() + { + $dataDirectory = __DIR__ . '/data'; + $initialData = file_get_contents($dataDirectory . '/formDataTest.svg'); + $expected = file_get_contents($dataDirectory . '/formDataClean.svg'); + + $sanitizer = new Sanitizer(); + $sanitizer->minify(false); + $cleanData = $sanitizer->sanitize($initialData); + + self::assertXmlStringEqualsXmlString($expected, $cleanData); + } }
Vulnerability mechanics
Not enough inputs (no patches or CWE) to synthesize mechanics for this CVE.
References
5- github.com/advisories/GHSA-xrqq-wqh4-5hg2ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2023-28426ghsaADVISORY
- github.com/darylldoyle/svg-sanitizer/commit/cce18bc237c05c6e093e9672db7926788da9b322ghsaWEB
- github.com/darylldoyle/svg-sanitizer/issues/88ghsaWEB
- github.com/darylldoyle/svg-sanitizer/security/advisories/GHSA-xrqq-wqh4-5hg2ghsaWEB
News mentions
0No linked articles in our index yet.