{"action":"created","issue":{"url":"https://api.github.com/repos/playframework/playframework/issues/4513","labels_url":"https://api.github.com/repos/playframework/playframework/issues/4513/labels{/name}","comments_url":"https://api.github.com/repos/playframework/playframework/issues/4513/comments","events_url":"https://api.github.com/repos/playframework/playframework/issues/4513/events","html_url":"https://github.com/playframework/playframework/issues/4513","id":78556430,"number":4513,"title":"[2.3.7] Script injection vulnerability in Javascript Router Generator","user":{"login":"Lennholm","id":2505588,"avatar_url":"https://avatars.githubusercontent.com/u/2505588?v=3","gravatar_id":"","url":"https://api.github.com/users/Lennholm","html_url":"https://github.com/Lennholm","followers_url":"https://api.github.com/users/Lennholm/followers","following_url":"https://api.github.com/users/Lennholm/following{/other_user}","gists_url":"https://api.github.com/users/Lennholm/gists{/gist_id}","starred_url":"https://api.github.com/users/Lennholm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Lennholm/subscriptions","organizations_url":"https://api.github.com/users/Lennholm/orgs","repos_url":"https://api.github.com/users/Lennholm/repos","events_url":"https://api.github.com/users/Lennholm/events{/privacy}","received_events_url":"https://api.github.com/users/Lennholm/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":8,"created_at":"2015-05-20T14:51:29Z","updated_at":"2015-05-22T09:56:45Z","closed_at":null,"body":"Play version: 2.3.7 (Scala)\r\n\r\nThanks to a Whitehat security scan, I recently discovered a vulnerability in the Javascript Router Generator where it's possible for a client to inject code that is then executed when the webpage downloads the generated jsroutes file.\r\n\r\nIn the generated file we can find the following line of code:\r\n\r\n``var _wA = function(r){return {ajax:function(c){c=c||{};c.url=r.url;c.type=r.method;return jQuery.ajax(c)}, method:r.method,type:r.method,url:r.url,absoluteURL: function(s){return _s('http',s)+'example.domain.com'+r.url},webSocketURL: function(s){return _s('ws',s)+'example.domain.com'+r.url}}}``\r\n\r\nThe above code creates the functions that generates the absolute URL and web socket URL of the route and the ``example.domain.com`` string is taken straight from the host header of the request.\r\n\r\nBy writing a different host header, the absolute URL can be made to point to a completely different URL which will cause files outside of your control to be loaded, or the file to not be loaded at all, depending on how the client handles cross-domain requests.\r\nAlternatively, it can be made to point all requests to another resource on your system which an attacker can use to mess things up.\r\n\r\n\r\nAlthough these absolute URL's aren't normally used, this isn't even the most dangerous aspect of this vulnerability.\r\n\r\nIt turns out the content of the host header isn't sanitized in any way which means it can be used to inject any code. For instance, writing the following to the host header:\r\n\r\n``'}}};alert(1);a={a:{a:{a:'``\r\n\r\n...will result in:\r\n\r\n``var _wA = function(r){return {ajax:function(c){c=c||{};c.url=r.url;c.type=r.method;return jQuery.ajax(c)}, method:r.method,type:r.method,url:r.url,absoluteURL: function(s){return _s('http',s)+''}}};alert(1);a={a:{a:{a:''+r.url},webSocketURL: function(s){return _s('ws',s)+''}}};alert(1);a={a:{a:{a:''+r.url}}}``\r\n\r\nwhere the ``alert(1)`` part is executed immediately as the client parses the file.\r\n\r\n\r\nThis can potentially be used by a compromised client or man-in-the-middle to compromise your system.\r\n\r\n\r\nOn the web site I'm working on, I worked around this issue by creating a new implicit request with the host header always set to ``'+window.location.host+'`` before calling the Javascript router generator. "},"comment":{"url":"https://api.github.com/repos/playframework/playframework/issues/comments/104602994","html_url":"https://github.com/playframework/playframework/issues/4513#issuecomment-104602994","issue_url":"https://api.github.com/repos/playframework/playframework/issues/4513","id":104602994,"user":{"login":"Lennholm","id":2505588,"avatar_url":"https://avatars.githubusercontent.com/u/2505588?v=3","gravatar_id":"","url":"https://api.github.com/users/Lennholm","html_url":"https://github.com/Lennholm","followers_url":"https://api.github.com/users/Lennholm/followers","following_url":"https://api.github.com/users/Lennholm/following{/other_user}","gists_url":"https://api.github.com/users/Lennholm/gists{/gist_id}","starred_url":"https://api.github.com/users/Lennholm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Lennholm/subscriptions","organizations_url":"https://api.github.com/users/Lennholm/orgs","repos_url":"https://api.github.com/users/Lennholm/repos","events_url":"https://api.github.com/users/Lennholm/events{/privacy}","received_events_url":"https://api.github.com/users/Lennholm/received_events","type":"User","site_admin":false},"created_at":"2015-05-22T09:56:45Z","updated_at":"2015-05-22T09:56:45Z","body":"@gmethvin I experimented a bit with a whitelist solution before I settled on always overriding the header with a safe value, which works well for my project. It turned ugly when I had to create different whitelists depending on which environment the application was running in (dev, stage or prod) but putting this as a configuration could alleviate that.\r\n\r\n@richdougherty That's essentially how I ended up working around this issue, by overriding the host header with ``'+window.location.host+'`` the jsroutes file will contain the code ``_s('http',s)+''+window.location.host+''+r.url``.\r\nI'm not sure this is a catch-all solution though, what if the client isn't meant to be a browser but a proprietary front-end application where ``window`` isn't a thing? Then again, the js router appears to (by default) assume that jQuery is running in the client, so does Play only support a front-end that runs in browsers?"}}