-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

John,

On 7/25/15 9:03 AM, John Baker wrote:
> Hello,
> 
>> Anything in particular? Plumbing code is always not terribly
>> pretty.
>> 
>> It's kept up-to-date and generally supports more features than 
>> mod_proxy_ajp.
> 
> Well, there was a point where 64bit windows builds didn't even work
> - which tells me there's not a lot of testing going on.

I'm not sure how long ago that was, but I don't live in the Windows
world. I would have thought that someone at Apache Lounge would have
balked if a release was broken. Were you building a release version,
or trunk?

> And having got involved and contributed a few years ago, I recall
> the code being somewhat in need of refurbishment, as does pretty
> much all 15+ year old C/Java/....

Last time I checked, C code pretty much compiled the same way it did
25 years ago. I don't see a particular need to go in there and change
a whole lot of stuff. Are there more efficient ways to dereference
pointers these days? Is all the new-fangled stuff compatible with APR
and httpd?

>>> I see your point regarding the ajp protocol but equally, HTTP
>>> is everywhere and if every other part of a web stack is HTTP,
>>> there seems little value in doing anything different between
>>> Apache & Tomcat.
>> 
>> There are some slight optimizations in comparison to AJP. When
>> HTTPS/2 (which is very much like AJP) hits, you'll see less of a
>> difference.
> 
> I don't think there's any good reason to use AJP over HTTP with
> respect to web performance. Pretty much any bottleneck exists in
> the application, or the plethora of components it uses, not the
> transport layer.

Agreed.

> AJP is merely obscuring a request that in many (commercially 
> deployed) solutions originated from a device with a number of
> other solutions in-between it and Apache/IIS, ie the F5, an Akami
> layer, BlueCothe protocol that one can't get away from; that
> everyone understands and can easily debug with telnet/etc)at, etc.

Nobody is making anyone use AJP. But it does offer a side-channel that
allows information like HTTPS client to come across in a way that
won't be confused with HTTP request headers. HTTP doesn't offer
anything like that, of course, so some other mechanism would have to
be invented. Probably some meta-information passed-through in HTTP
headers. It would work, but it would be a pain, and it would be more
difficult to hide those implementation details from the application.

>>> AJP has various load balancing features/etc and if that's what
>>> one wants, fine, but most organisations have hardware load
>>> balancers etc to do this for them now-a-days.
>> 
>> Also, mod_proxy_* does load-balancing. This is not a feature of
>> the protocol, but of the tool.
> 
> Yes, I appreciate that, but mod_proxy/mod_jk LB is not used in your
> day to day commercial solution that - rightly or wrongly -
> consider Apache/Tomcat as one (often, people don't even know the
> difference!) and do the load balancing in the corporate wide
> solution.

I'm not sure I agree with that, but it's largely irrelevant either way.

>>> Going back to my request, I note the Servlet Specification API 
>>> docs state that getRemoteUser should return the CGI variable 
>>> REMOTE_USER:
>>> 
>>> http://tomcat.apache.org/tomcat-7.0-doc/servletapi/javax/servlet/htt
p/
>>
>>> 
HttpServletRequest.html#getRemoteUser()
>>> 
>>> But as I've highlighted, it does not, so Tomcat is in breach
>>> of the spec. How can this be raised as a bug?
>> 
>> REMOTE_USER is not an HTTP header... it's the "REMOTE_USER" CGI 
>> variable
> 
> Yet they are used interchangeably.

Are they? I've never written a Perl script that expected to find
REMOTE_USER in the HTTP request headers, and I suspect nobody else
has, either.

> And we're not discussing mod_[fast]cgi, but a completely different 
> architecture/solution.

Right, and so the rules are a bit muddy.

>> So, your proposed implementation is incorrect and represents a
>> security vulnerability.
> 
> It does not represent a security vulnerability.

Sure it does: a client can supply a forged REMOTE_USER header quite
easily.

> Any application that trusts a user via REMOTE_USER, whether via
> the HTTP or AJP connector is doing so knowingly. And in such a
> case, a pen-test would fail unless there were extra measures in
> place (Tomcat's AJP or HTTP connector listening on localhost;
> restricted access to the host), but they are no substitute for
> authenticating within Tomcat.

So, how is Tomcat supposed to know that the request has been
properly-sanitized? At least with AJP, one expects that a nearby web
server is making the request and that the user knows what they are
doing. Nobody sets up a one-box-wonder in production with the AJP port
publicly available. But people do that all the time with port 80
available publicly.

> Apache authenticating on behalf of Tomcat is a bad decision, but a 
> decision still forced upon some because of vendors not providing
> Java authentication solutions out of the box (ie CA SiteMinder, RSA
> Access Manger, Tivoli, etc). If the vendor pushes and only actively
> supports an Apache front end, one has to use an Apache front end.
> 
> Setting up mod_proxy_http is easier than mod_[proxy_]jk. Everyone 
> understands HTTP, and I'd like Tomcat to more easily integrate
> with Apache (and the various authentication modules) using HTTP.

Okay, so what does the metaprotocol over HTTP look like? You just want
to take an HTTP header confusingly called REMOTE_USER and use that as
your user principal? No problem: write a Valve that does that and
insert it into your Valve chain. Problem solved. Should Tomcat support
this directly? Well, it does so for the AJP connector as you point out
(albeit using a different technique... specifically, it doesn't use
HTTP headers), so perhaps it's appropriate to extend that support to
the HTTP connectors.

Care to file a Bugzilla enhancement for that?

I don't like your proposed implementation, but that doesn't mean that
it could work similar to the way you've described it. For one thing,
it should be a configuration option that is off *by default*.

