How secure is using the applicationScope in an anonymous XPages application? - xpages

In a XPages application, I want to store some (confidental) information in the applicationScope to make it accessible for all users. However, the ACL of the application is configured such that anonymous users are allowed to read public documents. Still, I do not want them to have access to the applicationScope. Is it possible for an anonymous user to access/read the applicationScope?

All the scope variables (including applicationScope) are memory contexts. The term "scope", in this case, refers to how broadly each can be accessed.
requestScope can be accessed by any code executing within the current page for the duration of a single HTTP request, at which point the object is destroyed. Any other pages, and any subsequent requests against the same page instance, have their own separate requestScope.
viewScope can be accessed by any code executing within the current page for the life of that page instance. Other pages -- including those accessed by the same user -- have their own viewScope. Similarly, if the user navigates to another page, and then navigates back to the previous page, that's a new viewScope because it's a new instance of the page.
sessionScope can be accessed by any code executing within any page during a single HTTP session. This is tied to session cookies in the browser, not to authentication. So if an anonymous user later logs in, it's still the same sessionScope. If they later log out, they still have the same sessionScope until they close their browser or the application clears out the storage.
applicationScope can be accessed by any code executing within any page within the current application. This is what allows it to be shared across users: If User1 is accessing app1.nsf/page1.xsp on one computer while User2 is accessing the same page -- or a different page -- within the same NSF, they have the same applicationScope -- the variable refers to precisely the same in-memory object for both users -- so any data stored via code executed by one user can be retrieved via code executed by another user until the application clears out the storage.
BUT, if User1 is accessing any page in app1.nsf and User2 (or Anonymous) is accessing any page in app2.nsf, the variable applicationScope refers to different in-memory objects for each user, because they are accessing different applications, even if there is code in either app that accesses on-disk data in the other app. The in-memory object that the applicationScope variable refers to is different in each NSF, no matter where any on-disk data it may access or create happens to be stored.
So you (and anyone else writing code in the same NSF) still need to be diligent about how you structure your logic to avoid storing sensitive information in applicationScope and then exposing it to users who shouldn't have access to it, but you don't need to worry about code executed from other applications accessing the same memory scope. Code can only read the data you store in your applicationScope if that code is executed from the same NSF.

A user can only read values from applicationScope and other scoped variables if you expose the value through visible controls on an XPage. So if you do not expose the values, then a user (anonymous or not) can not see the value.

Related

Login session transferred to other user

I have kind of a strange problem. I have build a web application in Lucee. You need to login to use web application. It has happened, at least twice, that a login session has been transferred to an other user. To clarify what happen:
User 1 is logged in the application, the session is active
User 2 goes to the web application and is automatically logged in and sees "welcome to the application user 1".
As mentioned above this has happened at least twice since the application is live, so it sounds like an incident. Security wise this is a big problem because user 1 is an administrator and user 2 has a basic access profile.
My question: does anyone recognize this issue and can someone give my some advice how to troubleshoot this problem.
Thanks
If you are using session variables, this could happen with data being assigned to the incorrect scope in a CFC or with objects being stored incorrectly in the application scope or even a mash-up of both.
Make sure that your CFC functions are using the function local scope:
var x = "" or local.x = ""
otherwise, x will be in the variables scope of the CFC, where it can be manipulated by any function inside the CFC. This leads to data bleeding from one call to another across sessions. Try using varscoper to scan your code for these issues.
Alternately, you could store an object that contains data for a user into the application scope or inside another object which is stored in the application scope. This could allow User A to access data meant for User B when they are logged in at the same time.
You need to do an audit of your code base for issues like this and go through your user session logic to verify where and how data is stored and accessed.
Like one of the comments suggested could be the users were on the same network and/or they used a proxy such as squid which would cache all incoming content. To check to see if it's a possibility take a look at the headers being sent out by your server and see if there are any headers related to caching (Cache-Control, Expires, Last-Modified, ETag).
if you want to prevent caching you could set the first example header in you application.cfc onRequestStart or to at least prevent user content being cached you could do some variation of the second example.
<cfscript>
//EX 1
header name="cache-control" value="no-cache"; //no caching by anything
//EX 2
if(loggedIn){
header name="cache-control" value="private, max-age=<time_in_seconds>"; //allow browser to cache content
}else{
header name="cache-control" value="public, max-age=<time_in_seconds>"; //allow anything to cache content
}
</cfscript>

How does out-proc azure redis session get feature work?

Scenario:
We are using azure redis session provider. When page first loads, retrieves the data from external API and stores them in redish session.
The same session data is retrieved via different pages and components with in user session. The question is:
Does application gets the session data only once and stores locally http current context? Or everytime it goes to redis store?
What if we are encrypting the data on set and decrypt the data on Get operations?
Thanks.
Application gets the session-data from Redis everytime you ask for it... for the writing part, you'll have to wait until the dictionary key is unlocked. See https://msdn.microsoft.com/en-us/library/aa479041.aspx#aspnetsessionstate_topic3 assuming you are using asp.net for this
A page claims write access to the session state by setting the EnableSessionState attribute on the #Page directive to true. (This is the default setting.) A page, though, can also have read-only permissions on the session state, for example, when the EnableSessionState attribute is set to ReadOnly. In this case, the module will hold a reader lock on the session until the request for that page finishes. As a result, concurrent readings can occur.
If a page request sets a reader lock, other concurrently processed requests in the same session cannot update the session state but are at least allowed to read. This means that when a session read-only request is being served, awaiting read-only requests are given higher priority than requests needing a full access. If a page request sets a writer lock on the session state, all other pages are blocked, regardless of whether they have to read or write. For example, if two frames attempt to write to Session, one of them has to wait until the other finishes.
StackExchange.Redis is just a wrapper (or a abstraction) for the HttpSessionState Module

