[{"data":1,"prerenderedAt":994},["ShallowReactive",2],{"i-lucide:menu":3,"i-lucide:arrow-up-right":8,"i-lucide:moon":10,"i-lucide:sun":12,"i-lucide:rss":14,"i-simple-icons:github":16,"i-simple-icons:linkedin":18,"post-\u002F2020\u002Fecoop-xss-on-login-page":21,"surround-\u002F2020\u002Fecoop-xss-on-login-page":981,"i-lucide:arrow-left":990,"i-lucide:arrow-right":992},{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":7},0,24,false,"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 5h16M4 12h16M4 19h16\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":9},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M7 7h10v10M7 17L17 7\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":11},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":13},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"4\"\u002F>\u003Cpath d=\"M12 2v2m0 16v2M4.93 4.93l1.41 1.41m11.32 11.32l1.41 1.41M2 12h2m16 0h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":15},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Cpath d=\"M4 11a9 9 0 0 1 9 9M4 4a16 16 0 0 1 16 16\"\u002F>\u003Ccircle cx=\"5\" cy=\"19\" r=\"1\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":17},"\u003Cpath fill=\"currentColor\" d=\"M12 .297c-6.63 0-12 5.373-12 12c0 5.303 3.438 9.8 8.205 11.385c.6.113.82-.258.82-.577c0-.285-.01-1.04-.015-2.04c-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729c1.205.084 1.838 1.236 1.838 1.236c1.07 1.835 2.809 1.305 3.495.998c.108-.776.417-1.305.76-1.605c-2.665-.3-5.466-1.332-5.466-5.93c0-1.31.465-2.38 1.235-3.22c-.135-.303-.54-1.523.105-3.176c0 0 1.005-.322 3.3 1.23c.96-.267 1.98-.399 3-.405c1.02.006 2.04.138 3 .405c2.28-1.552 3.285-1.23 3.285-1.23c.645 1.653.24 2.873.12 3.176c.765.84 1.23 1.91 1.23 3.22c0 4.61-2.805 5.625-5.475 5.92c.42.36.81 1.096.81 2.22c0 1.606-.015 2.896-.015 3.286c0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":19,"hidden":20},"\u003Cpath fill=\"currentColor\" d=\"M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037c-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85c3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.06 2.06 0 0 1-2.063-2.065a2.064 2.064 0 1 1 2.063 2.065m1.782 13.019H3.555V9h3.564zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0z\"\u002F>",true,{"id":22,"title":23,"body":24,"category":967,"comments":968,"date":969,"description":970,"excerpt":968,"extension":971,"image":972,"meta":973,"navigation":20,"path":974,"readingTime":975,"seo":976,"stem":977,"subtitle":978,"tags":968,"wordCount":979,"__hash__":980},"posts\u002F2020\u002Fecoop-xss-on-login-page.md","eCoop open redirect and XSS on login page",{"type":25,"value":26,"toc":963},"minimark",[27,38,41,48,60,63,78,84,87,92,98,109,114,118,128,138,145,151,155,161,746,749,755,759,808,812,820,824,827,835,842,845,849,854,869,880,889,899,907,913,917,923,928,936,944,951,956,959],[28,29,30,37],"p",{},[31,32,36],"a",{"href":33,"rel":34},"https:\u002F\u002Fecoop.ee",[35],"nofollow","eCoop",", an Estonian food retailer, had two vulnerabilities on their login page. Both were responsibly disclosed and fixed by the vendor.",[28,39,40],{},"When unauthenticated users visit the online e-store and try to access a feature intended for authenticated users, they are shown a login page.",[28,42,43],{},[44,45],"img",{"alt":46,"src":47},"eCoop login page","\u002Fcontent\u002F2020\u002Fecoop\u002Flogin-page.png",[28,49,50,51,55,56,59],{},"The URL of the login page (",[52,53,54],"code",{},"https:\u002F\u002Fecoop.ee\u002Fet\u002Flogisisse\u002F?next=%2Fet%2Fostunimekirjad%2F",") has a query parameter ",[52,57,58],{},"next",",\nwhich is intended for user convenience - you get redirected to the subpage you were trying to access after login.",[28,61,62],{},"However, the frontend code in charge of using this parameter didn't validate the value, and it was possible to misuse it for two abuse cases.",[28,64,65,66,69,70,73,74,77],{},"The ",[52,67,68],{},"?next="," query parameter is an urlencoded value of an URI path in the same frontend application (React router path),\nwith expected values like ",[52,71,72],{},"%2Fet%2Fostunimekirjad%2F"," (decoded: ",[52,75,76],{},"\u002Fet\u002Fostunimekirjad\u002F",").",[28,79,80],{},[44,81],{"alt":82,"src":83},"React routes","\u002Fcontent\u002F2020\u002Fecoop\u002Frouter.png",[28,85,86],{},"The application tries to redirect to this path after the \"Login\" button is pressed.",[88,89,91],"h1",{"id":90},"open-redirect","Open redirect",[28,93,94,95,97],{},"It was possible to feed a full URI value to the ",[52,96,58],{}," parameter, hence redirecting the visitor out from the original eCoop website\nafter they attempted a login. The frontend code did not validate that the passed value would be a subpage of the current site.",[28,99,100,101,104,105,108],{},"PoC: Phishing e-mail from \"Coop\" with a link to ",[52,102,103],{},"https:\u002F\u002Fecoop.ee\u002Fet\u002Flogisisse\u002F?next=%2F%2Fekoop.ee"," (",[52,106,107],{},"\u002F\u002Fekoop.ee"," with two slashes - external (currently unclaimed) domain).\nUsers would try to login on a legitimate site, but get redirected to a phishing site after the first login attempt.",[28,110,111],{},[44,112],{"alt":91,"src":113},"\u002Fcontent\u002F2020\u002Fecoop\u002Fopen-redirect.png",[88,115,117],{"id":116},"reflected-xss","Reflected XSS",[28,119,120,121,123,124,127],{},"It was also possible to abuse the ",[52,122,58],{}," query parameter to execute JavaScript in the context of the site. This could be done, because it was possible\nto specify ",[52,125,126],{},"javascript"," as the link protocol.",[28,129,130,131,104,134,137],{},"PoC: ",[52,132,133],{},"https:\u002F\u002Fecoop.ee\u002Fet\u002Flogisisse\u002F?next=javascript%3Aalert(1)",[52,135,136],{},"javascript:alert(1)","). A maliciously crafted link could be sent to a user, with the payload encoded\nin the URL. The payload would execute once the victim pressed \"log in\", and run arbitrary JavaScript in the context of the eCoop site.",[28,139,140,141,144],{},"eCoop session cookie is marked as ",[52,142,143],{},"httpOnly",", but the site has no Content Security Policy in place to protect against it. The payload could include additional scripts,\nmodify the content of the site, read out user-entered username\u002Fpassword, or phish for more information - all the while using the percieved legitimacy of the trusted domain\u002Fbrand.",[28,146,147],{},[44,148],{"alt":149,"src":150},"XSS","\u002Fcontent\u002F2020\u002Fecoop\u002Fxss.png",[88,152,154],{"id":153},"the-fix","The fix",[28,156,157,158,160],{},"eCoop fixed the issue 16 months after initial disclosure. The fix involved adding a frontend validator for the value of the ",[52,159,58],{}," parameter, checking it against\na whitelist of all internally set React Routes.",[162,163,167],"pre",{"className":164,"code":165,"language":126,"meta":166,"style":166},"language-javascript shiki shiki-themes github-light github-dark","\n\u002F\u002F ...\nreturn o(t, e), f(t, [{\n    key: \"componentWillMount\",\n    value: function() {\n        if (this.props.location.query) {\n            var e = this.props.location.query.next;\n            e && this.validateRedirectPath(e), this.props.location.query.e && this.setState({\n                socialLoginErrors: (0, R.attachError)(null, this.props.location.query.e, this.context.activeLanguage)\n            })\n        }\n    }\n},\n{              \n    key: \"validateRedirectPath\",\n    value: function(e) {\n        var t = e.split(\"\u002F\"),\n            r = this.whitelistedRedirectPaths.some(function(e) {\n                var r = e.split(\"\u002F\");\n                return r.length === t.length && r.every(function(e, r) {\n                    var u = t[r];\n                    return \":\" === e[0] && u || e === u\n                })\n            });\n        if (!r) throw \"Invalid redirect path!\"\n    }\n},{\n    key: \"_getWhitelistedRedirectPaths\",\n    value: function(e) {\n        return e.reduce(function(e, t) {\n            return e.concat(t.childRoutes.filter(function(e) {\n                return e.to\n            }).map(function(e) {\n                return \"\u002F\" + e.to\n            }))\n        }, [])\n    }\n}\n\u002F\u002F ...\n","",[52,168,169,177,184,205,218,233,248,266,303,336,342,348,354,360,366,376,395,420,446,468,511,525,559,565,570,589,594,600,610,625,651,678,686,705,718,724,730,735,741],{"__ignoreMap":166},[170,171,174],"span",{"class":172,"line":173},"line",1,[170,175,176],{"emptyLinePlaceholder":20},"\n",[170,178,180],{"class":172,"line":179},2,[170,181,183],{"class":182},"sJ8bj","\u002F\u002F ...\n",[170,185,187,191,195,199,202],{"class":172,"line":186},3,[170,188,190],{"class":189},"szBVR","return",[170,192,194],{"class":193},"sScJk"," o",[170,196,198],{"class":197},"sVt8B","(t, e), ",[170,200,201],{"class":193},"f",[170,203,204],{"class":197},"(t, [{\n",[170,206,208,211,215],{"class":172,"line":207},4,[170,209,210],{"class":197},"    key: ",[170,212,214],{"class":213},"sZZnC","\"componentWillMount\"",[170,216,217],{"class":197},",\n",[170,219,221,224,227,230],{"class":172,"line":220},5,[170,222,223],{"class":193},"    value",[170,225,226],{"class":197},": ",[170,228,229],{"class":189},"function",[170,231,232],{"class":197},"() {\n",[170,234,236,239,241,245],{"class":172,"line":235},6,[170,237,238],{"class":189},"        if",[170,240,104],{"class":197},[170,242,244],{"class":243},"sj4cs","this",[170,246,247],{"class":197},".props.location.query) {\n",[170,249,251,254,257,260,263],{"class":172,"line":250},7,[170,252,253],{"class":189},"            var",[170,255,256],{"class":197}," e ",[170,258,259],{"class":189},"=",[170,261,262],{"class":243}," this",[170,264,265],{"class":197},".props.location.query.next;\n",[170,267,269,272,275,277,280,283,286,288,291,293,295,297,300],{"class":172,"line":268},8,[170,270,271],{"class":197},"            e ",[170,273,274],{"class":189},"&&",[170,276,262],{"class":243},[170,278,279],{"class":197},".",[170,281,282],{"class":193},"validateRedirectPath",[170,284,285],{"class":197},"(e), ",[170,287,244],{"class":243},[170,289,290],{"class":197},".props.location.query.e ",[170,292,274],{"class":189},[170,294,262],{"class":243},[170,296,279],{"class":197},[170,298,299],{"class":193},"setState",[170,301,302],{"class":197},"({\n",[170,304,306,309,312,315,318,321,324,326,328,331,333],{"class":172,"line":305},9,[170,307,308],{"class":197},"                socialLoginErrors: (",[170,310,311],{"class":243},"0",[170,313,314],{"class":197},", ",[170,316,317],{"class":243},"R",[170,319,320],{"class":197},".attachError)(",[170,322,323],{"class":243},"null",[170,325,314],{"class":197},[170,327,244],{"class":243},[170,329,330],{"class":197},".props.location.query.e, ",[170,332,244],{"class":243},[170,334,335],{"class":197},".context.activeLanguage)\n",[170,337,339],{"class":172,"line":338},10,[170,340,341],{"class":197},"            })\n",[170,343,345],{"class":172,"line":344},11,[170,346,347],{"class":197},"        }\n",[170,349,351],{"class":172,"line":350},12,[170,352,353],{"class":197},"    }\n",[170,355,357],{"class":172,"line":356},13,[170,358,359],{"class":197},"},\n",[170,361,363],{"class":172,"line":362},14,[170,364,365],{"class":197},"{              \n",[170,367,369,371,374],{"class":172,"line":368},15,[170,370,210],{"class":197},[170,372,373],{"class":213},"\"validateRedirectPath\"",[170,375,217],{"class":197},[170,377,379,381,383,385,388,392],{"class":172,"line":378},16,[170,380,223],{"class":193},[170,382,226],{"class":197},[170,384,229],{"class":189},[170,386,387],{"class":197},"(",[170,389,391],{"class":390},"s4XuR","e",[170,393,394],{"class":197},") {\n",[170,396,398,401,404,406,409,412,414,417],{"class":172,"line":397},17,[170,399,400],{"class":189},"        var",[170,402,403],{"class":197}," t ",[170,405,259],{"class":189},[170,407,408],{"class":197}," e.",[170,410,411],{"class":193},"split",[170,413,387],{"class":197},[170,415,416],{"class":213},"\"\u002F\"",[170,418,419],{"class":197},"),\n",[170,421,423,426,428,430,433,436,438,440,442,444],{"class":172,"line":422},18,[170,424,425],{"class":197},"            r ",[170,427,259],{"class":189},[170,429,262],{"class":243},[170,431,432],{"class":197},".whitelistedRedirectPaths.",[170,434,435],{"class":193},"some",[170,437,387],{"class":197},[170,439,229],{"class":189},[170,441,387],{"class":197},[170,443,391],{"class":390},[170,445,394],{"class":197},[170,447,449,452,455,457,459,461,463,465],{"class":172,"line":448},19,[170,450,451],{"class":189},"                var",[170,453,454],{"class":197}," r ",[170,456,259],{"class":189},[170,458,408],{"class":197},[170,460,411],{"class":193},[170,462,387],{"class":197},[170,464,416],{"class":213},[170,466,467],{"class":197},");\n",[170,469,471,474,477,480,483,486,488,491,493,496,498,500,502,504,506,509],{"class":172,"line":470},20,[170,472,473],{"class":189},"                return",[170,475,476],{"class":197}," r.",[170,478,479],{"class":243},"length",[170,481,482],{"class":189}," ===",[170,484,485],{"class":197}," t.",[170,487,479],{"class":243},[170,489,490],{"class":189}," &&",[170,492,476],{"class":197},[170,494,495],{"class":193},"every",[170,497,387],{"class":197},[170,499,229],{"class":189},[170,501,387],{"class":197},[170,503,391],{"class":390},[170,505,314],{"class":197},[170,507,508],{"class":390},"r",[170,510,394],{"class":197},[170,512,514,517,520,522],{"class":172,"line":513},21,[170,515,516],{"class":189},"                    var",[170,518,519],{"class":197}," u ",[170,521,259],{"class":189},[170,523,524],{"class":197}," t[r];\n",[170,526,528,531,534,536,539,541,544,546,548,551,553,556],{"class":172,"line":527},22,[170,529,530],{"class":189},"                    return",[170,532,533],{"class":213}," \":\"",[170,535,482],{"class":189},[170,537,538],{"class":197}," e[",[170,540,311],{"class":243},[170,542,543],{"class":197},"] ",[170,545,274],{"class":189},[170,547,519],{"class":197},[170,549,550],{"class":189},"||",[170,552,256],{"class":197},[170,554,555],{"class":189},"===",[170,557,558],{"class":197}," u\n",[170,560,562],{"class":172,"line":561},23,[170,563,564],{"class":197},"                })\n",[170,566,567],{"class":172,"line":5},[170,568,569],{"class":197},"            });\n",[170,571,573,575,577,580,583,586],{"class":172,"line":572},25,[170,574,238],{"class":189},[170,576,104],{"class":197},[170,578,579],{"class":189},"!",[170,581,582],{"class":197},"r) ",[170,584,585],{"class":189},"throw",[170,587,588],{"class":213}," \"Invalid redirect path!\"\n",[170,590,592],{"class":172,"line":591},26,[170,593,353],{"class":197},[170,595,597],{"class":172,"line":596},27,[170,598,599],{"class":197},"},{\n",[170,601,603,605,608],{"class":172,"line":602},28,[170,604,210],{"class":197},[170,606,607],{"class":213},"\"_getWhitelistedRedirectPaths\"",[170,609,217],{"class":197},[170,611,613,615,617,619,621,623],{"class":172,"line":612},29,[170,614,223],{"class":193},[170,616,226],{"class":197},[170,618,229],{"class":189},[170,620,387],{"class":197},[170,622,391],{"class":390},[170,624,394],{"class":197},[170,626,628,631,633,636,638,640,642,644,646,649],{"class":172,"line":627},30,[170,629,630],{"class":189},"        return",[170,632,408],{"class":197},[170,634,635],{"class":193},"reduce",[170,637,387],{"class":197},[170,639,229],{"class":189},[170,641,387],{"class":197},[170,643,391],{"class":390},[170,645,314],{"class":197},[170,647,648],{"class":390},"t",[170,650,394],{"class":197},[170,652,654,657,659,662,665,668,670,672,674,676],{"class":172,"line":653},31,[170,655,656],{"class":189},"            return",[170,658,408],{"class":197},[170,660,661],{"class":193},"concat",[170,663,664],{"class":197},"(t.childRoutes.",[170,666,667],{"class":193},"filter",[170,669,387],{"class":197},[170,671,229],{"class":189},[170,673,387],{"class":197},[170,675,391],{"class":390},[170,677,394],{"class":197},[170,679,681,683],{"class":172,"line":680},32,[170,682,473],{"class":189},[170,684,685],{"class":197}," e.to\n",[170,687,689,692,695,697,699,701,703],{"class":172,"line":688},33,[170,690,691],{"class":197},"            }).",[170,693,694],{"class":193},"map",[170,696,387],{"class":197},[170,698,229],{"class":189},[170,700,387],{"class":197},[170,702,391],{"class":390},[170,704,394],{"class":197},[170,706,708,710,713,716],{"class":172,"line":707},34,[170,709,473],{"class":189},[170,711,712],{"class":213}," \"\u002F\"",[170,714,715],{"class":189}," +",[170,717,685],{"class":197},[170,719,721],{"class":172,"line":720},35,[170,722,723],{"class":197},"            }))\n",[170,725,727],{"class":172,"line":726},36,[170,728,729],{"class":197},"        }, [])\n",[170,731,733],{"class":172,"line":732},37,[170,734,353],{"class":197},[170,736,738],{"class":172,"line":737},38,[170,739,740],{"class":197},"}\n",[170,742,744],{"class":172,"line":743},39,[170,745,183],{"class":182},[28,747,748],{},"The fix appears effective, as both PoC-s now fail.",[28,750,751],{},[44,752],{"alt":753,"src":754},"PoCs now fail","\u002Fcontent\u002F2020\u002Fecoop\u002Ffix1.png",[88,756,758],{"id":757},"appendix-timeline","Appendix: Timeline",[760,761,762,766,775,778,787,790,793,796,799,802,805],"ul",{},[763,764,765],"li",{},"2019-04-04 Initial discovery",[763,767,768,769,774],{},"2019-04-04 No security \u002F IT contact (or responsible disclosure\u002F",[31,770,773],{"href":771,"rel":772},"https:\u002F\u002Fsecuritytxt.org\u002F",[35],"security.txt",") found for eCoop, wrote to customer support for an IT contact",[763,776,777],{},"2019-04-05 Received contact e-mail of E-Services Development Manager",[763,779,780,781,786],{},"2019-04-07 ",[31,782,785],{"href":783,"rel":784},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FResponsible_disclosure",[35],"Responsible disclosure"," to Coop about both problems, with full PoC \\ explanation",[763,788,789],{},"2019-04-08 Acknowledgment of receipt from Coop's E-Services Development Manager; PoC forwarded to development team",[763,791,792],{},"2019-11-25 Escalation: disclosure to CERT-EE (CC Coop); as nothing had happened yet - bug still live. No response form either party",[763,794,795],{},"2020-03-12 Escalation: contact Coop ISO directly for an update (CC original report contents)",[763,797,798],{},"2020-03-12 ISO replies: acknowledgment that issue was known internally since initial report; remediation plan had been made (switch to a new technical e-store platform), but implementation delayed",[763,800,801],{},"2020-08-04 ISO notifies that the issue has been fixed in the current production system",[763,803,804],{},"2020-08-05 Verified fix (a whitelist validator had been added; protects against both PoC-s), can see no obvious bypass - issue fixed",[763,806,807],{},"2020-08-05 Public disclosure",[88,809,811],{"id":810},"appendix-developer-view","Appendix: developer view",[28,813,814,815,279],{},"solutional.ee wrote a blog on this: ",[31,816,819],{"href":817,"rel":818},"https:\u002F\u002Fsolutional.ee\u002Fblog\u002F2020-10-20-Tackling-Security-Issues.html",[35],"Tackling Security Issues",[88,821,823],{"id":822},"appendix-disclosure-e-mail","Appendix: Disclosure e-mail",[28,825,826],{},"Tere",[28,828,829,830,834],{},"Kirjutan Teile kui e-arendusjuhile heas usus, et ",[31,831,833],{"href":783,"rel":832},[35],"responsible disclosure"," raames teada anda Coop e-poest leitud XSS + open redirect turvaveast.\nTeadaolevalt ei ole neid veel halvasti ära kasutatud, ning see teavitus võimaldab Teil vead parandada, muutes Coop keskkonna klientidele (sh minule) turvalisemaks.",[28,836,837,838,841],{},"(Kirjutan otse Teile, kuna ei suutnud ecoop.ee kodulehelt leida turvaküsimusteks otsekontakti, ning ecoop.ee ei kasuta ",[31,839,773],{"href":771,"rel":840},[35]," standardit).",[28,843,844],{},"Leitud haavatavused on järgnevad.",[846,847,91],"h2",{"id":848},"open-redirect-1",[28,850,851,852,279],{},"Rakenduse aktsepteerib sisselogimisel URL parameetrit \"next\". Näiteks, kui sisselogimata külastaja vajutab peamenüü lingile \"Ostunimekirjad\", suunatakse ta edasi \"Sisene eCoopi\" lehele, kusjuures lehe URL on ",[52,853,54],{},[28,855,856,857,859,860,865,866,868],{},"Aadressi vaadates märgati, et ",[52,858,58],{}," parameeter sisaldab URI segmenti ja on ilmselt haavatav ",[31,861,864],{"href":862,"rel":863},"https:\u002F\u002Fgithub.com\u002FOWASP\u002FCheatSheetSeries\u002Fblob\u002Fmaster\u002Fcheatsheets\u002FUnvalidated_Redirects_and_Forwards_Cheat_Sheet.md",[35],"open redirect"," turvaveale: ",[52,867,58],{}," parameetri väärtus on muudetav ning võib näidata suvalisele URL-ile - mispeale rakendus ka peale sisselogimist sinna suunab.",[28,870,871,875,876,879],{},[872,873,874],"strong",{},"PoC:"," ",[52,877,878],{},"https:\u002F\u002Fecoop.ee\u002Fet\u002Flogisisse\u002F?next=%2F%2Fneti.ee"," (peale sisselogimist suunatakse ümber neti.ee veebilehele)",[28,881,882,885,886,888],{},[872,883,884],{},"Probleem:"," rakendus ei valideeri ",[52,887,58],{}," parameetri väärtust ning suunab ka välistele domeenidele.",[28,890,891,894,895,898],{},[872,892,893],{},"Väärkasutus (näide #1):"," Kliendile saadetakse link stiilis ",[52,896,897],{},"https:\u002F\u002Fecoop.ee\u002Fet\u002Flogisisse\u002F?next=%2F%2Fekoop.ee%2Fet%2Flogisisse","; näiteks phishing-uudiskirjaga. Kirjas olev link on õigele domeenile, ning klient usaldab seda. Peale sisselogimist suunab süsteem aga edasi phishing veebilehele, mis asub hoopis teisel domeenil, ning väidab, et sisselogimine ebaõnnestus, palun sisestada parool uuesti. Klient ei märka domeeni muutust, ning annab kolmandale osapoolele oma parooli.",[28,900,901,875,904],{},[872,902,903],{},"Kaitse:",[52,905,906],{},"https:\u002F\u002Fgithub.com\u002FOWASP\u002FCheatSheetSeries\u002Fblob\u002Fmaster\u002Fcheatsheets\u002FUnvalidated_Redirects_and_Forwards_Cheat_Sheet.md#preventing-unvalidated-redirects-and-forwards",[28,908,909,912],{},[872,910,911],{},"Kriitilisus:"," Madal",[846,914,916],{"id":915},"reflected-xss-via-get-uri","Reflected XSS via GET URI",[28,918,919,920,922],{},"Kasutades sama ",[52,921,58],{}," URL parameetrit sisselogimislehel, on võimalik ecoop keskkonnas käivitada JavaScript koodi. See on nn \"Reflected XSS\" haavatavus.",[28,924,925,927],{},[872,926,884],{}," Rakendus käivitab next parameetri väärtust kui JavaScript koodi, kasutaja browseri kontekstis - XSS",[28,929,930,875,932,935],{},[872,931,874],{},[52,933,934],{},"https:\u002F\u002Fecoop.ee\u002Fet\u002Flogisisse\u002F?next=javascript:window.location.href%3D%27%2F%2Flocalhost%2F%27%2Bdocument.getElementById(%27tfid-84-1%27).value"," (peale sisselogimist suunatakse ümber teisele domeenile localhost, kusjuures kliendi parool on tekstina URL-is)",[28,937,938,940,941,943],{},[872,939,893],{}," Kliendile saadetakse phishing kirjaga link Coop e-poodi. Kirjas olev link on õigele domeenile, ning klient usaldab seda. Link viib sisselogimislehele. Kui klient vajutab \"Logi sisse\", käivitub ",[52,942,58],{}," parameetris olev JavaScript kood, mis võtab kliendi poolt täidetud parooli väljast (enne ümbersuunnamist!) parooli väärtuse, ning saadab selle kolmandale osapoolele, kompromiteerides nõnda kliendi sisselogimisandmed.",[28,945,946,875,948],{},[872,947,903],{},[52,949,950],{},"https:\u002F\u002Fwww.owasp.org\u002Findex.php\u002FCross-site_Scripting_(XSS)",[28,952,953,955],{},[872,954,911],{}," Keskmine",[28,957,958],{},"Palun vastust, kinnitamaks raporti kättesaamist ning võimalusel ka indikatiivset aega, millal mainitud vead parandatakse (tüüpiliselt parandatakse turvavead maksimaalselt 90 päeva jooksul).",[960,961,962],"style",{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":166,"searchDepth":179,"depth":179,"links":964},[965,966],{"id":848,"depth":179,"text":91},{"id":915,"depth":179,"text":916},"Security",null,"2020-08-04","eCoop, an Estonian food retailer, had two vulnerabilities on their login page. Both were responsibly disclosed and fixed by the vendor.","md","\u002Fcontent\u002F2020\u002Fecoop\u002Fheader-inverse.png",{},"\u002F2020\u002Fecoop-xss-on-login-page","about 5 minutes",{"title":23,"description":970},"2020\u002Fecoop-xss-on-login-page","Accepting unvalidated user-input in redirect URL-s can result in security issues",1057,"VqwnMxxSpl2RXX4f2FPXiXrC1PCdviGT_X5H9ujBLHo",[982,986],{"title":983,"path":984,"stem":985,"children":-1},"Buspad kiosk breakout","\u002F2020\u002Fbuspad-kiosk-bypass","2020\u002Fbuspad-kiosk-bypass",{"title":987,"path":988,"stem":989,"children":-1},"Puzzle box Christmas gift","\u002F2020\u002Fpuzzle-box-christmas-gift","2020\u002Fpuzzle-box-christmas-gift",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":991},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"m12 19l-7-7l7-7m7 7H5\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":993},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M5 12h14m-7-7l7 7l-7 7\"\u002F>",1790228552485]