{"id":831,"date":"2019-04-05T04:48:27","date_gmt":"2019-04-05T04:48:27","guid":{"rendered":"http:\/\/reichartonline.de\/?page_id=831"},"modified":"2022-12-19T18:52:02","modified_gmt":"2022-12-19T18:52:02","slug":"xss-protection","status":"publish","type":"page","link":"https:\/\/reichartonline.de\/?page_id=831","title":{"rendered":"XSS protection"},"content":{"rendered":"\n<h4 class=\"wp-block-heading\">Why &#8220;protection&#8221; rather than &#8220;prevention&#8221;?<\/h4>\n\n\n\n<p>Simply because it wouldn\u00b4t be realistic. Effective XSS (abbreviation to <em>Cross-site Scripting<\/em>) prevention is very hard to get. That\u00b4s why you\u00b4ll find security advisories describing XSS vulnerabilities even for the most popular software products providing a web-based user interface. This article intends to show you why that\u00b4s the case.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">The essential step to approach XSS &#8220;protection&#8221;<\/h4>\n\n\n\n<p>Like with all, it\u00b4s comprehension. &#8220;Cross-site&#8221; refers to the fact, that the web server sends data to the client, &#8220;Scripting&#8221; details that such data could be executed by the client (but not by the server itself). But in order for a web server to send executable code to the client, this data first has to get to the server. Either by being programmed as part of the web application the server provides or &#8230; sent to the server by a client!<br><br>This understanding brings two basic concepts to the mind<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>What kind of data a (web) client executes that a (web) server does not? It must be the currently most widely-spread programming language: <a href=\"https:\/\/reichartonline.de\/?page_id=56\">JavaScript<\/a> (JS). The potential harm running untrustworthy JS code is infinite as JS is virtually omnipotent.<\/li>\n\n\n\n<li>If data has to be stored on the (web) server before it can unleash its potential harm to clients, it needs to be considered which data is worth being trusted and which is not<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\">Untrustworthy data sanitization<\/h4>\n\n\n\n<p>Which data can be deemed to be trustworthy? Only the one that is fully under control of your party. Typically this is your program code (provided you\u00b4ve conducted adequate quality checks). Nothing else!<br><br>Second, there might be code of other parties used by your own code. You may check the quality of such code as well and &#8211; if it proofs to be secure &#8211; trust it (on a per-release basis).<br><br>Third, there is (arbitrary) data generated by the clients (users) that your party has no control about. As a consequence, such data is always(!) untrustworthy and logically in scope of XSS protection.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Usages of untrustworthy data<\/h4>\n\n\n\n<p>Having deduced the data in scope, currently there are three ways to use such data in web UIs presented by a browser and thus potentially prone to XSS<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Display the data as text, in text inputs (incl. text areas) or select boxes<\/li>\n\n\n\n<li>Use the data as part of generated <a href=\"https:\/\/reichartonline.de\/?page_id=56\">JS<\/a> code<\/li>\n\n\n\n<li>Use the data as part of generated Cascaded Style Sheets (<a href=\"https:\/\/reichartonline.de\/?page_id=53\">CSS<\/a>)<\/li>\n<\/ul>\n\n\n\n<p>In order to consider the attack surface of your application, will you need untrustworthy data to be part of generated CSS? Probably not. Will you need untrustworthy data to be part of generated JS? Probably yes. Will you need to display untrustworthy data within your web UI? Definitely!<br>So we have made our priorities clear. Why is that important? Because each of these cases requires a different approach to XSS protection.<br><br>Consequently, this article will focus on the top priority, which is displaying untrustworthy data as HTML.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Display untrustworthy data as HTML text<\/h4>\n\n\n\n<p>Depending on the main use case of your application, there are two basic strategies to approach XSS protection<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>If your application is to be used just to process basic text (no potentially malicious special characters (&#8216;, &#8220;, &lt;, &gt;), no line feeds, tabs etc., then the easiest and most effective approach is to delete all unsupported characters from untrustworthy data <strong>before<\/strong> persisting the same (XSS input sanitization). The result could even be referred to as an XSS &#8220;prevention&#8221; as there is nothing left that could be exploited<\/li>\n\n\n\n<li>If your application is to be used to process untrustworthy data exactly the way it has been entered by users (blogs, descriptions including code snippets, emojicons etc.), then things get far more complicated<\/li>\n<\/ul>\n\n\n\n<p>Consequently, this article will focus on the latter (thus more interesting) case. By the way: the software powering this web site is such an application.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">No XSS input sanitization<\/h4>\n\n\n\n<p>If you must display untrustworthy data exactly the way it has been entered by users, the logical consequence is that you wouldn\u00b4t want to touch them when persisting the same. This implies that your persistence layer may contain potentially (XSS) malicious data (not to be confused with SQL injection, whose input sanitization is always mandatory (but that\u00b4s another story out of scope of this article). So the persisted data remains perfectly <strong>untrustworthy<\/strong>.<br>Subsequently, whenever data is extracted, it needs to be properly XSS sanitized <strong>before<\/strong> being output to a web UI.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">XSS output sanitization<\/h4>\n\n\n\n<p>&#8220;Web&#8221; UI means that data is output to (X)HTML, so regarding XSS some aspects of HTML are good to be known. Not all HTML elements use the same syntax pattern with regards to the position of data to be displayed<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li> Text inputs define the output value in a <em>value<\/em> attribute<\/li>\n\n\n\n<li>Text areas and select options enclose the output value between their start and end tags<\/li>\n<\/ul>\n\n\n\n<p>Good news might be that modern web browsers automatically sanitize the values of the <em>value<\/em> attributes. But attackers are smart enough to break that mitigation. As every string requires delimiters, the same may be used to intentionally end a string previously input followed by malicious (JavaScript) code.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Break the implicit XSS mitigation on output values<\/h4>\n\n\n\n<p>Following a classic HTML example<\/p>\n\n\n\n<p class=\"has-vivid-cyan-blue-color has-text-color\">&lt;input type=&#8221;text&#8221; value=&#8221;some output data&#8221;&gt;<\/p>\n\n\n\n<p>That code displays a text input field holding the value <em>some output value<\/em>. Typically it is part of a web form that sends the data entered to the server on submit. According to the approach described above the web server will not XSS sanitize that value before persisting it. If the application grants users to edit their data, the form is loaded and the inputs are pre-populated with the existing values requested from the persistence layer. And we rely on the browser to sanitize them&#8230;<br><br>Now imagine an attacker entering the following value into the text field<\/p>\n\n\n\n<p class=\"has-vivid-cyan-blue-color has-text-color\">&#8221; &lt;script&gt;alert(&#8220;XSS!&#8221;)&lt;\/script&gt;<\/p>\n\n\n\n<p>and sending it to the server which stores it unchanged. When opening the edit form, this value will be loaded which causes the browser to parse the following code<\/p>\n\n\n\n<p class=\"has-vivid-cyan-blue-color has-text-color\">&lt;input type=&#8221;text&#8221; value=&#8221;&#8221; &lt;script&gt;alert(&#8220;XSS!&#8221;)&lt;\/script&gt;&#8221;&gt;<\/p>\n\n\n\n<p>Wow! The leading double quotes terminate the value of the <em>value<\/em> attribute and the following code is proper JS which will run like a charm popping up the message <em>XSS!<\/em>. XSS in action&#8230;<br><\/p>\n\n\n\n<h4 class=\"wp-block-heading\">How to XSS output sanitize<\/h4>\n\n\n\n<p>Fortunately, HTML offers means to overcome such &#8220;misinterpretations&#8221;. Any potentially ambiguous or special character has a unique literal referred to as an <a href=\"https:\/\/dev.w3.org\/html5\/html-author\/charref\">HTML entity<\/a>. By replacing each ambiguous character by its corresponding HTML entity, things get very clear to the browser (backslashes inserted in order to prevent the browser from displaying the corresponding HTML characters)<\/p>\n\n\n\n<p><font color=\"blue\">&lt;input type=&#8221;text&#8221; value=&#8221;&amp;\\quot; &amp;\\lt;script&amp;\\gt;alert(&amp;\\quot;XSS!&amp;\\quot;)&amp;\\lt;\/script&amp;\\gt;&#8221;&gt;<\/font><\/p>\n\n\n\n<p>Nothing left to execute. More obvious is the case of HTML elements enclosing the output value between tags<\/p>\n\n\n\n<p><font color=\"blue\">&lt;textarea rows=&#8221;3&#8243; cols=&#8221;25&#8243;&gt;&lt;script&gt;alert(&#8220;XSS!&#8221;)&lt;\/script&gt;&lt;\/textarea&gt;<\/font>\n\n\n\n<p>will cause the script to be executed. Once sanitized, the code changes to (backslashes inserted in order to prevent the browser from replacing them by their corresponding HTML character)<\/p>\n\n\n\n<p><font color=\"blue\">&lt;textarea&gt;&amp;\\lt;script&amp;\\gt;alert(&amp;\\quot;XSS!&amp;\\quot;)&amp;\\lt;\/script&amp;\\gt;&gt;\/textarea&gt;<\/font><\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Encapsulation<\/h4>\n\n\n\n<p>It is advisable to encapsulate sanitizers into dedicated classes or functions in order for them to serve as references thus avoiding instances (<em>Don\u00b4t Repeat Yourself<\/em>). For the same reason, it is also advisable to encapsulate the code generating HTML elements into a dedicated class, so the generator methods inherently make use of the sanitizer methods or functions. In a best case, there will be no other option than using the dedicated generators in order to produce output, because if just a single output is not considered for sanitization, it will be vulnerable.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Verification<\/h4>\n\n\n\n<p>Having realized the ideas described above, it\u00b4s not too challenging to verify the basic effectiveness of your XSS protection (best by using an offensive security testing tool in order to automate it). The following examples are taken from the <a href=\"https:\/\/reichartonline.de\/?page_id=44\">Housekeeping application<\/a> in order to make them easily reproducible.<\/p>\n\n\n\n<p>Having realized the ideas described above, it\u00b4s not too challenging to verify the basic effectiveness of your XSS protection (best by using an offensive security testing tool in order to automate it). The following examples are taken from the <a href=\"https:\/\/reichartonline.de\/?page_id=44\">Housekeeping application<\/a> in order to make them easily reproducible.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Elements with a &#8220;value&#8221; attribute<\/h4>\n\n\n\n<p>In all of the following examples no popup should appear.<\/p>\n\n\n\n<p>Text input field. As it is a search field, the search should just run normally and re-display the search value entered.<\/p>\n\n\n\n<p>XSS value terminator attack<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/reichartonline.de\/content\/wp-content\/uploads\/2019\/04\/20190405_xss_onfocus-4.png\"><img loading=\"lazy\" decoding=\"async\" width=\"339\" height=\"90\" src=\"http:\/\/reichartonline.de\/content\/wp-content\/uploads\/2019\/04\/20190405_xss_onfocus-4.png\" alt=\"XSS value terminator attack\" class=\"wp-image-826\" srcset=\"https:\/\/reichartonline.de\/content\/wp-content\/uploads\/2019\/04\/20190405_xss_onfocus-4.png 339w, https:\/\/reichartonline.de\/content\/wp-content\/uploads\/2019\/04\/20190405_xss_onfocus-4-300x80.png 300w\" sizes=\"auto, (max-width: 339px) 100vw, 339px\" \/><\/a><figcaption class=\"wp-element-caption\">Classic XSS attack on value terminator string<\/figcaption><\/figure>\n\n\n\n<p>And it should find malicious code if a user (attacker) has entered such.<\/p>\n\n\n\n<p>XSS script tag attack<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/reichartonline.de\/content\/wp-content\/uploads\/2019\/04\/20190405_xss_script_tag.png\"><img loading=\"lazy\" decoding=\"async\" width=\"340\" height=\"89\" src=\"http:\/\/reichartonline.de\/content\/wp-content\/uploads\/2019\/04\/20190405_xss_script_tag.png\" alt=\"XSS script tag attack\" class=\"wp-image-827\" srcset=\"https:\/\/reichartonline.de\/content\/wp-content\/uploads\/2019\/04\/20190405_xss_script_tag.png 340w, https:\/\/reichartonline.de\/content\/wp-content\/uploads\/2019\/04\/20190405_xss_script_tag-300x79.png 300w\" sizes=\"auto, (max-width: 340px) 100vw, 340px\" \/><\/a><figcaption class=\"wp-element-caption\">Classic XSS attack on script tag<\/figcaption><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\">Elements enclosing output between tags<\/h4>\n\n\n\n<p><strong>Text area<\/strong>. if loading an existing comment for edit, nothing unusual should happen<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/reichartonline.de\/content\/wp-content\/uploads\/2019\/04\/20190406_Housekeeping_comment_edit.png\"><img loading=\"lazy\" decoding=\"async\" width=\"375\" height=\"89\" src=\"http:\/\/reichartonline.de\/content\/wp-content\/uploads\/2019\/04\/20190406_Housekeeping_comment_edit.png\" alt=\"Javascript in text area\" class=\"wp-image-1005\" srcset=\"https:\/\/reichartonline.de\/content\/wp-content\/uploads\/2019\/04\/20190406_Housekeeping_comment_edit.png 375w, https:\/\/reichartonline.de\/content\/wp-content\/uploads\/2019\/04\/20190406_Housekeeping_comment_edit-300x71.png 300w\" sizes=\"auto, (max-width: 375px) 100vw, 375px\" \/><\/a><figcaption class=\"wp-element-caption\">Text area containing JavaScript<\/figcaption><\/figure>\n\n\n\n<p><strong>Select<\/strong> option using untrustworthy data<\/p>\n\n\n\n<p>Variable select entries might be vulnerable to XSS attacks<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/reichartonline.de\/content\/wp-content\/uploads\/2019\/04\/20190405_xss_select.png\"><img loading=\"lazy\" decoding=\"async\" width=\"283\" height=\"45\" src=\"http:\/\/reichartonline.de\/content\/wp-content\/uploads\/2019\/04\/20190405_xss_select.png\" alt=\"Variable select entries might be vulnerable to XSS attacks\" class=\"wp-image-858\"\/><\/a><figcaption class=\"wp-element-caption\">XSS attack on variable select entry<\/figcaption><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\">Simple text output<\/h4>\n\n\n\n<p>A <strong>comment<\/strong> containing JavaScript<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/reichartonline.de\/content\/wp-content\/uploads\/2019\/04\/20190406_Houskeeping_comment.png\"><img loading=\"lazy\" decoding=\"async\" width=\"367\" height=\"50\" src=\"http:\/\/reichartonline.de\/content\/wp-content\/uploads\/2019\/04\/20190406_Houskeeping_comment.png\" alt=\"Display Javascript code as text\" class=\"wp-image-1013\" srcset=\"https:\/\/reichartonline.de\/content\/wp-content\/uploads\/2019\/04\/20190406_Houskeeping_comment.png 367w, https:\/\/reichartonline.de\/content\/wp-content\/uploads\/2019\/04\/20190406_Houskeeping_comment-300x41.png 300w\" sizes=\"auto, (max-width: 367px) 100vw, 367px\" \/><\/a><figcaption class=\"wp-element-caption\">Javascript code in comment<\/figcaption><\/figure>\n\n\n\n<p>A <strong>note<\/strong> containing JavaScript (as well as SQL injection strings and multi-byte characters).<\/p>\n\n\n\n<p>Finding any character, including potentially executable ones.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/reichartonline.de\/content\/wp-content\/uploads\/2019\/04\/20190407_Housekeeping_xss_combined_search.png\"><img loading=\"lazy\" decoding=\"async\" width=\"245\" height=\"336\" src=\"http:\/\/reichartonline.de\/content\/wp-content\/uploads\/2019\/04\/20190407_Housekeeping_xss_combined_search.png\" alt=\"A note containing potentially executable characters\" class=\"wp-image-1017\" srcset=\"https:\/\/reichartonline.de\/content\/wp-content\/uploads\/2019\/04\/20190407_Housekeeping_xss_combined_search.png 245w, https:\/\/reichartonline.de\/content\/wp-content\/uploads\/2019\/04\/20190407_Housekeeping_xss_combined_search-219x300.png 219w\" sizes=\"auto, (max-width: 245px) 100vw, 245px\" \/><\/a><figcaption class=\"wp-element-caption\">A note containing potentially executable characters<\/figcaption><\/figure>\n\n\n\n<p>This also demonstrates that even search hits on malicious code can be (securely) highlighted using CSS. This advanced technique is described in the the <a href=\"https:\/\/reichartonline.de\/?page_id=1024\">dedicated how-to<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Why &#8220;protection&#8221; rather than &#8220;prevention&#8221;? Simply because it wouldn\u00b4t be realistic. Effective XSS (abbreviation to Cross-site Scripting) prevention is very hard to get. That\u00b4s why you\u00b4ll find security advisories describing XSS vulnerabilities even for the most popular software products providing a web-based user interface. This article intends to show you why that\u00b4s the case. The [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":62,"menu_order":5,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_bbp_topic_count":0,"_bbp_reply_count":0,"_bbp_total_topic_count":0,"_bbp_total_reply_count":0,"_bbp_voice_count":0,"_bbp_anonymous_reply_count":0,"_bbp_topic_count_hidden":0,"_bbp_reply_count_hidden":0,"_bbp_forum_subforum_count":0,"footnotes":""},"class_list":["post-831","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/reichartonline.de\/index.php?rest_route=\/wp\/v2\/pages\/831","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/reichartonline.de\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/reichartonline.de\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/reichartonline.de\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/reichartonline.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=831"}],"version-history":[{"count":106,"href":"https:\/\/reichartonline.de\/index.php?rest_route=\/wp\/v2\/pages\/831\/revisions"}],"predecessor-version":[{"id":1181,"href":"https:\/\/reichartonline.de\/index.php?rest_route=\/wp\/v2\/pages\/831\/revisions\/1181"}],"up":[{"embeddable":true,"href":"https:\/\/reichartonline.de\/index.php?rest_route=\/wp\/v2\/pages\/62"}],"wp:attachment":[{"href":"https:\/\/reichartonline.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=831"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}