问题
I'm facing a security problem with ESI on Symfony2 (2.2) :
Some ESI of my application don't require to be logged and are public, but other ESI required the user to be logged and have the role ROLE_USER, for example.
The problem is that every guy can display an ESI, by writing its URL in the address bar of the navigator... So a man can access to a ESI (that is called inside an action which requires an admin role), even none logged !
For example, my ESI "SybioWebsiteBundle:Controller:showEsiAction" can be read at this URL : http://mywebsiteurl.com/_proxy?_path=id%3D1%26slug%3Dlorem%26locale%3Dfr%26ranks%3D1-2-3-5-6-7%26page%3D1%26isPhotograph%3D1%26_format%3Dhtml%26_controller%3DSybioWebsiteBundle%253AAlbum%253AshowEsi
This ESI should only be visible by logged users : they go to showAction, and inside the Twig template, this ESI is called... But all people can cheat and read thanks to this "issue" !
I searched solutions, I got one really ugly : check if the user is logged in the ESI action... it's OK, but I'm using HTTP Cache validation to optimize my site loading (and memory). So if I choose this solution, I need to add an additionnal ETag that test the user role, to clear the ESI cache each time a none user access to the ESI, and display an empty response, and after if one is logged, clear it again and display the normal view, etc...
I now that people who want to cheat will be uncommon, so it could be a satifying solution... In theory, the cache won't be constantly cleared because of them, luckily !
But I want to know if you have another solution ? Thanks !
回答1:
In <=2.1
versions, the ESI URL came from importing the internal.xml routing file, which exposed a regular Symfony route that was capable of rendering any controller.
If a normal user had access to this, they could render any controller with any arguments in your system, which is the issue you are currently facing.
In >=2.2
, the internal.xml routing file is gone. You now have a fragments key in config.yml
. Instead of a route, this activates a listener that watches for any requests that start with /_proxy
, which is the URL that the ESI tags now render as.
This alone doesn’t help security, except that the listener uses a few tricks internally.
So what prevents an evil user from exploiting this URL to render any controller in our system with any parameters? Since 2.2
, there are two built in protections: trusted proxies and signed URLs.
The class that handles all this magic is called FragmentListener
. Before it starts serving anything from your application, it first checks to see if the person requesting is “trusted”.
If you’re using a reverse proxy like Varnish, then you’ll want to add its IP address or - CIDR IP address range for the super-geeks - to your config.yml file:
framework
trusted_proxies:
- 192.168.12.0
If the request comes from this IP or range, it allows it. And, if it comes from a local address, it also allows it. In other words, if it’s someone you trust, then it’s ok.
来源:https://stackoverflow.com/questions/16817671/security-esi-issue-with-symfony2