Xpages: Determining if user can access a database

I have a navigation bar at the top of my Xpages applications. This element is going to be shared among many Xpage apps - it will work kind of like a intranet for our Xpage apps.
I do not want to display databases links to users who do not have access to the database.
How do I determine if a user can access a db? And is this something that I should somehow cache, so it doesn't have to be loaded again and again:
You can use the Database method queryAccess(name) to get the ACL level for the individual user. You can then check for No Access and for Depositor. Here's an example that returns true if the user has access to db:
db.queryAccess(userName) != ACL.LEVEL_NOACCESS && db.queryAccess(userName) != ACL.LEVEL_DEPOSITOR
I will suggest that you cache this in a user bean for the user.
Per's suggestion is great but be aware of one limitation on queryaccess:
From the documentation:
If the name you specify is listed explicitly in the ACL, queryAccess returns the access level for that ACL entry and does not check the groups.
If the name you specify is not listed explicitly in the ACL, queryAccess checks if the name is a member of a group in the primary Address Book known to the computer on which the script is running. On a local workstation, that address book is the Personal Address Book. On a server, that address book is the Domino® Directory. If queryAccess finds the name in one or more groups, it returns the highest access level among those groups. If the name you specify is not listed in the ACL either individually or as part of a group, queryAccess returns the default access level for the ACL.
First of all - if code runs under user's privileges, you can't call queryAccess for database you can't open. To work around this you could force the code to use signer's session and get the access. But...
I recommend this: make a bean named hasAccess. About the scope:
application scope is shared among users - useless
session scope - quite fine, but in case of ACL change
you would need to restart http or wait for session timeout
view scope is recommended
request scope wont help much
Implement map interface, so you can bind it like #{hasAccess[database]} where database will be filepath, or some special key to lookup database. Implement cache and return true/false, according to user's access. How do you determine user's access is up to you, but I think the best method is to use try/catch with attempt to open that database and check it with isOpen().

Should objects stored in the sessionScope be thread-safe?

If I'm informed correctly, every request for/from a XPage is processed in a new thread in the JVM on the Domino server.
Hence, all objects stored in the applicationScope which might be modified concurrently by different users should be thread-safe. However, all the articles about thread safety I have read so far never say anything about the necessity of using thread-safe objects in the sessionScope.
A user could, for example, run the same XPage (which modifies a sessionScope object) in two different browser tabs at the same time.
In my opinion, that sessionScope object has to be thread-safe too, or did I get something wrong?
In general, whenever there is more than one thread trying to access the same object and at least one of them tries to modify the state of the object it needs to be threadsafe.
So in this case if two browser tabs try to access same xpage or different xpages but trying to access the same session scope object and at least one of them trying to modify that object, we need to ensure it is threadsafe.
As #Tiny commented regarding the view scoped beans, "According to the JSF specification, AJAX requests made from the same view are queued on the client side. Therefore, the possibility of concurrent access in a view scoped bean is zero. A view scoped bean is not shared across different tabs / windows of the same browser".
Refer to Section 13.3.2 of jsf 2.0 specification.

XPages: what is the lifetime of an application scope variable?

A. What is the actual lifetime of an application scope variable in xpages?
B. how can i remove/reset it if necessary?
(I can't find anything like "re-deploy" or "start-stop application", so do i have to restart the webserver,do it with code, just re-save my application from designer or anything else...?)
A. It varies. You can set an explicit timeout in the XSP Properties (surfaced in Designer 9 as a design element under the Application Configuration category; in 8.5.x you'll need to navigate to WebContent/WEB-INF/xsp.properties via Package Explorer). Otherwise, it times out when Domino thinks it "should". This is based on application usage, so the more heavily the app is used, the less likely the scope will ever expire unless the HTTP task -- or Domino itself -- is restarted.
B. To destroy the entire scope, restart HTTP (or restart Domino entirely). NOTE: this is not
Tell HTTP Restart
...which only reloads certain portions of the task, and does not reload the JVM. You need to actually restart the task:
Tell HTTP Quit
Load HTTP
OR
Restart Task HTTP
After the task restarts, a fresh application scope will be instantiated the next time the application is accessed.
You can also selectively clean the scope. Each of the scopes in XPages (request / view / session / application) is an instance of a Java Map, so each supports all of the methods defined in that interface.
I would recommend only removing specific items, e.g.:
applicationScope.remove("myBean");
If you clear the entire scope without actually destroying the scope itself (see above), it can cause unpredictable behavior, because the platform also stores its own information in the application scope (this applies to the other scopes as well). You should only remove scope entries that you added.
As the Name application scope variable already tells you its lifetime is as long as the application is running if defined in the xsp.properties if you defined nothing the standard duration is 30 minutes. or Or from IBM:
The applicationScope duration is the WebModule duration. A web module is started when the first request comes in, and is eventually discarded after a period of inactivity, the default being 30 minutes. Every user of the application can access these variables once they are created, so there is no privacy with these variables. The applicationScope should only be used for data that must be shared among many XPages.
If you develope using application scope vars you can reset them by clearing your Application in designer go to: Projekt => clear...
or if this does not help try following code from Tommy Valand:
function clearMap( map:Map ){
// Get iterator for the keys
var iterator = map.keySet().iterator();
// Remove all items
while( iterator.hasNext() ){
map.remove( iterator.next() );
}
}
This will allow you to reset the application scope durring runtime, verry usefull for debugging and testing.
I believe that refreshing the design also clears application scope variables....

Resources