<div dir="ltr">Hi,<div><br>I was initially going to file this on <a href="https://bugs.launchpad.net/ossn/" target="_blank">https://bugs.launchpad.net/ossn/</a> as a bug, but its not a exploitable vulnerability and more a defence in depth / increase security posture recommendation for Horizon I thought the list would be best place to spark initial discussion, its also very similar in nature to the HSTS header issue <a href="https://bugs.launchpad.net/ossn/+bug/1191050" target="_blank">https://bugs.launchpad.net/ossn/+bug/1191050</a> , but probably a lot more work to implement :-(</div>

<div><br></div><div>Although Horizon does a very good job of escaping user input and does not have a track record of Cross-Site Scripting vulnerabilities, its security posture could be increased long term by the use of the Content-Security-Policy header. This would protect against any new functionality tat falls short of current XSS filtering, and also framework and middleware vulns that Horizon doesn't really have control over. Its use when configured correctly pretty much eradicates XSS bugs (along with some other cross-site includes) and is a huge step forward in client-side browser security. </div>
<div><br></div><div>If your not familiar with the CSP header and how it works, it basically prevents inline JavaScript, and has fine grain control regarding where client-side script is loaded from. </div><div><br></div><div>
The reason I said in the first paragraph that its probably a lot more work is that the web application needs to move any JavaScript it uses into .js files and include those from within the HTML, so something that was originally[1]:</div>
<div><br></div><pre class="" style="font-family:'Source Code Pro',monospace;font-size:13px;white-space:pre-wrap;word-wrap:break-word;margin-right:auto;margin-left:auto;padding:1em;color:white;background-color:rgb(68,68,68);border-top-left-radius:8px;border-top-right-radius:8px;border-bottom-right-radius:8px;border-bottom-left-radius:8px;line-height:16px">
<code style="font-family:'Source Code Pro',monospace;font-size:1em"><span class="" style="color:rgb(137,189,255)"><script></span><span class="">
  </span><span class="" style="color:rgb(226,137,100)">function</span><span class=""> doAmazingThings</span><span class="">()</span><span class=""> </span><span class="">{</span><span class="">
    alert</span><span class="">(</span><span class="" style="color:rgb(101,176,66)">'YOU AM AMAZING!'</span><span class="">);</span><span class="">
  </span><span class="">}</span><span class="">
