Information Security Stack Exchange is a question and answer site for information security professionals. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have a web-site written in nginx.conf — which essentially accepts two parameters, an operating system and a manual page name, and does a redirect to a different site based on the parameters in the URL.

Since the intention is that the site is to be navigated and used directly from the Location bar of the browser, every character counts, and I want to make it possible to have a location that would set a cookie through a regular GET request, such that further requests for manual pages can be done without specifying an operating system.

However, I realised that if I unconditionally set a preference/cookie based on a parameter in the URL, then it would make my site subject to XSS, since any other webpage could construct a malicious cookie-setting URL, and load it in the background, amending cookies for my site, and breaking the security paradigm.

What is the solution? Can I not set cookies securely in a language like nginx.conf that carries no state between requests?

share|improve this question

Since there are only a few BSD versions, you can easily do white-listing on the server. Only set the cookie if "OS-version" matches the allowed OS-versions. If check fails redirect the user to the document root of your website.

I don't see why this would be an XSS attack since the modified cookie is not read and used anywhere on the client side with JavaScript. If I'm mistaken, please tell me.

share|improve this answer
It would be an attack vector if a malicious web-page were to set the cookie to anything other than what the user has set it to prior. E.g. if you're an openbsd user, and expect an openbsd man.cgi page when omitting the os in the uri, it'll certainly not please you to get a netbsd page instead. One way to partially prevent this is to do some matching through User-Agent, but my Referer solution sounds much more flexible and reliable. – cnst Mar 13 '13 at 20:34
You're right. Authenticity and integrity of the cookies can be achieved by hmac(cookiePayload, secretKey) and then appending the output to the cookie. For each request you then have to check that the hash in the cookie is correct. – Matrix Mar 13 '13 at 21:17
This is not exactly related to the question: the question is not about authenticity or integrity, but about XSS. I don't care what the value of the cookie is, as long as it was typed in and authorised by the user, and not JavaScript from a malicious third-party. Verification of actual cookie values is a secondary matter, which is not XSS related as far as the present question goes. Also, there is no hmac in the nginx.conf language. – cnst Mar 13 '13 at 22:33
Checking for authenticity and integrity enables you to know whether the cookie has been created by you and whether it has been modified. This way you can trust the cookie. nginx was not designed to be used in this way as you're clearly hitting its limitations. – Matrix Mar 13 '13 at 23:31
You're completely redefining my question and design principles: if there was a way for the user to manually edit the cookie, all power to them. The whole OS value is supplied by the user and, as a redirection service, we have little clue of whether or not the value is correct (it can include release numbers, for example, and we have no clue whether those releases exist); so, it's pointless to try to check for authenticity of such cookies; IMHO, your hmac suggestion is overly complicated compared to a simple Referer check, without any extra benefits, and fails on meeting the requirements. – cnst Mar 14 '13 at 4:36
up vote 0 down vote accepted

It would seem like the solution is to provide the user with an intermediate page after they enter the cookie-setting URL.

On such page, simply provide a link back to itself.

Within nginx.conf, check for $http_referer in a location of such page; if it matches $request_uri, set the cookie; otherwise, serve the page with the link to itself, with Cache-Control: no-cache.

This solution relies on the idea that it is not possible to modify the HTTP Referer header (through JavaScript or otherwise) in requests performed by web browsers.

It would even be immune even if it was possible to access raw TCP sockets from JavaScript (raw sockets from web-browser's JavaScript are not possible for security reasons) and create your own custom requests, because even then such sockets would exist in a separate realm than the HTTP requests from the web-browser engine itself, and replies would not be treated as HTTP, and would be unable to set any cookies.

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.