Imagine a scenario where you own mysite.com, and it loads javascript from an exterior domain such as adsprovider.com/ads.js.
Can adsprovider.com's javascript then perform an ajax call to mysite.com and attempt to retrieve the user's session data? If so, how can you protect your users against it?
Can adsprovider.com's javascript then perform an ajax call to mysite.com
Yes. The origin is defined by the URL of the HTML document the script is loaded into, not by the URL the script itself is loaded from.
retrieve the user's session data
Only if the session data is exposed through HTTP. Stuff you never give to the client is safe (but there is probably going to be quite a lot of session data that should be kept private between your server and the user).
Note that the script can read document.cookies and steal the session token too (unless the session token is sent with the httponly flag on).
If so, how can you protect your users against it?
Sandbox the adverts in iframes hosted on different origins.
Fortunatly, an Ajax call for your session data can't be directly request from external server.
You can load javascript from a CDN external source of course, but the script run from your own domain, and access to your server is not possible from outside.
Otherwise there would be a lot of security problem.
Also keep in mind that javascript is client side.
You can check Same-origin policy and CORS for more info on this topic.
Related
I am working with CORS on a website.
Code sample:
header("Access-Control-Allow-Origin: *");
session_start();
$session_id = session_id();
This code is working fine, but it's returning a new session id every time.
How can I maintain the session data in this situation?
Although you allow access from external domains with the Access-Control-Allow-Origin header, the session itself is cookie based.
If the script which makes the request is delivered from the external domain, it will not be able to read the cookie and pass it to your server.
Solution: Deliver the JS which makes the call from the same context (i.e. same protocol/domain/port) as the AJAX service. Also make sure that the cookie itself is not restricted to a different subdomain or path.
DO NOT try passing the session identifier by POST or GET requests, this will make your application vulnerable to CSRF.
By the way, setting the allowed origin to * is also discouraged, because it can also be used for XSS/CSRF, in combination with other techniques. Please do limit requests to the third-party domain.
Last, but not least, you might also want to look into the subject of preflight requests via HTTP OPTIONS.
A server (in this case the PHP application) can have a session with many different clients at the same time. There is no way for the session to tell which session belongs to which client without having the PHPSESSID cookie. This cooke has to set in the request header for PHP to identify the client.
Okay, on my website, I have a lot of embedded pages for Twitch. Below all the embeds, I also have an authorization flow so that people can log into Twitch and click a follow button.
Normally, the flow would start at: mydomain.com/channel/name, and at the end of the flow, they would be returned to mydomain.com/auth. Originally, I had it so that the start URL would be stored in browser session storage using javascript; and then when they reach the final auth endpoint, I would use the javascript and pull the session storage and relocate them back to the original URL.
This has been working great... however, one of the features I have on my website is the ability to use custom canonical urls to proxy to their channel on my website. So someone could use theirdomain.com to proxy to mydomain.com/channel/them.
This created an issue with the session storage since session storage follows cross-domain restrictions. They would start at theirdomain.com and end at mydomain.com/auth. Since the domains don't match, I can't access the session storage to forward them back to the original URL.
I am using PHP, so I'm wondering what would be the best way to get around this. I figure instead of storing the start URL in session storage, I can save it using AJAX to temporary storage using PHP, linked to their IP addresses. However, I don't know how to do this.
Does PHP have some sort of temporary storage system with definable TTL? That also works across multiple domains? (it would be the same server)
If the request is proxied to the same application then the session is accessible, it's just the session identifier (which is stored in a cookie, hence the cross domain issue) which is causing the problem.
What you can do is pass the session identifier from one domain over the transition to the other domain, as part of a get request, so when you do the leap from theirdomain.comto example.com do it with a link formatted as http://example.com/blah/?session_id=[session_id_from cookie] (ideally using https).
Then on on example.com grab the session_id and use that to set the session_id in the cookie for that domain, and it will load the session from the source domain.
This can be used for session hijacking, but so can having your session_id in a cookie, so it's generally OK to do, though using https endpoints will improve security.
I'm coding a php framework to add functionalities for a second party website, which is not ours and don't have control at all.
This website has Oauth 2.0 authorization for its clients and save access token in cookies. As I must interact with their own public API, I need to read that token to make my requests.
Question is.. which is the best strategy to code that? I'm not a php programmer but very proficient in C++. I wonder if its possible to open website inside an IFRAME and read cookies with javascript, am I making any sense????
If you really want to do that, open the site in a hidden iframe, the page that the iframe loads should have something like
window.parent.getCookie(/* the cookie value*/);
So you can use the getCookie method is in your main site and read the external site cookie, then you can use ajax to send the cookie value to your script, and work with it or save it as a cookie, you can also use javascript to save the cookie.
EDIT: Remember cookies should never store sensitive data, even in your own site.
Say I'm on my home PC with my browser open, I visit a site that uses sessions, as long as I don't close my browser or remain idle for 24 minutes the session will be maintained as I make subsequent HTTP requests to the site.
However on my server running PHP, if I use fopen() or file_get_contents() to request a page from that same site, does that site create a session for the 'user' that is my server? Is there a way to keep the connection open so the session is maintained for subsequent fopen() requests?
Can I do this by passing the session id in the request headers on the subsequent request? ie I set the headers including the session id, pass the headers to a context_stream_create(), and then pass the context with the next fopen() request? Can this be done for POST requests (which is what I really need to do)?
Any app which can speak HTTP language have the capability to save the cookie and therefore save the state in HTTP.
The answer to your questions is YES. You can do anything you want with just using the right protocol ( GET/POST ) and sending proper headers ( Host, User-Agent, ... )
But you have an alternate solution, i think this class will help : PHP Browser Class
If I had a user logged onto my site, having his id stored in $_SESSION, and from his browser he clicked a 'Save' button which would make an AJAX request to the server. Will his $_SESSION and cookies be retained in this request, and can I safely rely on the id being present in the $_SESSION?
The answer is yes:
Sessions are maintained server-side. As far as the server is concerned, there is no difference between an AJAX request and a regular page request. They are both HTTP requests, and they both contain cookie information in the header in the same way.
From the client side, the same cookies will always be sent to the server whether it's a regular request or an AJAX request. The Javascript code does not need to do anything special or even to be aware of this happening, it just works the same as it does with regular requests.
If the PHP file the AJAX requests has a session_start() the session info will be retained. (baring the requests are within the same domain)
What you're really getting at is: are cookies sent to with the AJAX request? Assuming the AJAX request is to the same domain (or within the domain constraints of the cookie), the answer is yes. So AJAX requests back to the same server do retain the same session info (assuming the called scripts issue a session_start() as per any other PHP script wanting access to session information).
Well, not always. Using cookies, you are good. But the "can I safely rely on the id being present" urged me to extend the discussion with an important point (mostly for reference, as the visitor count of this page seems quite high).
PHP can be configured to maintain sessions by URL-rewriting, instead of cookies. (How it's good or bad (<-- see e.g. the topmost comment there) is a separate question, let's now stick to the current one, with just one side-note: the most prominent issue with URL-based sessions -- the blatant visibility of the naked session ID -- is not an issue with internal Ajax calls; but then, if it's turned on for Ajax, it's turned on for the rest of the site, too, so there...)
In case of URL-rewriting (cookieless) sessions, Ajax calls must take care of it themselves that their request URLs are properly crafted. (Or you can roll your own custom solution. You can even resort to maintaining sessions on the client side, in less demanding cases.) The point is the explicit care needed for session continuity, if not using cookies:
If the Ajax calls just extract URLs verbatim from the HTML (as received from PHP), that should be OK, as they are already cooked (umm, cookified).
If they need to assemble request URIs themselves, the session ID needs to be added to the URL manually. (Check here, or the page sources generated by PHP (with URL-rewriting on) to see how to do it.)
From OWASP.org:
Effectively, the web application can use both mechanisms, cookies or
URL parameters, or even switch from one to the other (automatic URL
rewriting) if certain conditions are met (for example, the existence
of web clients without cookies support or when cookies are not
accepted due to user privacy concerns).
From a Ruby-forum post:
When using php with cookies, the session ID will automatically be sent in the request headers even for Ajax XMLHttpRequests. If you
use or allow URL-based php sessions, you'll have to add the session id
to every Ajax request url.
It is very important that AJAX requests retain session. The easiest example is when you try to do an AJAX request for the admin panel, let's say. Of course that you will protect the page that you make the request to, not to accessible by others who don't have the session you get after administrator login.
Makes sense?
One thing to watch out for though, particularly if you are using a framework, is to check if the application is regenerating session ids between requests - anything that depends explicitly on the session id will run into problems, although obviously the rest of the data in the session will unaffected.
If the application is regenerating session ids like this then you can end up with a situation where an ajax request in effect invalidates / replaces the session id in the requesting page.
That's what frameworks do, e.g. if you initialize session in Front Controller or boostrap script, you won't have to care about it's initalization either for page controllers or ajax controllers. PHP frameworks are not a panacea, but they do so many useful things like this!
put your session() auth in all server side pages accepting an ajax request:
if(require_once("auth.php")) {
//run json code
}
// do nothing otherwise
that's about the only way I've ever done it.