</span><span class="" style="color:rgb(137,189,255)"></script> </span></code><span class="" style="font-size:1em;color:rgb(137,189,255)"><button</span><span class="" style="font-size:1em"> </span><span class="" style="font-size:1em;color:rgb(189,183,107)">onclick</span><span class="" style="font-size:1em">=</span><span class="" style="font-size:1em;color:rgb(101,176,66)">'</span><span class="" style="font-size:1em">doAmazingThings</span><span class="" style="font-size:1em">();</span><span class="" style="font-size:1em;color:rgb(101,176,66)">'</span><span class="" style="font-size:1em;color:rgb(137,189,255)">></span><span class="" style="font-size:1em">Am I amazing?</span><span class="" style="font-size:1em;color:rgb(137,189,255)"></button></span><span style="background-color:rgb(255,255,255);font-family:arial;font-size:small;line-height:normal;color:rgb(34,34,34)"> </span></pre>
<div>Becomes:</div><div><br></div><div><pre class="" style="font-family:'Source Code Pro',monospace;font-size:13px;white-space:pre-wrap;word-wrap:break-word;margin-right:auto;margin-left:auto;padding:1em;color:white;background-color:rgb(68,68,68);border-top-left-radius:8px;border-top-right-radius:8px;border-bottom-right-radius:8px;border-bottom-left-radius:8px;line-height:16px">
<code style="font-family:'Source Code Pro',monospace;font-size:1em"><span class="" style="color:rgb(174,174,174);font-style:italic"><!-- amazing.html --></span><span class="">
</span><span class="" style="color:rgb(137,189,255)"><script</span><span class=""> </span><span class="" style="color:rgb(189,183,107)">src</span><span class="">=</span><span class="" style="color:rgb(101,176,66)">'amazing.js'</span><span class="" style="color:rgb(137,189,255)">></script></span><span class="">
</span><span class="" style="color:rgb(137,189,255)"><button</span><span class=""> </span><span class="" style="color:rgb(189,183,107)">id</span><span class="">=</span><span class="" style="color:rgb(101,176,66)">'amazing'</span><span class="" style="color:rgb(137,189,255)">></span><span class="">Am I amazing?</span><span class="" style="color:rgb(137,189,255)"></button></span></code></pre>
<pre class="" style="font-family:'Source Code Pro',monospace;font-size:13px;white-space:pre-wrap;word-wrap:break-word;margin-right:auto;margin-left:auto;padding:1em;color:white;background-color:rgb(68,68,68);border-top-left-radius:8px;border-top-right-radius:8px;border-bottom-right-radius:8px;border-bottom-left-radius:8px;line-height:16px">
<code style="font-family:'Source Code Pro',monospace;font-size:1em"><span class="" style="color:rgb(174,174,174);font-style:italic">// amazing.js</span><span class="">
</span><span class="" style="color:rgb(226,137,100)">function</span><span class=""> doAmazingThings</span><span class="">()</span><span class=""> </span><span class="">{</span><span class="">
  alert</span><span class="">(</span><span class="" style="color:rgb(101,176,66)">'YOU AM AMAZING!'</span><span class="">);</span><span class="">
</span><span class="">}</span><span class="">
document</span><span class="">.</span><span class="">addEventListener</span><span class="">(</span><span class="" style="color:rgb(101,176,66)">'DOMContentReady'</span><span class="">,</span><span class=""> </span><span class="" style="color:rgb(226,137,100)">function</span><span class=""> </span><span class="">()</span><span class=""> </span><span class="">{</span><span class="">
  document</span><span class="">.</span><span class="">getElementById</span><span class="">(</span><span class="" style="color:rgb(101,176,66)">'amazing'</span><span class="">)</span><span class="">
          </span><span class="">.</span><span class="">addEventListener</span><span class="">(</span><span class="" style="color:rgb(101,176,66)">'click'</span><span class="">,</span><span class=""> doAmazingThings</span><span class="">);</span><span class="">
</span><span class="">});</span></code></pre></div><div><br></div><div>Once you have moved all your JS out of the HTML and into .js files, you can set the CSP header to only load script from your domain:</div><div><br></div>
<div><pre class="" style="font-family:'Source Code Pro',monospace;font-size:13px;white-space:pre-wrap;word-wrap:break-word;margin-right:auto;margin-left:auto;padding:1em;color:white;background-color:rgb(68,68,68);border-top-left-radius:8px;border-top-right-radius:8px;border-bottom-right-radius:8px;border-bottom-left-radius:8px;line-height:16px">
<code style="font-family:'Source Code Pro',monospace;font-size:1em"><span class="" style="color:rgb(226,137,100)">Content-Security-Policy: </span><span class="" style="color:rgb(137,189,255)">default-src</span><span class=""> </span><span class="" style="color:rgb(101,176,66)">'none'</span><span class="">;</span><span class=""> </span><span class="" style="color:rgb(137,189,255)">script-src</span><span class=""> <a href="https://horizon.mycloud.net">https://horizon.mycloud.net</a></span><span class="">;</span></code></pre>
</div><div><br></div><div>So with that set, even if you had a parameter vulnerable to reflected XSS as follows:</div><div><br></div><div><a href="https://horizon.mycloud.net/login/user=admin">https://horizon.mycloud.net/login/user=admin</a><script>alert('i am stealing your session token')</script></div>
<div><br></div><div>It wouldn't get executed - demonstrating the excellent defence in depth.</div><div><br></div><div>Finally, as the CSP may be organisation specific, it may be best to allow the exact policy to be configureable and a note in the security guide, but for this even to be a possibility the JavaScript needs to be cleaned up and moved out :-(</div>
<div><br></div><div>Heres a few posts on how twitter have gone about it:</div><div><br></div><div><a href="https://blog.twitter.com/2011/improving-browser-security-csp">https://blog.twitter.com/2011/improving-browser-security-csp</a><br>
</div><div><a href="https://blog.twitter.com/2013/csp-to-the-rescue-leveraging-the-browser-for-security">https://blog.twitter.com/2013/csp-to-the-rescue-leveraging-the-browser-for-security</a><br></div><div><br></div><div>
I'm happy to provide more help, test and work with anyone if this moves forward, and Hi, I'm Myles :-)</div><div><br></div><div>[1] Example taken from <a href="http://www.html5rocks.com/en/tutorials/security/content-security-policy/">http://www.html5rocks.com/en/tutorials/security/content-security-policy/</a></div>
<div><br></div></div>