Session State Using Client IP - java

I am attempting to determine if there is a security flaw using the proposed method of maintaining session state when the client has cookies blocked.
Normally I store a UUID in the clients cookies and auto login if the UUID matches whats stored in the database. However, if the client has cookies blocked, I can't access a UUID on their machine and therefore have to resolve to using their IP address and match against the database that way.
I determine the IP address using:
String ip = request.getHeader("X-FORWARDED-FOR");
if(ip == null) {
ip = request.getRemoteAddr();
}
I'm a little green in this area, but I think there might be a security flaw in this approach. For instance, if the user accesses the application on a public wifi network (in a coffee shop, airport, hotel... whatever) it will store the public ip and match their account to that ip. Anyone coming in behind them on that same ip will have complete access to their account unless they specifically remember to log out. How do I prevent this? I'm not totally against using another approach when cookies are blocked besides matching to the ip. I'm just not sure what other approach their might be besides just totally disallowing user logins when cookies are not available. Is this the only truly secure method?
UPDATE
Based on T.J. Crowders comment, recent stats show that 2% of users actual have cookies blocked. I chose to rely on cookies for a number of reasons and show a warning when session state cannot be managed due to cookies being blocked.

...but I think there might be a security flaw in this approach. For instance, if the user accesses the application on a public wifi network (in a coffee shop, airport, hotel... whatever)...
Not just that. People who have wireless broadband in their home will all seem to be from the same IP, so if two people who live together both want to use your site simultaneously (maybe one recommended it to the other), they'll conflict.
If you can't use cookies, you could use the old J2EE technique of putting the session ID in every URL. If you're already using J2EE, you can use its built-in support for this (HttpServletResponse#encodeURL and such), which will use ;jsessionid=token on the URL. If you aren't, it's simple enough to implement the technique using a query string parameter.

The servlet API allows tracking sessions without cookies, using URL-rewriting (every URL pointing to the app in a given session will contain the session ID). This is automatic if you respect a few rules:
always use HttpServletResponse.encodeRedirectURL() when redirecting
always use HttpServletResponse.encodeURL() when generating a URL (for a link, image or whatever)
Note that the JSTL's <c:url> calls encodeURL() for you.

Related

WebAuthn : how to register an authenticator several time

I'm using Yubico demo to implement a webauthn server : https://developers.yubico.com/WebAuthn/WebAuthn_Walk-Through.html
I have implemented the CredentialRepository class to replace In Memory with access to a database.
Currently I am facing a problem:
I want to be able to use this server so that a client can connect with a Yubikey (or Andorid phone) to several websites. I would like the customer to register his key for each site. The problem is that the Yubico server does not want us to register the same key several times on the server while keeping the same username.
Would there be a way around this problem by making the registration of a key depend on the origin of the site where the key must be registered and not on the username?
(I don't want to replace the username with a different value for comprehension issues in the database)
All ideas are welcome.
Thank you.
What is preventing you from enrolling an authenticator multiple times for the same account lies within the PublicKeyCreationOptions that is being sent by the relying party. Within the PublicKeyCreationOptions is a field, excludeCredentials (line 22 in the screenshot link below).
PublicKeyCreationOptions Example
If you attempt to register a credential that has a credential ID that matches any of the items in the list, then the WebAuthn ceremony will not complete the request.
Why is this being done?
Users not familiar with how WebAuthn works may not realize that they only need to register an authenticator once, and that they can use that same authenticator across multiple devices. A confused user may attempt to register a security key on multiple devices, and may create the perception of a more cumbersome user experience. This is why we utilize the excludeList in our general guidance.
Here is some background as to how this list is being built.
How is the server creating this list?
When the relying party is built, you pass in the userStorage which allows the rp object to talk to your database where you're storing the credentials. When you begin your registration request, you pass in the userID when you are building the PublicKeyCredentialCreationOptions object needed by the RegistrationRequest object. If you observe the rp.startRegistration method you will see that the excludeList is built by searching userStorage for every credential that matches the userID of the user who made the request.
It's worth mentioning that the our example is typically acting as a relying party for a single origin/application, while yours is handling multiple.
With that context you have a few options
Here are some recommendations:
Provide guidance to your users noting that they can use the same
account/authenticator to enter into your multiple websites. This will only be applicable if your relying party is acting as a single origin authentication service, then routing the user back to the website they are coming from; example, Users in website1.com, website2.com and website3.com are all routed to my-relyingparty.com, authenticated, and routed back to their original site
As noted the java-webauthn-server is looking for registrations by username. You will first need to leverage multiple rp objects as they contain a reference to a specific origin (each registration you create with this rp object will correspond to the identity/origin you set). You can either create multiple instances of the java-webauthn-server for each origin, or create logic in your single instance to 1) Create multiple rp objects for each origin and 2) dynamically choose the rp object to use based on the origin of the users request. You could choose to leverage the same credential repository across multiple server instances or rp by overloading the startRegistrations method to search by both userID and rp ID/origin - While this is technically possible, it'll be a fair amount of rework.
Opt not to send existing credentials in the excludeCredentials list,
but this may be confusing to some users
Hope this helps
Thank you #CodySalas for your interesting answer.
This is what I did before you gave me an answer: I made the client send me back the origin of the client for the startRegistration and startAuthentication steps.
I added a trackedOrigin variable in InMemoryRegistrationStorage and I set trackedOrigin with userStorage.setTrackedOrigin(origin) for the two steps.
So when the Relying Party wants to search for excluded credentials (excludeCredentials) with "getCredentialIdsForUsername()" it will check the trackedOrigin to be able to make a request in the database according to the origin. Username is therefore no longer a uniqueness constraint since excludeCredentials will only have the credentials of keys with the same username AND the same origin.
Now that I saw your answer, I think reconsidered the solution I found because I discovered that the RP ID must be exactly the same as the domain of the client while the sites that will use the webauthn server will not have at all the same domain... Which is problematic but that's another question.
I'll probably open another question for that.

