Cookie is a special type of HTTP header.
Javascript can retrieve all cookies for the current page (e.g.
https://stackoverflow.com/a/3400787/418439).
However, it is not possible to retrieve the header of the current
page
(Accessing the web page's HTTP Headers in JavaScript)
unless making another request.
Why it is designed in this way? Due to security concern?
Related
If for example, an installed third party package issues an HTTP request to their servers, and by default, any HTTP request leaves with the cookies content in the request headers, doesn't it make the content to be exposed to the server who receives the request? I don't get how httpOnly prevents from the access token to be revealed...
HTTP requests carry with it only cookies that are applicable to the domain being requested, not all of the browser's cookies. If you have a browser with cookies for bank.com, shop.com, and evil-site.com, a request to evil-site.com would only send evil-site.com cookies with the request. Not so useful.
Now say a malicious script has infected bank.com and has placed itself on a page in that domain. Now that script is running in the context of bank.com and the currently viewing user. It can now read bank.com's non-HttpOnly cookies using document.cookie and send them to evil-site.com with a simple script. This means that if you logged in to bank.com and viewed that infected page, your login cookies can now be stolen.
Marking a cookie as HttpOnly tells the browser not to expose the cookie to JavaScript, i.e. any script, legit or not, cannot read the cookie's value from document.cookie. So if bank.com made their login cookie HttpOnly, this cookie would not be readable by any script on the page. However, the cookie is still passed back and forth between browser and bank.com in requests and responses while the cookies are present and valid.
HttpOnly is just one of the many measures to prevent cookie theft and should be complemented by other security features. Secure makes sure the cookie is only ever sent through HTTPS connections. SameSite defines when the cookie is allowed to cross sites. HTTPS connections prevent reading the request over the network.
The httpOnly attribute purpose is to hide the cookie from the JavaScript context.
To observe it, you can type document.cookie in the console of any web page, and you'll notice that the result contains all of the cookies that are not httpOnly and from the current domain. You can verify it with the Application tab of the DevTools.
That means if an attacker somehow manages to execute malicious code on a user's web page (e.g. by exploiting a script injection vulnerability), he may be able to send requests on behalf of that user but he should not be able to retrieve the cookie's value.
I'd like to generate a file on a website using JavaScript and provide it for download by the user. I learned that this is not possible using plain JavaScript and HTML5.
I'm thinking of posting the generated file contents to a CGI function on my server that just echoes the data. By setting the right headers I could provide the data for download this way.
I'm wondering if such an echo CGI function could be misused and result in security problems. The website (also the CGI function) is password protected using basic authentication.
Any comments?
It is indeed possible to do this using data: URLs:
text file
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.
If all it does is echo data coming from the client, I don't see any security issues. That data was already known to the client. You are just changing headers so the browser will allow you to save the contents as a file.
You are not disclosing any information to parties that don't already have access.
I'm fairly new to JavaScript and I'm trying to access a page that requires user authentication before that page is displayed.
How do I access this page? (I have the required user name and Password) I'm know we can use the XML HTTPrequest object to access other URLs via the script. But I'm not aware of any option that lets me authenticate first.
How do I do this?
You should probably make a request to the authentication page, sending username and password. That would set a session cookie that the browser will handle on his own, then the session cookie will automatically be forwarded to the following requests you make, until the session expiral.
Remember however about the limits of cross-domain scripting, e.g. if the page you want to authenticate is in a different domain than the one the page the script is running in is the browser will likely refuse to make any request.
Actually this automatic cookie handling from the browser is the reason cross-domain scripting is insecure and thus forbidden for most sites.
I am testing CSRF on one website. The website prevents CSRF by checking the referrer field. Now I have created an HTML page which sends the request. How can I add the referrer field to that request using JavaScript or any other method?
A web page shouldn’t be able to add a Referer header to a request using JavaScript. However, according to Wikipedia, there are still some problems with relying on the Referer header:
Some proxies automatically strip out the Referer header. So it’s not always there.
A web page “can suppress the Referer header by issuing requests from FTP or HTTPS URLs.”
“[O]ld versions of Flash (before 9.0.18) allow malicious Flash to generate GET or POST requests with arbitrary HTTP request headers using CRLF Injection.”
Just wondering if it's possible to use an XMLHTTPReq to login to a website, and store the cookie. Specifically I'm after the PHPSessionID from the website I am logging into.
I then want to pass this cookie into another request to submit a form.
Any ideas of how to do this?
Cheers,
Nick
You will be able to get your own site's cookies from document.cookie. In the AJAX callback, use a library to parse the value and read the cookie you're looking for.
Of course, if the server sets the cookie HttpOnly (which it should be doing), it won't be available in document.cookie.
At this pont, you need to reevaluate what you're doing:
If the form points to your website, your server script would have access to the cookie anyway.
If you're sending the user's session ID to another domain, why? This is a huge red flag that screams security problem.
If you're logging in to another site, then no – the same-origin policy prevents you from accessing another site's cookies.
Edit: Since this is for your own use, you can do this in a way you're not limited by the browser's origin restrictions. Some thoughts:
You could make a Chrome extension. Extensions aren't subject to origin restrictions, and the development model and API is pretty much the same as what you'd do on a regular web page.
You could use Node, which has no restrictions. You'd be able to invoke your script from the command line, but the API is going to be slightly different that what you'd use in a web page.
Use your language and framework of choice to POST to the login page, get the Set-Cookie header in the response, and use it to send a Cookie header in another POST to the form target.
You can only send cross-origin requests using XHR if both the browser and server support CORS. Additionally, the third party site needs to allow your site to send such requests and to receive its responses. If it doesn’t, you aren’t allowed to send the request or receive its response respectively.