Today I faced the term "cookiejar" (package net/http/cookiejar). I tried to gather some information regarding it, but got nothing intelligible came out. I know that cookie is key/value pairs that server sends to a client, eg: Set-Cookie: foo=10, browser stores it locally and then each subsequent request browser will send these cookies back to the server, eg: Cookie: foo=10.
Ok, but what about cookiejar? What is it and how does it look like?
As you described in your question, cookies are managed by browsers (HTTP clients) and they allow to store information on the clients' computers which are sent automatically by the browser on subsequent requests.
If your application acts as a client (you connect to remote HTTP servers using the net/http package), then there is no browser which would handle / manage the cookies. By this I mean storing/remembering cookies that arrive as Set-Cookie: response headers, and attaching them to subsequent outgoing requests being made to the same host/domain. Also cookies have expiration date which you would also have to check before deciding to include them in outgoing requests.
The http.Client type however allows you to set a value of type http.CookieJar, and if you do so, you will have automatic cookie management which otherwise would not exist or you would have to do it yourself. This enables you to do multiple requests with the net/http package that the server will see as part of the same session just as if they were made by a real browser, as often HTTP sessions (the session ids) are maintained using cookies.
The package net/http/cookiejar is a CookieJar implementation which you can use out of the box. Note that this implementation is in-memory only which means if you restart your application, the cookies will be lost.
So basically an HTTP cookie is a small piece of data sent from a website and stored in a user's web browser while the user is browsing that website.
Cookiejar is a Go interface of a simple cookie manager (to manage cookies from HTTP request and response headers) and an implementation of that interface.
In general it is a datastore where an application (browser or not) puts the cookies it uses during requests and responses. So it is really a jar for cookies.
Related
I have a resource (an html web page, but it could be anything else like json/xml describing a book) and retrieve it with a GET request:
http://127.0.0.1/welcome
This resource is in Japanese (because kawai desu). Now, I do a GET request on this resource, asking server for another language:
http://127.0.0.1/welcome?lang=en
So the server responses with the English version of the resource. But from now on, since I called ?lang=en, I want to set the default language of the user in a cookie. So server adds a cookie to its response:
Cookie: language=en
Browser now have the language=en cookie. Then, I ask for the resource without GET parameters and the server delivers the English version because the browser sent the Cookie:language=en request header:
http://127.0.0.1/welcome
Returns the English version.
These queries look like retrieving (a resource with a cookie), idempotents (doesn't change a bit when send several times) and safe (server-modification less) queries to me: am I right to use GET requests even if they involve cookies?
Two GET requests have the same URI http://127.0.0.1/welcome
but different results: how does caching (browser and proxy) handle
this?
GET response for http://127.0.0.1/welcome?lang=en could be cached too: will (proxy/CDN, browser) cached responses include the language=en cookie (so user language for the website switches to en)?
I am using Firefox 22 and Selenium IDE 2.2.0.
I have loaded a page in firefox using the HTTP protocol (not HTTPS). I know for sure that the page has set a secure cookie (as a result of an embedded AJAX request). I can verify this using the browser internal url chrome://web-developer/content/generated/view-cookie-information.html - because among other cookies that page shows a cookie like this:
Name WC_AUTHENTICATION_5122759
Value 5122759%2cDKppXa7BAqnZ0ERDLb0Wee%2bXqUk%3d
Host .testserver.dk
Path /
Expires At end of session
Secure Yes
HttpOnly No
However, when I run assertCookie in the Selenium IDE I can only see the unsecure cookies. I.e. all cookies - except then one above - are detected by Selenium IDE:
Executing: |assertCookie | glob:WC_AUTHENTICATION_* | | yields this set of visible cookies:
[error] Actual value 'JSESSIONID=0000uCQdh2FZ0ZA8z-O5zcGoUtD:-1;
WC_PERSISTENT=lT8Z5tbkQrvLhNm%2bGyCj%2bh4yPAU%3d%0d%0a%3b2013%2d07%2d05+13%3a18%3a18%2e807%5f1373023098807%2d3048%5f10201%5f5122827%2c%2d100%2cDKK%5f10201;
WC_SESSION_ESTABLISHED=true;
WC_ACTIVEPOINTER=%2d100%2c10201; WC_USERACTIVITY_5122827=5122827%2c10201%2cnull%2cnull%2cnull%2cnull%2cnull%2cnull%2cnull%2cnull%2cy6bjcrZgvCVe5c52BBKvcItxyF5lLravpDq9rd9I0ZmRfRNxcC2oG13Eyug3kKgbtLOHVLxm9T76%0d%0a%2fGJFLp5bOrkPoNqmc38TIr%2fO7eU%2fbd7Mfny2kQg7v6xGweYoRkXYgAEz91rH0QavFhlOjpd12A%3d%3d;'
did not match 'glob:WC_AUTHENTICATION_*'
So does anyone know how can I use the Selenium IDE to verify the presence of secure cookies on a page loaded with http:// (not https://) ?
Sadly, what you are doing is breaking the specifications. A secure cookie is suppose to be only available if the connection is secure. Hence, if you are connecting with HTTP, you can't see it.
However, if this is just on your test machine (not your end user), you can modify the response from the server using Fiddler. With Fiddler, you can program something like, if you see this cookie, add another cookie, or strip the secure flag.
EDIT:
Some background information about Selenium and cookies:
Selenium works through the browser with JavaScript as part of the page. Because it is essentially a part of the page, it has to follow all the same rules as the page. This means that it still has to abide by the security rules on cookies. A secure only cookie can only be read on a secure connection, thus Selenium cannot read a secure cookie if it's not on a secure connection.
The place where HTTP request comes in is that cookies are a part of the HTTP header. Both the request (from the browser) and the response (from the server) have an HTTP header. Cookies are present in both.
You want to verify if the server has set the cookie, so you want to inspect the HTTP response from the server for the presence of the cookie. Because of security restrictions, however, you cannot from Selenium. These security restrictions are enforced by the browser. All reputable browsers enforce these policies, since without these policies, the end user's credentials will be easily compromised.
This is where Fiddler comes in. Fiddler inspects the HTTP data at a lower level, before the browser gets to it. Thus, you can use Fiddler to manipulate the data before it gets to the browser to give some kind of indication that the cookie was present.
I have a website that uses asynchronous http requests (ajax, to use the common misnomer) for performing login and registration. The authentication cookie is set by the asynchronous request and it all works great.
I recently locked down the registration and login actions to require https. Everything appears to work, except that the authentication cookie returned isn't functioning properly and the user doesn't actually get logged in.
In Chrome, in the development tools, under resources, it doesn't show any cookies having been created. If I go to the Chrome settings and view all the cookies, I can see that a cookie has been created. Perhaps it's encrypted and not readable?
So, to summarize:
The initial page is loaded using normal HTTP
The Login action is an asynchronous HTTPS request
The authentication cookie returned by the HTTPS request doesn't seem to be working
How do I get this to work?
A couple things I should note:
This is not a CORS issue.
I am aware of the potential man-in-the-middle attack. This website does not house sensitive data. I'm attempting to do something very similar (if not exactly the same) to what reddit is doing.
I managed to figure this out. Turns out that in the Http response, you need to set the Access-Control-Allow-Credentials header to true. Also, you must set the withCredentials to true on the client-side http request.
I was trying to understand CORS. As per my understanding, it is a security mechanism implemented in browsers to avoid any AJAX request to domain other than the one open by the user (specified in the URL).
Now, due to this limitation many CORS was implemented to enable websites to do cross origin request. but as per my understanding implementing CORS defy the security purpose of the "Same Origin Policy" (SOP).
CORS is just to provide extra control over which request server wants to serve. Maybe it can avoid spammers.
From Wikipedia:
To initiate a cross-origin request, a browser sends the request with
an Origin HTTP header. The value of this header is the site that
served the page. For example, suppose a page on
http://www.social-network.example attempts to access a user's data
in online-personal-calendar.example. If the user's browser implements
CORS, the following request header would be sent:
Origin: http://www.social-network.example
If online-personal-calendar.example allows the request, it sends an
Access-Control-Allow-Origin header in its response. The value of the
header indicates what origin sites are allowed. For example, a
response to the previous request would contain the following:
Access-Control-Allow-Origin: http://www.social-network.example
If the server does not allow the cross-origin request, the browser
will deliver an error to social-network.example page instead of
the online-personal-calendar.example response.
To allow access to all pages, a server can send the following response
header:
Access-Control-Allow-Origin: *
However, this might not be appropriate for situations in which
security is a concern.
What am I missing here? what is the the intend of CORS to secure the server vs secure the client.
Same-origin policy
What is it?
The same-origin policy is a security measure standardized among browsers. The "origin" mostly refers to a "domain". It prevents different origins from interacting with each other, to prevent attacks such as Cross Site Request Forgery.
How does a CSRF attack work?
Browsers allow websites to store information on a client's computer, in the form of cookies. These cookies have some information attached to them, like the name of the cookie, when it was created, when it will expire, who set the cookie etc. A cookie looks something like this:
Cookie: cookiename=chocolate; Domain=.bakery.example; Path=/ [// ;otherDdata]
So this is a chocolate cookie, which should be accessible from http://bakery.example and all of its subdomains.
This cookie might contain some sensitive data. In this case, that data is... chocolate. Highly sensitive, as you can see.
So the browser stores this cookie. And whenever the user makes a request to a domain on which this cookie is accessible, the cookie would be sent to the server for that domain. Happy server.
This is a good thing. Super cool way for the server to store and retrieve information on and from the client-side.
But the problem is that this allows http://malicious-site.example to send those cookies to http://bakery.example, without the user knowing! For example, consider the following scenario:
# malicious-site.example/attackpage
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://bakery.example/order/new?deliveryAddress="address of malicious user"');
xhr.send();
If you visit the malicious site, and the above code executes, and same-origin policy was not there, the malicious user would place an order on behalf of you, and get the order at his place... and you might not like this.
This happened because your browser sent your chocolate cookie to http://bakery.example, which made http://bakery.example think that you are making the request for the new order, knowingly. But you aren't.
This is, in plain words, a CSRF attack. A forged request was made across sites. "Cross Site Request Forgery". And it would not work, thanks to the same-origin policy.
How does Same-origin policy solve this?
It stops the malicious-site.example from making requests to other domains. Simple.
In other words, the browser would not allow any site to make a request to any other site. It would prevent different origins from interacting with each other through such requests, like AJAX.
However, resource loading from other hosts like images, scripts, stylesheets, iframes, form submissions etc. are not subject to this limitation. We need another wall to protect our bakery from malicious site, by using CSRF Tokens.
CSRF Tokens
As stated, malicious site can still do something like this without violating the same-origin policy:
<img src='http://bakery.example/order/new?deliveryAddress="address of malicious user"'/>
And the browser will try to load an image from that URL, resulting in a GET request to that URL sending all the cookies. To stop this from happening, we need some server side protection.
Basically, we attach a random, unique token of suitable entropy to the user's session, store it on the server, and also send it to the client with the form. When the form is submitted, client sends that token along with the request, and server verifies if that token is valid or not.
Now that we have done this, and malicious website sends the request again, it will always fail since there is no feasible way for the malicious website to know the token for user's session.
CORS
When required, the policy can be circumvented, when cross site requests are required. This is known as CORS. Cross Origin Resource Sharing.
This works by having the "domains" tell the browser to chill, and allow such requests. This "telling" thing can be done by passing a header. Something like:
Access-Control-Allow-Origin: //comma separated allowed origins list, or just *
So if http://bakery.example passes this header to the browser, and the page creating the request to http://bakery.example is present in the origin list, then the browser will let the request go, along with the cookies.
There are rules according to which the origin is defined1. For example, different ports for the same domain are not the same origin. So the browser might decline this request if the ports are different. As always, our dear Internet Explorer is the exception to this. IE treats all ports the same way. This is non-standard and no other browser behaves this way. Do not rely on this.
JSONP
JSON with Padding is just a way to circumvent same-origin policy, when CORS is not an option. This is risky and a bad practice. Avoid using this.
What this technique involves is making a request to the other server like following:
<script src="http://badbakery.example/jsonpurl?callback=cake"></script>
Since same-origin policy does not prevent this2 request, the response of this request will be loaded into the page.
This URL would most probably respond with JSON content. But just including that JSON content on the page is not gonna help. It would result in an error, ofcourse. So http://badbakery.example accepts a callback parameter, and modifies the JSON data, sending it wrapped in whatever is passed to the callback parameter.
So instead of returning,
{ user: "vuln", acc: "B4D455" }
which is invalid JavaScript throwing an error, it would return,
cake({user: "vuln", acc:"B4D455"});
which is valid JavaScript, it would get executed, and probably get stored somewhere according to the cake function, so that the rest of the JavaScript on the page can use the data.
This is mostly used by APIs to send data to other domains. Again, this is a bad practice, can be risky, and should be strictly avoided.
Why is JSONP bad?
First of all, it is very much limited. You can't handle any errors if the request fails (at-least not in a sane way). You can't retry the request, etc.
It also requires you to have a cake function in the global scope which is not very good. May the cooks save you if you need to execute multiple JSONP requests with different callbacks. This is solved by temporary functions by various libraries but is still a hackish way of doing something hackish.
Finally, you are inserting random JavaScript code in the DOM. If you aren't 100% sure that the remote service will return safe cakes, you can't rely on this.
References
1. https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy#Definition_of_an_origin
2. https://www.w3.org/Security/wiki/Same_Origin_Policy#Details
Other worthy reads
http://scarybeastsecurity.blogspot.dk/2009/12/generic-cross-browser-cross-domain.html
https://www.rfc-editor.org/rfc/rfc3986 (sorry :p)
https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy
https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)
The Same Origin Policy (SOP) is the policy browsers implement to prevent vulnerabilities via Cross Site Scripting (XSS). This is mainly for protecting the server, as there are many occasions when a server can be dealing with authentication, cookies, sessions, etc.
The Cross Origin Resource Sharing (CORS) is one of the few techniques for relaxing the SOP. Because SOP is "on" by default, setting CORS at the server-side will allow a request to be sent to the server via an XMLHttpRequest even if the request was sent from a different domain. This becomes useful if your server was intended to serve requests from other domains (e.g. if you are providing an API).
I hope this clears up the distinction between SOP and CORS and the purposes of each.
I'm trying to determine the most secure method for an ajax based login form to authenticate and set a client side cookie. I've seen things about XSS attacks such as this:
How do HttpOnly cookies work with AJAX requests?
and
http://www.codinghorror.com/blog/archives/001167.html
So, I guess my core questions are...
1) Is using pure ajax to set cookies secure, if so, what is the most secure method (httpOnly + SSL + encrypted values, etc.)?
2) Does a pure ajax method involve setting the cookie client side? Is this at all secure?
3) Is setting cookies this way reliable across all major browsers/OSs?
4) Would using a hidden IFrame be any more secure (calling a web page to set the cookies)?
5) If possible, does anybody have code for this (PHP is my backend)?
My goal is to set the cookies and have them available for the next call to the server without navigating away from the page.
I really want to nail down the consensus, most secure way to do this. Eventually, this code is planned to be made Open Source, so please no commercial code (or nothing that wouldn't stand up to public scrutiny)
Thanks,
-Todd
The cookie needs to be generated server-side because the session binds the client to the server, and therefore the token exchange must go from server to client at some stage. It would not really be useful to generate the cookie client-side, because the client is the untrusted remote machine.
It is possible to have the cookie set during an AJAX call. To the server (and the network) an AJAX call is simply an HTTP call, and any HTTP response by the server can set a cookie. So yes, it is possible to initiate a session in response to an AJAX call, and the cookie will be stored by the client as normal.
So, you can use AJAX to do the logging in process in the same was as you could have just relied on a POST from a form on the page. The server will see them the same way, and if the server sets a cookie the browser will store it.
Basically, client-side Javascript never needs to be able to know the value of the cookie (and it is better for security if it doesn't, which can be achieved using the "httponly" cookie extension honored by recent browsers). Note that further HTTP calls from the client to the server, whether they are normal page requests or they are AJAX requests, will include that cookie automatically, even if it's marked httponly and the browser honors that extension. Your script does not need to be 'aware' of the cookie.
You mentioned using HTTPS (HTTP over SSL) - that prevents others from being able to read information in transit or impersonate the server, so it's very handy for preventing plain text transmission of the password or other important information. It can also help guard against network based attacks, though it does not make you immune to everything that CSRF can throw you, and it does not at all protect you against the likes of session fixation or XSS. So I would avoid thinking of HTTPS as a fix-all if you use it: you still need to be vigilant about cross-site scripting and cross-site request forgery.
(see 1. I sort of combined them)
Given that the cookie is set by the server in its HTTP response headers, yes it is reliable. However, to make it cross-browser compatible you still need to ensure logging in is possible when AJAX is unavailable. This may require implementing an alternative that is seen only when there is no Javascript or if AJAX isn't available. (Note: now in 2014, you don't need to worry about browser support for AJAX anymore).
It would not change the security. There would be no need for it, except that I have seen hidden iframes used before to 'simulate' AJAX before - ie make asyncronous calls to the server. Basically, however you do it doesn't matter, it's the server setting the cookie, and the client will accept and return the cookie whether it does it by AJAX or not.
For the most part, whether you use AJAX or not does not affect the security all that much as all the real security happens on the server side, and to the server an AJAX call is just like a non-AJAX call: not to be trusted. Therefore you'll need to be aware of issues such as session fixation and login CSRF as well as issues affecting the session as a whole like CSRF and XSS just as much as you would if you were using no AJAX. The issues don't really change when using AJAX except, except, I guess, that you may make more mistakes with a technology if you're less familiar with it or it's more complicated.
Answer updated September 2014