>> Tomcat is compliant insofar as there is no standard that covers
>> where the REMOTE_USER CGI variable should be set or what its
>> value should be. When a user is logged-into a web application, 
>> request.getRemoteUser returns the name of the
>> currently-logged-in user. When no user is logged-in, it returns
>> null. That seems to be compliant to me.
> 
> Well, admitting there's no standard and then stating is compliant
> is an interesting conclusion :)

What I'm saying is that Tomcat is compliant with the Java Servlet spec
which only refers to CGI environment variables. Since those don't
really exist, the references to those are more informational than
normative. HttpServletRequest.getRemoteUser should return what you'd
normally expect to be in the REMOTE_USER CGI environment variable.
Since Tomcat does its own authentication, there is no such variable,
but the semantics are pretty much what most people would expect:
calling that gets you the username of the currently logged-in user.

As far as Tomcat is concerned, there is no currently logged-in user in
your case, so it's behaving consistently with the specification.

>> How do you want it to behave instead?
> 
> It should be consistent with the AJP Interface. Either they both
> return a user on getRemoteUser() or they don't. The
> tomcatAuthentication flag on the AJP connector tells Tomcat to
> trust the REMOTE_USER header/CGI variable/whatever we wish to call
> it. With a simple change to the HTTP connector, it can do the same.
> Rename REMOTE_USER to X_UNTRUSTED_USER if you wish, but this no
> more or no less secure than the AJP connector because one has to
> 'opt in' to the security issue.

I would agree that the "tomcatAuthentication" setting should be
supported on other connectors, but you'll also have to make sure that
the client (e.g. mod_proxy_http) either natively knows how to proxy
those values over the connection or use something like mod_headers to
do it. What I'm trying to say is that this isn't merely a failing of
Tomcat's connectors: you'll have to do some work on the httpd side
already, because "REMOTE_USER" is not, as far as I know, automatically
sent via mod_proxy_http to the origin server as an HTTP header. You'll
have to make that happen yourself.

> I would also like to see Tomcat reporting the obvious security hole
> when this approach is used (for either AJP or HTTP) by reporting to
> the logs if the connector is not bound to localhost/etc. I'm amazed
> at how often I find Apache+Tomcat deployed with zero security on
> the AJP connector and no-one appearing to understand the issue.

Just "localhost"? What about "127.0.0.1"? "::"? Aliases of "::"?
192.168.x.y? 10.x.y.z? 172.x.y.z? How many things should be
white-listed, or should you be required to set not only the
"tomcatAuthentication" flag but also the "shutUpIKnowWhatImDoing" flag?

>> If you want to have the web server report the REMOTE_USER CGI
>> variable to Tomcat, you'll have to arrange that for yourself.
> 
> And indeed it's not hard to do so, but if one wants to get rid of
> AJP and stick with pure HTTP, then a Tomcat Valve is required to
> set the Principal when REMOTE_USER is passed as an HTTP header from
> Apache. It's an extra level of effort that people can do without.

Fair enough.

> So in summary:
> 
> * There's no security issue with my proposal above and beyond what
> is already considered an issue with AJP.

One caveat: (a) if the web server is not configured correctly, this is
a security vulnerability and (b) if Tomcat is publicly-reachable, then
this is a security vulnerability. (Note that the same is true with a
publicly-accessible AJP port).

> * Tomcat should provide much more informative reporting when
> security issues are opened up through the use of AJP and 
> tomcatAuthentication="false".

Well, the use of AJP should be irrelevant, if the connectors are to
have feature-parity.

> * If we really don't like the idea of getRemoteUser() returning 
> REMOTE_USER (set as an HTTP Header or provided by mod_jk) then
> maybe a Valve can be included by default that wraps up both the
> logging and functionality (I'm happy to write it).

I think this might be more easily coded at a higher level, though a
Valve in the meantime would suffice.

- -chris
-----BEGIN PGP SIGNATURE-----
Comment: GPGTools - http://gpgtools.org

iQIcBAEBCAAGBQJVtqGgAAoJEBzwKT+lPKRYLfoP/iw2V1XCUeUKIngZ4lBsIFuc
8dOq3avRfKAaY+pf8aXVEDMramsqwrn9QDLFhBzhAhj4kj1uSMXKZHa4xbF1Cqgl
F0/pI+/xNbYUw0mTounetMFR7xOkjjsOUwUmSiY0bExVdLTvmWRSO8ECwe+0dDr5
cjuwUKZj1MI31VWe9YlZqAcRnlulGrk4FwW1rPXKWU31OyKuFLCYrCWt76LSO674
5MUFX7/LimP6V+rQHUIQ3wsUh8rxUti333tl9h0Qk1hPtaMOXC5h/s+eEHTKC+bw
ZE1i41sQPTSkzbrgO+URWWIpOEDEOvNFgjdTlOYtspe6NN0OeHHN4NYK0dlaJ9kb
cpQP5IKt0ZhcP+jCd7gS5+eN0l8WlYPCBHXhoOKWG8hwTq/XIKxLkp3LXOG8Dkba
mksAnrm07OZynevmi6LKJL1j3r5ksIBw4/pI7UurzBiomo+iRTiMD8BjDYqpgEu2
cTFjoB4Dsb5zV8Ls3/XmwlXoLHsHw9+QmUz/sLJkzlS3pdMNORUMALRYKcFzvyLd
F3qfXplips4fUYIIK+4k+xnCLapSZPQv6Ee5h5mBUXwmmFwlmszjckE7t3ZjWegN
g1isZAtjuw23vnXrNT/8x00x7UM0umBWqFpzj0IQhMF2SCt6q5eed6jjQUNjY5MT
V5D9gqOTUU1clqr8Gj83
=9cBj
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org

Reply via email to