It is indeed possible to do this using data:
URLs:
<a href="data:application/octet-stream;charset=utf-16le;base64,//5mAG8AbwAgAGIAYQByAAoA">text file</a>
However, if you still wish to use the CGI method, there are security risks of allowing a page to echo POSTed data. This is known as reflected Cross Site Scripting (XSS).
Say you have a CGI listening on https://example.com/cgi-bin/downloader
.
Assume the user is already authenticated with your basic authentication and then receives an email containing a link. The user visits the website in the email (say evil.com
) which creates a POST request submitted by JavaScript to https://example.com/cgi-bin/downloader
containing a HTML document which also contains some JavaScript to send the cookies from your domain to the attacker. Even if you are setting the correct content-type
header to identify the HTTP response as XML, some browsers (IE) will try to sniff the content and present the Content Type that the browser thinks it is to the user (HTML in this case). To avoid this, make sure that the following header is set in the response:
X-Content-Type-Options: nosniff
So using this header in combination with a Content Type of text/xml
in the response should mitigate the risk of XSS. I also recommend the Content-Disposition header being set so the file will be downloaded rather than displayed:
Content-Disposition: attachment; filename="bar.xml"
To prevent other sites making requests to your CGI service in the first place, you could use a CSRF prevention method. The recommended method is the "Synchronizer Token Pattern" and this involves creating a server side token that is tied to user session that must be submitted with the POST request. Whether this is possible with your system using basic authentication is for you to decide. The Referer
header can be used, although this is less secure:
checking the referer is considered to be a weaker form of CSRF protection. For example, open redirect vulnerabilities can be used to exploit GET-based requests that are protected with a referer check and some organizations or browser tools remove referrer headers as a form of data protection. There are also common implementation mistakes with referer checks. For example if the CSRF attack originates from an HTTPS domain then the referer will be omitted. In this case the lack of a referer should be considered to be an attack when the request is performing a state change. Also note that the attacker has limited influence over the referer. For example, if the victim's domain is "site.com" then an attacker have the CSRF exploit originate from "site.com.attacker.com" which may fool a broken referer check implementation. XSS can be used to bypass a referer check.
In short, referer checking is a reasonable form of CSRF intrusion detection and prevention even though it is not a complete protection. Referer checking can detect some attacks but not stop all attacks. For example, if you HTTP referrer is from a different domain and you are expecting requests from your domain only, you can safely block that request.
You should also test this to make sure that script will not be executed when an XML is downloaded using Internet Explorer.