symfony2 behind Amazon ELB: always trust proxy data? - symfony

I'm running a Symfony2 web application on AWS, and am using an Elastic Load Balancer.
In a controller method, I need to do the following to get the IP of a user requesting a web page:
$request->trustProxyData();
$clientIp = $request->getClientIp(True);
Does this present any security risks? I'm not using the client IP for privilege escalation, I'm just logging it.
Is there some way to force trustProxyData() always, or otherwise reconfigure $request->getClientIp() to DWIM? My app will always be behind a load balancer (except while I do development on my desktop).
Related: http://fabien.potencier.org/article/51/create-your-own-framework-on-top-of-the-symfony2-components-part-2 (but it doesn't say if there's some global config so I don't have to call trustProxyData() everywhere).

You can configure the framework bundle to do this: http://symfony.com/doc/2.0/reference/configuration/framework.html#trust-proxy-headers
framework:
trust_proxy_headers: true

I am not sure about any general security risks, but I can give you a tip how to avoid calling this method in each controller action.
In your app.php just before the $kernel->handle(...); you should set:
Request::trustProxyData();
Cheers ;)

Note:
The trust_proxy_headers option is deprecated and will be removed in Symfony 2.3.
See a trusted_proxies and a Trusting Proxies for details on how to properly trust proxy data.

I used
Request::setTrustedProxies(array($request->server->get('REMOTE_ADDR')));
in web/app.php to solve the problem.
See my answer here: https://stackoverflow.com/a/28793609/2030937

In modern symfony versions: https://symfony.com/doc/current/deployment/proxies.html#but-what-if-the-ip-of-my-reverse-proxy-changes-constantly
If your elb is behind a cloudfront proxy you should take a look at this package too:
https://packagist.org/packages/fmaj/cloudfront-trusted-proxies

Related

Yaws basic auth letsencrypt