How do I get unique incoming request IP address

There are four people who are sharing a same wifi connection,
according to below definition there IP must be unique.
An IP address is a numerical label assigned to each device participating in a computer network that uses the Internet Protocol for communication.
Q1. IS IT SO OR NOT?
For uniquely identifying them I tried:
request.remoteAddress
But I get same IP for those all four person.
Q2.HOW UNIQUELY IDENTIFY THEM?(should I say them to pass some token like thing to identify them uniquely? but I will prefer unique IP)
The correct phrasing is that they all 4 are behinds a NAT firewall -- that is;
They all have unique IP addresses on their internal network (like 192.168.x.x or other internal IP address) see http://en.wikipedia.org/wiki/Private_network and RFC1918 for details.
They are connecting to the public internet though a firewall/gateway which does network address translation (see http://en.wikipedia.org/wiki/Network_address_translation for details).
This is the common way for most home/office networks to connect to the internet, for two reasons -- it require much fewer public internet addresses, and it also makes the network more secure as avoiding public addresses for internal resources means that there is less likelyhood for that you fail to configure you firewalls correctly.
The downside is that IP addresses are by no means a unique ID for the users -- that is what Cookies are for.
It may be that these 4 persons are connected from the same network. In this case the ip address will be seen as the same ip address for the external networks.
Requests sent from a router to a server outside that local network will all have the same IP address. This is one reason session ids are useful. If you need an identifier that MUST be unique for each user even if they are underneath the same local network you will need to use session variables.
Consider looking at this post
Where is session.id in Play 2.0?
Essentially create your unique ID. (Code taken from referenced SO post)
// Generate a unique id
String uuid=session("uuid");
if(uuid==null) {
uuid=java.util.UUID.randomUUID().toString();
session("uuid", uuid);
}
All the 4 users are accessing using the same internet line. Thus the Public IPAddress of all of them will be same. If you have a native application, then on first request that you make to your server, send the device ID with the request. Device ID combined with IP Address should be fairly unique, unless the device ID on all the devices are same (very rare). Another solution can be that you generate a unique Id (JSessionID when session is created on server can be used) on the first request to the server and send it in response. Then pass the unique Id on all subsequent request.
If you are using web browser of the mobile, then you can create session (JsessionId cookie will be generated by server). Mobile browser will take care of sending the jsessionid cookie with each request.
I am afraid there is no easy way to identify users since they can always modify the data they send you. That is why almost all the web services require log in (their own system or Facebook, Google, etc.). The problem, however, is, if someone registers enough accounts they can keep requesting you all the time. To avoid this problem, you may want to introduce Captcha verification every so often even after registration.
Also, not every user has static IP meaning they can change IP every time they get blocked (if you do block by IP, if I understand the question correctly).
They all have unique IP addresses on their internal network (like 192.168.x.x or other internal IP address) see http://en.wikipedia.org/wiki/Private_network and RFC1918 for details.
They are connecting to the public internet though a firewall/gateway which does network address translation (see http://en.wikipedia.org/wiki/Network_address_translation for details).

Is a Servlet "secure" if it checks for a given session attribute in the request handler?

Assume I have a single servlet in a web app, and all users need to be logged in before they can do anything. So in the get and post methods there is an if block to test if the user is logged by trying to extract a session attribute in to process request, and else to redirect to login page if not logged in.
Given this scenario, is there a way an intruder can manipulate the system to gain entry without knowing the password? Assume the password is hard-coded into the servlet. If yes, where would he start?
I would look at http://docs.oracle.com/javaee/5/tutorial/doc/bncbe.html#bncbj and the section linked from that section about specifying authentication mechanisms.
See also (on Stackoverflow) Looking for a simple, secure session design with servlets and JSP and How do servlets work? Instantiation, sessions, shared variables and multithreading
In short, you don't need to do much yourself about checking for a session attribute if you use the mechanisms described on those pages. Your login form can be used in the 'form-login' configuration requiring authentication.
The key of security is around your comment extract a session attribute -- how are you doing this? Are they sending you a query string param? Are they sending you credentials in the method headers?
To #Hogan's point, unless this is over HTTPS the answer is: "No, it is not secure. A man-in-the-middle (MITM) can get the password from your submission and simply re-use it to mask its own nefarious requests".
If the communication IS done over HTTPS, then you should be fine. Having a single hard-coded password is fine, but consider the case where the password gets compromised; now every single client/user/etc. has to change their code.
A better design is to issue clients a key they can send along with their requests that you can use to identify who they are and if a key gets compromise, re-issue a new one to that user/client/etc.
This assumes traffic is over HTTPS
If traffic is not, a lot of this breaks down and you need to look at things like HMAC's. I wrote this article on designing secure APIs -- it should give you a good introduction to how all this nightmare of security works.
If your eyes are rolling into the back of your head and you are thinking "My god, I just wanted a YES/NO", then my recommendation is:
Require all traffic to be over HTTPS
Issue individual passwords to each client so if one gets compromised, every single one isn't compromised.
That should get you pretty far down the road.
Hope that help. This topic is super hairy and I know you didn't want a history lesson and just want to solve this question and move forward. Hope I gave you enough to do that.

Generating Dynamic URLs

I have a list of users across various companies who are using one of the functionality that our website provides. Whenever they contact our business group , we need to send a url via email to the requestor in order for them to upload some data. All these external users do not have any dedicated account. However we do not want a static link to be provided to them as this can be accessed by anyone over the internet. We want dynamic links to be generated. Is this something that is usually done? Is there an industry accepted way of doing this? Should we ensure that the dynamic link expires after a certain amount of time - if so , are there any design options?
Thanks a lot!
Usually, parameters to urls and not the actual urls are what's dynamic. Basically you generate params that are stored somewhere, typically on the database, and send email with the url and the parameter(s). This url is valid for only a limited period of time and possibly only for one request.
Answers to questions:
yes, this is something that is quite commonly used in, for example, unsubscribing from a mailing list or validating an account with a working email address
I'm not aware of any single way that is "industry accepted", there are many ways of doing it, but the idea is not that complex - you just need to decide on a suitable token format
normally you should ensure that the link expires after a certain amount of time. Depending on the use case that can be some days, a week or something else. In practice, you'd remove or disable the generated parameters in your database. However, if this data is something that might be needed for extended periods of time, you might want to think up a functionality so that it can be retrieved later on.
You may have a static URL taking a token as parameter. Eg. http://www.mycompany.com/exchange/<UUID> or http://www.mycompany.com/exchange?token=<UUID>.
The UUID could have a validity in a time range or be limited to a single use (one access or one upload).
Other variant is to use exists cookies on that site in web browser (of course, if they are).
But there are some drawbacks in this solution:
User can open link in different machine, different browser. User can clean all cookies or they can expire after it was visited your site last time when user try to go on granted URL. In these cases user won't access your page.

Identifying user by browser agent details?

I understand that this kind of identification cannot be 100% accurate, but example usage would be internet poll, to detect users that have already voted. Is user detection possible with browser sent details? And what kind of information I can get from browser with every request? If I add IP address or location for example town to this, then identification would be more accurate. Are there any possible downsides I should know about?
You may want to check out the research the EFF has conducted, to identify visitors using default browser-transported information - but no cookies.
Here's the link for Panopticlick.
You should not rely on such information.
As I'm sure you are aware all of this information can be easily forged. As you can specify any request header at will (the request header contains IP, location, browser etc.).
You can use it as a poll, but you should keep in mind that the poll will never be 100% accurate.
If you want to know where the user is from make him authenticate in the site with a valid e-mail and set a cookie on his browser.
Another way to check a user's identity/location is using a paid identity validation service like URU for instance. Even this however is never 100% accurate.
ip + location is not a good thing. Much of internet users are behind firewalls/NAT's/proxy's.
Your best best is long term persistent cookie.

Categories

Resources