I have an Apache/2.2.15 web server with the modules, mod_shib, mod_ssl, and mod_jk. I have a virtual host which is configured (attached below) with AuthType Shibboleth, SSLCertificates, and JKMount to direct requests using AJP to my Tomcat 8 server after a session is successfully established with the correct IDP. When my http request reaches my app server, I can see the various Shib-* headers, along with the attributes my SP requested from the IDP.
Is there a way my app server can validate the shibsession cookie or other headers? I am trying to protect against the scenario where my web server, which resides in the DMZ is somehow compromised, and an attacker makes requests to my app server, which resides in an internal zone.
Is there a way I can validate a signature of something available in the headers, to guarantee that the contents did indeed originate from the IDP, and were not manufactured by an attacker who took control of my web server?
Is there something in the OpenSAML library I could use to achieve this?
Is there a way my app server can validate the shibsession cookie or other headers?
mod_shib has already done that difficult work for you. After validating the return of information from the Identity Provider (IdP), mod_shib then sets environment variables (cannot be set by the client) for your application to read and trust. Implementing OpenSAML in your application is unnecessary as mod_shib has done the validation work for you.
From the docs:
The safest mechanism, and the default for servers that allow for it,
is the use of environment variables. The term is somewhat generic
because environment variables don't necessarily always imply the
actual process environment in the traditional sense, since there's
often no separate process. It really refers to a set of controlled
data elements that the web server supplies to applications and that
cannot be manipulated in any way from outside the web server.
Specifically, the client has no say in them.
Related
I'm new on the world of load balancing...
I heard about HAProxy and I wonder if I can achieve this objective (not found yet over searches already done):
HAProxy receive a MQTT/HTTP connection with basic authentication
(login-password) or token based
HAProxy checks credentials from a Database (or
LDAP)
HAProxy manage the access depending on the authenticated User.
--> all of user/credential and ACL should be stored in Database.
Is this possible? Is there in HAProxy a system of custom plugin/add-on to enhance its behavior ?
I found things about settings list of ACL directly in the configuration with already existing list of login/password (but not dynamically even if cached after)
Thanks a lot for your ideas.
I think this is only supported in Enterprise Haproxy:
The HAProxy Single Sign-On solution [...] is also compatible with Microsoft Active Directory or OpenLDAP servers.
https://www.haproxy.com/documentation/hapee/1-8r1/security/using-sso/
The only plugin I found is a http request check to see if user is authenticated on an arbitrary endpoint:
https://github.com/TimWolla/haproxy-auth-request
But it requires a specialized web app responding the requests for that.
In the interest of avoiding yak-shaving, I'll try to provide as much context as possible.
We have an internal application that's also available on the public internet. This application runs on several instances of Apache on the IBM i - most of these instances require http basic authentication, except for one instance that acts as the 'welcome page' so to speak. This 'welcome page' has no authentication, but acts as a navigation hub with links for the user to go to other parts of the app (which DO have authentication and run on different instances of Apache).
We also have some documentation stored in Confluence (a wiki application) that runs on a separate server. This wiki application can display the documentation without requiring authentication, but if you authenticate, you then have the option to edit the documentation (assuming you're authorized to do so, of course). But the key is that the documentation is visible without requiring authentication.
My problem is: we want the documentation in Confluence to be accessible from within the main application (both when being accessed internally and over the internet) but, because the documentation is somewhat sensitive, we don't want it accessible to the internet at large.
The solution we came up with was to use a reverse proxy - we configure the Apache instances on the main application such that requests to /help/ on the main application are proxied to the confluence application. Thus, the Confluence application is not directly exposed to the Internet.
But this is where the problem starts.
If we just proxy /help/ through the main application Apache instance that doesn't require authentication, then the documentation is available from the main application without a problem - but since you don't require authentication, it's available to everyone on the Internet as well - so that's a no-go.
if we instead proxy '/help/' through the main application Apache instances that DO require authentication, it seems as though the basic authentication information is passed from the main application servers onto the Confluence server, and then we get an authentication failure, because not everyone who uses the main application has an account on the Confluence server. (For those that do, it works fine - but the majority of users won't have a Confluence account).
(Possible yak shaving alert from this point forward)
So, it seems as though when dealing with HTTP Basic authentication, if you set up proxy configuration from server A to server B, and set up the proxy on server A to require http basic authentication, then that authentication information is passed straight through to the server B, and in this scenario, server B complains since it doesn't expect authentication information.
My solution to that problem was to set up 2 levels of proxying - use the Apache instances requiring authentication to also require authentication for the proxy to /help/, but have /help/ proxy to a different server (Server C). This Server C doesn't require authentication but is not exposed to the internet. And Server C is configured to proxy /help/ to the actual Confluence server.
I did this on the basis of proxy-chain-auth - an environment variable which seems to indicate that by default, if you have a proxy chain, the authentication information is NOT automatically sent along the chain.
Alas, this did not work - i got an authentication error that seems to indicate that Server C did in fact proxy the authentication info onwards, even though i did not set proxy-chain-auth.
So, that's my yak-shaving journey.
I simply want to set up a configuration such that our documentation stored on Confluence requires some sort of authentication, but that authentication comes from the main application, not from Confluence.
(Without the requirement of having it accessible over the internet, none of this would've been an issue since the Confluence server can be viewed by anyone on its network without a problem).
I hope my question is clear enough - I honestly don't mind being pointed in a different direction to achieve the main goal, with the caveat that I can't change the main application (or Confluence for that matter) from using HTTP Basic Authentication.
Ideas, anyone?
PS. To retrieve the documentation from the Confluence server, I'm actually using their REST API to retrieve the page content - i don't know if that has any relevance, but I just wanted that made clear in case it does.
It turns out that the solution to the issue was pretty straightforward.
For my second proxy that does not require authentication, I had to change the Apache configuration to remove any authorization headers.
RequestHeader unset Authorization
This stops the authentication information from being passed from the second proxy onto Confluence.
More of a theoretical question, but I'm really curious!
I have a two part application:
Apache server hosting my UI
Back-end that services all http requests from the UI
The apache service proxies all http requests from the UI to the server. So, if the user is reasonably adept, they can reverse engineer our API by inspecting the calls in the browser's developer tools.
Thus, how do I prevent a user from using the server API directly and instead force them to use the UI?
The server can't determine whether a call came from the UI or not because a user can make a call to myapp.com/apache-proxy/blah/blah/blah from outside of the UI, apache will get the request and forward it to the server, which will have no idea it's not coming from a UI.
The option I see is to inject a header into the request from the UI, that indicates the origin of the request as the UI. This seems ripe for exploitation though.
To me, this is more of a networking question since its something I'd resolve at the network level. If you run your backend application in a private network (or on a public network with firewall rules) you can configure the backend host to only accept communication from your Apache server.
That way the end-user can't connect directly to the API, since its not accessible to the public. Only the allowed Apache server will be able to communicate with the backend API. That way the Apache server acts as an intermediary between the end-user (client side) and the backend API server.
An example diagram from AWS.
You could make the backend server require connections to be authenticated before accepting any requests from them. Then make it so only the Apache server can successfully authenticate in a way that end users cannot replicate. For example, by using SSL/TLS between Apache and the backend, where the backend requires client certificates to be used, and then issue Apache a private certificate that the backend will accept. Then end users will not be able to authenticate with the backend directly.
Anyone know how a web server (apache, tomcat) maintains sessions ?
I know how to create / handle and destroy sessions. What I need to know is how server maintains sessions internally.
i.e if 10 users are connected to the server, how the server identifies which session belongs to a particular user
Strictly speaking, your webserver (Apache) doesn't have a concept for "session"; it merely understands requests according to the HTTP protocol.
In fact, HTTP is famous for being a "stateless protocol" - there is no concept of "session". This is fundamental to the scalability of HTTP, but makes it hard to build web applications that need state.
So different web application frameworks have introduced the concept of "session".
Tomcat is not strictly speaking a web server, it's a servlet container.
Sessions are usually identified by a cookie with a unique ID for each user. The ID is generated and sent as a cookie when the session is first created (i.e. when the user doesn't already have a cookie).
Another way that's sometimes seen is keeping the session ID in the URL, which is used when the client refuses to accept cookies for some reason. This has numerous drawbacks though, such as security issues if the user pastes their URL to another user, having to add the ID to all links, and ugly URLs.
I am creating a secure web based API that uses HTTPS; however, if I allow the users to configure it (include sending password) using a query string will this also be secure or should I force it to be done via a POST?
Yes, it is. But using GET for sensitive data is a bad idea for several reasons:
Mostly HTTP referrer leakage (an external image in the target page might leak the password[1])
Password will be stored in server logs (which is obviously bad)
History caches in browsers
Therefore, even though Querystring is secured it's not recommended to transfer sensitive data over querystring.
[1] Although I need to note that RFC states that browser should not send referrers from HTTPS to HTTP. But that doesn't mean a bad 3rd party browser toolbar or an external image/flash from an HTTPS site won't leak it.
From a "sniff the network packet" point of view a GET request is safe, as the browser will first establish the secure connection and then send the request containing the GET parameters. But GET url's will be stored in the users browser history / autocomplete, which is not a good place to store e.g. password data in. Of course this only applies if you take the broader "Webservice" definition that might access the service from a browser, if you access it only from your custom application this should not be a problem.
So using post at least for password dialogs should be preferred. Also as pointed out in the link littlegeek posted a GET URL is more likely to be written to your server logs.
Yes, your query strings will be encrypted.
The reason behind is that query strings are part of the HTTP protocol which is an application layer protocol, while the security (SSL/TLS) part comes from the transport layer. The SSL connection is established first and then the query parameters (which belong to the HTTP protocol) are sent to the server.
When establishing an SSL connection, your client will perform the following steps in order. Suppose you're trying to log in to a site named example.com and want to send your credentials using query parameters. Your complete URL may look like the following:
https://example.com/login?username=alice&password=12345)
Your client (e.g., browser/mobile app) will first resolve your domain name example.com to an IP address (124.21.12.31) using a DNS request. When querying that information, only domain specific information is used, i.e., only example.com will be used.
Now, your client will try to connect to the server with the IP address 124.21.12.31 and will attempt to connect to port 443 (SSL service port not the default HTTP port 80).
Now, the server at example.com will send its certificates to your client.
Your client will verify the certificates and start exchanging a shared secret key for your session.
After successfully establishing a secure connection, only then will your query parameters be sent via the secure connection.
Therefore, you won't expose sensitive data. However, sending your credentials over an HTTPS session using this method is not the best way. You should go for a different approach.
Yes. The entire text of an HTTPS session is secured by SSL. That includes the query and the headers. In that respect, a POST and a GET would be exactly the same.
As to the security of your method, there's no real way to say without proper inspection.
SSL first connects to the host, so the host name and port number are transferred as clear text. When the host responds and the challenge succeeds, the client will encrypt the HTTP request with the actual URL (i.e. anything after the third slash) and and send it to the server.
There are several ways to break this security.
It is possible to configure a proxy to act as a "man in the middle". Basically, the browser sends the request to connect to the real server to the proxy. If the proxy is configured this way, it will connect via SSL to the real server but the browser will still talk to the proxy. So if an attacker can gain access of the proxy, he can see all the data that flows through it in clear text.
Your requests will also be visible in the browser history. Users might be tempted to bookmark the site. Some users have bookmark sync tools installed, so the password could end up on deli.ci.us or some other place.
Lastly, someone might have hacked your computer and installed a keyboard logger or a screen scraper (and a lot of Trojan Horse type viruses do). Since the password is visible directly on the screen (as opposed to "*" in a password dialog), this is another security hole.
Conclusion: When it comes to security, always rely on the beaten path. There is just too much that you don't know, won't think of and which will break your neck.
Yes, as long as no one is looking over your shoulder at the monitor.
I don't agree with the statement about [...] HTTP referrer leakage (an external image in the target page might leak the password) in Slough's response.
The HTTP 1.1 RFC explicitly states:
Clients SHOULD NOT include a Referer
header field in a (non-secure) HTTP
request if the referring page was
transferred with a secure protocol.
Anyway, server logs and browser history are more than sufficient reasons not to put sensitive data in the query string.
Yes, from the moment on you establish a HTTPS connection everyting is secure. The query string (GET) as the POST is sent over SSL.
You can send password as MD5 hash param with some salt added. Compare it on the server side for auth.