I have a domain in stealth mode, protected by basic auth. Basic auth is not supported by Letsencrypt and probably never will (https://github.com/certbot/certbot/issues/1744#issuecomment-162038303).
After moving from Nginx to Yaws, the next Letsencrypt renewal is scheduled. So here is a problem. I could disable basic auth in Yaws, do the renewal and then enable again, but that is no real solution.
There are easy workarounds for Apache and Nginx, i.e. define an exception to basic auth for the directory /.well-known/acme-challenge.
How to do that in Yaws? The basic auth definition for my domain in yaws.conf is now
<auth>
realm = "some realm"
user = "some_user:some_pw"
</auth>
The only reference within this context with respect to Yaws I found is from 2010 and refers to Yaws 1.81 (https://uu.diva-portal.org/smash/get/diva2:344199/FULLTEXT01.pdf). Letsencrypt started 2015. I use Yaws 2.0.9.
There seems to be a solution for FreeDNS with shell variables (https://gist.github.com/ammgws/381b4d9104c4e2b43b9210f33f03a15a). Similar hacks are given at https://github.com/acmesh-official/acme.sh/blob/master/dnsapi/, but I have no idea how to use such an approach.
For each subdirectory you want to exclude, add a .yaws_auth file to that subdirectory with the contents
{allow, all}.
and be sure to include the trailing period/full stop. Also make sure that auth_skip_docroot is either set to false or not set at all in your yaws.conf file.

IdentityModel.OidcClient library doesn't seem to work with UWP

We are using ASP.NET Identity with IdentityServer4. We've added a Client to use with Azure AD. This works great within a web page, that part is working.
Our end goal is a UWP app, so we found the IdentityModel.OidcClient which has a UWP sample. This sample has two browser classes. We configured HTTPS, but the WabBrowser class now refuses to connect to the site at all. If I change the config to hit https://demo.identityserver.io then it works, but all the other config is the same, so I'm not sure what the problem could be. It shows an error message in the pop up browser that it could not connect.
I looked at the SystemBrowser class, but this logs in fine, then the browser window does not close, and even if we close it, the code doesn't move on to get back a result. Looking at the source, this is not surprising, it calls:
Launcher.LaunchUriAsync(new Uri(options.StartUrl));
and that's all. The RedirectUri is not passed in, and mechanism appears to exist to use it. So, the behaviour we see appears to be the extent of what the class can do.
Looking at the console .NET Core sample, it has a SystemBrowser class that works. I updated the UWP sample to use the Fall Creators Update and was able to bring in the ASP.NET Core dlls needed to compile this code. It sets up a class like this:
public LoopbackHttpListener(int port, string path = null)
{
path = path ?? String.Empty;
if (path.StartsWith("/")) path = path.Substring(1);
_url = $"http://127.0.0.1:{port}/{path}";
_host = new WebHostBuilder()
.UseKestrel()
.UseUrls(_url)
.Configure(Configure)
.Build();
_host.Start();
}
and I can confirm this gets called only once, but even if I hard code an unused IP address, I get an error that the IP is in use.
So, at this stage, the sample that exists for UWP works for the demo server but not for ours (I suspect an HTTPS issue, but that's not the error I get), and importing code that works for a Core sample, does not work either. I've spent a couple of days on this and would appreciate a nudge in the right direction.
So, to recap, the WabBrowser seems the best bet but, for my localhost IdentityServer I get this:
and if I try to use a .NET Core library that works elsewhere, it thinks a port is in use. I suspect I need to work out why WabBrowser can't connect to my local site. I have turned off Fiddler. I can browse to my https URL and get a disco document, in the browser, at https://localhost:44305/.well-known/openid-configuration.
There are extra steps necessary to enable localhost in the Web Authentication Broker -
https://msdn.microsoft.com/en-us/library/windows/desktop/jj658959%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
This website gave me the fix. Here is a synopsis:
Remove loopback isolation
For security and reliability reasons, UWP applications are not allowed to send requests to the loopback interface. While Visual Studio automatically creates exemptions for debugged apps, this feature won't be helpful in this case, as the authentication broker always executes in a separate process.
If you see this (cryptic) error message in your Windows event logs, then you're likely facing this issue:
AuthHost encountered a navigation error at URL: [...] with StatusCode: 0x800C0005.
One option to fix it is to use the loopack exemption utility developed by Eric Lawrence. It's natively included in Fiddler 4 but can also be downloaded as a standalone software. To allow the authentication broker to communicate with the loopback interface, exempt the applications starting with microsoft.windows.authhost and save your changes:
If everything was properly configured, you should now see the login/consent page returned by your server.

Nginx authentication using JWT and an external authentication server in a multi-tenant system

I am building a multi-tenant system fronted by Nginx.
I want all requests hitting Nginx to first be 'filtered' on whether they have a valid JWT. If not, there should be a 'call out' to an external authentication server which will do SAML/SSO and return a JWT or 'false'. If false, then a 401 is returned.
If there is a valid JWT, it needs to be interpreted and the tenant name extracted. Then, depending on the request path, the url/POST body will need to be modified to include the correct tenant (we are hitting an Elasticsearch and need to make sure that a tenant is only allowed to query their own indexes)
The Authentication server will be built in php, so what we need is just the 'filter' part and a valid way of calling the Auth server. Is there any off-the-shelf nginx module which will solve this requirement? Or is Lua my best bet here? I'm a relatively novice Nginx-er.
There is much better and simpler JWT based authentication module for nginx.
Highly configurable.
https://github.com/tarachandverma/nginx-openidc
You can configure multiple relying parties.
https://github.com/tarachandverma/nginx-openidc/blob/master/test-conf/oidc-config.xml#L12
<!-- relying parties configuration -->
<relyingParties default="282412598309-545pvmsh9r23f4k1o7267744s59sod6v.apps.googleusercontent.com">
<relyingParty clientID="282412598309-545pvmsh9r23f4k1o7267744s59sod6v.apps.googleusercontent.com" clientSecret="xxxxx" domain=".com" validateNonce="true">
<description>nginx oidc demo</description>
<redirectUri>http://ngx-oidc-demo.com/oauth2/callback</redirectUri>
</relyingParty>
</relyingParties>
Use https://github.com/auth0/nginx-jwt, for me it was easier to install Openresty, since I didn't have that much time to install manually lua module on nginx, and all it's dependencies.
At https://github.com/auth0/nginx-jwt/blob/master/nginx-jwt.lua at the line 114 the library adds the sub to the header which should be an Id, you may change this if you need anything alse.
ngx.header["X-Auth-UserId"] = jwt_obj.payload.sub

How to Check Proxy

I have a Web app calling a Web Service by IP with the following code:
ws.Proxy = System.Net.HttpWebRequest.DefaultWebProxy;
ws.Credentials = System.Net.CredentialCache.DefaultCredentials;
ws.Proxy.Credentials = System.Net.CredentialCache.DefaultCredentials;
I believe this uses the IE proxy settings. I'm trying to troubleshoot a separate issue and want to confirm the default proxy details being used.
How do I do that?
I tried making sense of this:
How to AutoDetect/Use IE proxy settings in .net HttpWebRequest
I failed to get the proxy uri back using Scotty's link in the comments or this one:
https://msdn.microsoft.com/en-us/library/vs/alm/system.net.iwebproxy.getproxy(v=vs.110)
So had to use another approach to troubleshoot my app. Not an answer, just closing this out.

Grails - SSL and Spring security core

I would like to have my application running exclusively with SSL turned on.
I am using the Spring Security core plugin.
This is how I attempt to do it in Config.groovy:
grails.plugins.springsecurity.portMapper.httpPort = 8080
grails.plugins.springsecurity.portMapper.httpsPort = 8443
grails.plugins.springsecurity.secureChannel.definition = [ '/**' : 'REQUIRES_SECURE_CHANNEL']
I was expecting this to cause redirects every time I would try to access a Url using HTTP.
However, I am never redirected, and can navigate through both HTTP and HTTPS. I may add I am starting my application using grails run-app -https
Am I getting this all wrong ?
Any suggestion is most welcome.
Do you have a custom filterchain declared in your config?
you might need to add 'channelProcessingFilter' to your chain in that case
http://static.springsource.org/spring-security/site/docs/3.0.x/reference/security-filter-chain.html
You can also try using the forceHttps option
grails.plugins.springsecurity.auth.forceHttps = true
You don't have any wildcards, so the definition is literally matching the root URL (/), but nothing below it (/foo). What you want is:
grails.plugins.springsecurity.secureChannel.definition = [ '/**' : 'REQUIRES_SECURE_CHANNEL']
^^
(You can clearly see the wildcards in the documentation :-)
Finally, if your server is behind a load balancer or other firewall that hides the protocol, check that same page for instructions on checking the header.

Resources