Security: Session Identifier Not Updated in tcl - session

I'm working on open-source application "Project-Open" and during the scanning I got the following vulnerability:
[Medium] Session Identifier Not Updated
Issue: 13800882
Severity: Medium
URL: https://<server_name>/register/
Risk(s): It is possible to steal or manipulate customer session and cookies, which might be used to impersonate a legitimate user,allowing the hacker to view or alter user records, and to perform transactions as that user
Fix: Do not accept externally created session identifiers
though the fix is mentioned but it is not sufficient for me to understand it completely.please guide me how should I remove this.Also let me know if any further details are needed to understand the question.
The project source code is in tcl
I found the following code which does the same but it's in java.
public HttpSession changeSessionIdentifier(HttpServletRequest request) throws AuthenticationException {
// get the current session
HttpSession oldSession = request.getSession();
// make a copy of the session content
Map<String,Object> temp = new ConcurrentHashMap<String,Object>();
Enumeration e = oldSession.getAttributeNames();
while (e != null && e.hasMoreElements()) {
String name = (String) e.nextElement();
Object value = oldSession.getAttribute(name);
temp.put(name, value);
}
// kill the old session and create a new one
oldSession.invalidate();
HttpSession newSession = request.getSession();
User user = ESAPI.authenticator().getCurrentUser();
user.addSession( newSession );
user.removeSession( oldSession );
// copy back the session content
for (Map.Entry<String, Object> stringObjectEntry : temp.entrySet()){
newSession.setAttribute(stringObjectEntry.getKey(), stringObjectEntry.getValue());
}
return newSession;
}
P.S. I'm newbie in TCL.
please let me know if you need any further explanation.

There is a fix in OpenACS 5.9 that addresses your scanning reports. Please see the following discussion on OpenACS.org for reference.
http://www.openacs.org/forums/message-view?message_id=5332821

The problem that the OWASP report is talking about is the inability to migrate a session to use a new ID, making it easier for an attacker to discover the ID and reuse it. The protection against this is to change the session ID from time to time (no, I don't know how often!) and that Java code is involved in doing just that.
A session is represented as a token stored in the browser, usually in a cookie (and this is what cookies are designed to do). That token is then used to look up the database record corresponding to the session, which holds serializations of the key/value mappings in the session. It's a simple mechanism, but very powerful. The Java code for doing all this will be fairly complex behind the scenes because of the serialization, etc., but Tcl values are (usually, and always for built-in types) naturally serializable and so should prove much less of a problem in this; copying a session to a new key could be done without having to deserialize in the first place.
The exact code for doing this depends on the framework in use. I don't know what ]project-open[ uses, so that's as far as we can drill right now. You need to talk to other people actually working on PO…
For all that, the best way would be to make the key given to clients not be the primary key, so that you can change the session key without having to delete things. Just have a session key column (with an index!) and you'll be able to make things work fine. This is a more sophisticated approach though; it might not be practical to implement in your environment..

Related

Session Fixation - Change sessionId on asp.net core 2

Based on what i have understood we have
sessionId is stored in the cookie .AspNetCore.Session
Deleting the cookies and Clearing the session does nothing.
context.HttpContext.Session.Clear();
foreach (var cookie in context.HttpContext.Request.Cookies.Keys)
{
context.HttpContext.Response.Cookies.Delete(cookie);
}
So the question is can we change the sessionId somehow, or is there a way to protect us from Session-Fixing?
...or is there a way to protect us from Session-Fixing?
Yes there is! OWASP states:
Unfortunately, some platforms, notably Microsoft ASP, do not generate new values for sessionid cookies, but rather just associate the existing value with a new session. This guarantees that almost all ASP apps will be vulnerable to session fixation, unless they have taken specific measures to protect against it.
The same page recommends an approach for ASP.Net, which we used for all of our ASP.Net applications and which passed pen testing. I think it is still valid for ASP.Net Core:
The idea is that, since ASP prohibits write access to the ASPSESSIONIDxxxxx cookie, and will not allow us to change it in any way, we have to use an additional cookie that we do have control over to detect any tampering. So, we set a cookie in the user’s browser to a random value, and set a session variable to the same value. If the session variable and the cookie value ever don’t match, then we have a potential fixation attack, and should invalidate the session, and force the user to log on again.
This is a simplified example of how we approached this in .Net Core Razor Pages and should give you an idea of how to implement it yourself:
public IActionResult OnPost()
{
Login();
return Redirect("~/Login");
}
private void Login()
{
// Check the user's credentials and do all the other necessary stuff.
// ...
// Create the random value we will use to secure the session.
string authId = GenerateAuthId();
// Store the value in both our Session and a Cookie.
HttpContext.Session.SetString("AuthId", authId);
CookieOptions options = new CookieOptions()
{
Path = "/",
HttpOnly = true,
Secure = true,
SameSite = Strict
};
Response.Cookies.Append("AuthCookie", authId, options);
}
private string GenerateAuthId()
{
using(RandomNumberGenerator rng = new RNGCryptoServiceProvider())
{
byte[] tokenData = new byte[32];
rng.GetBytes(tokenData);
return Convert.ToBase64String(tokenData);
}
}
Check the content of the Session and Cookie wherever you need it. If they don't match, you should Clear the Session (I don't think Session.Abandon is still available in .Net Core) and log out the user.
public void OnGet()
{
string cookieValue = Request.Cookies["AuthCookie"];
string sessionValue = HttpContext.Session.GetString("AuthId");
if (cookieValue == null || sessionValue == null || cookieValue != sessionValue )
{
// Invalidate the session and log out the current user.
}
}
Session.Clear only removes all data from the session, it does not actually remove the session itself. That will occur when the timeout is hit. It was an odd choice, in my opinion, for the ASP.NET Core team to not have implemented Session.Abandon, as previously existed, since that actually would remove the actual session, itself.
As long as the actual session still exists, even if the data for it no longer does, it can still be retrieved by that session id, as a result, the problem shifts to the client-side.
Importantly, the server cannot actually make the client do anything. Calling Cookies.Delete really only sends a new Set-Cookie response header for the same cookie with an expiration date in the past. This should prompt the client (browser, most likely) to then remove that cookie, since it is now expired. However, that is totally 100% on the client, so if there's a bug or the client otherwise is not picking up the change or the client simply refuses to comply for whatever reason, the cookie will remain. Then, again, if the cookie still exists and the session identified by the session id it contains still exists, it can be restored.
Long and short, the code you have should work, and there's really not anything else you can do other than what you're already doing. If the session isn't being abandoned, there's some other issue somewhere (most likely with the client).

How to migrate a cached ServiceStack session to a new "version"

When we add new properties to our custom AuthUserSession based session DTO, we either need to invalidate users active sessions and force them to re-login, or migrate their sessions (either in mass, or in lazy fashion). If this is not done, expected properties will not be filled, and adds a lot more complexity to the code relying on those properties.
I dug around and looked for any events around hydration of sessions from cache, but didn't see any easy place to tie in and determine if the session should be refreshed.
Any suggestions on where to plug in such logic in the flow where it will always happen before some session object is used by a ServiceStack Service or Razor view?
For Caching providers that implement ICacheClientExtended you can access all Sessions with:
var sessionPattern = IdUtils.CreateUrn<IAuthSession>(""); //= urn:iauthsession:
var sessionKeys = Cache.GetKeysStartingWith(sessionPattern).ToList();
var allSessions = Cache.GetAll<IAuthSession>(sessionKeys);
Otherwise I've just added a custom hook to be able to filter a session (in this commit), by overriding OnSessionFilter() in your AppHost, e.g:
public override IAuthSession OnSessionFilter(IAuthSession session, string id)
{
return base.OnSessionFilter(session, id);
}
This change is available from v4.0.49 that's now available from MyGet.

How can I get a user with a given facebook id using cloud code?

My app requires facebook login, so it is supposed I have all facebook ids from my users. What I want to o in cloud code is a function that given a facebook id (a string), returns the user (or null if no exists). The problem I see is that it seems the facebook id is inside a json structure in the authData column, but I have no idea how to create a query to access to that information. I found this: https://www.parse.com/questions/how-to-get-the-facebook-id-of-an-pfuser-from-a-pfquery-in-ios but no idea about how to use it.
Can you help me with the function I want to create? Thanks in advance.
My comment on Eric's answer expresses my concerns around security, but the cloud-code BeforeSave() function to address my concerns really isn't difficult... for simple use-cases:
Parse.Cloud.beforeSave("MyObject", function(request, response) {
request.object.set("owner_facebook_id", request.user.get("authData").facebook.id);
response.success();
});
In your case, MyObject is the user class, and as long as no users can modify properties on another user object, than this will work pretty well.
However, for the app I was working on, we allowed any user to "like" an object, which incremented a "number_of_likes" property on the object. At that point, this became more tricky, because the user making that request was not, in fact, the owner of the object, so their Facebook_id properties wouldn't have matched.
The work-around was to try and detect whether or not the object had previously existed, and then just make sure the Facebook_id never changed after it was originally created.
We had to access the ORIGINAL object and make sure the newly-saving object had the same Facebook id... it was not exactly trivial, and that lookup actually counts against your request limit. This, combined with a few more edge-cases, caused us to ultimately abandon Parse for that project.
The problem with using authData is that you need a valid active session of that user (or use your master key) to access the data.
If you don't already have a large amount of users, I would recommend creating a new column in your User class that stores the Facebook ID so you can query for it later. That way, you could do something like:
var query = new Parse.Query("User");
query.equalTo("facebookId", request.params.facebookId);
query.find({
success: function(results) {
// do something with the resulting user at results[0], if found
},
error: function() {
response.error("lookup failed");
}
});

Manage multiple calls of Membership.GetUser().ProviderUserKey;

I was thinking yesterday how to solve this issue, because everything what i give or check about user is depended of his ProviderUserKey (ID).
So i made one static function like
public static Guid GetUserID()
{
string UserID = string.Empty;
if(HttpContext.Current.Session["UserID"] != null)
{
UserID = HttpContext.Current.Session["UserID"].ToString();
}
if(!string.IsNullOrEmpty(UserID))
{
return new Guid(UserID);
}
UserID = Membership.GetUser().ProviderUserKey.ToString();
HttpContext.Current.Session["UserID"] = UserID;
return new Guid(UserID);
}
Main point of this class is to reduce database connections to check/get user ID.
My problem with this function is not that this is not working, my problem is what if logged user log out and log with another account?
Or Is it better to add session value on log in and clear session value on log out?
Where you can see any other problem with this kind of "Get User ID"?
If you log the user out then you should also be killing the session.
When you login as another user you would also have the session reinitialized.
Note you'll want to keep the session and forms auth timeouts (assuming you are using forms auth) in sync with each other:
How can I handle forms authentication timeout exceptions in ASP.NET?
This should help keep the session in line with the forms auth token. You'll in turn need to kill the session on logout and intialize it upon login.
Another alternative is to implememt your own membership provider that caches this key to prevent constant db hits.
have you tried using the ProfileProvider?
you can use and customize with special properties and that's is managed by session each user.
example to get values:
HttpContext.Profile.GetPropertyValue["CustomProperty"]
In this video you can lean to implement it, create, configure and use...
http://www.asp.net/web-forms/videos/how-do-i/how-do-i-create-a-custom-profile-provider

Static Properties with Session in ASP.NET

There are several posts about this online but none seem to provide a definitive answer. My question is this. If I have static properties declared that solely get/set Session values is that thread safe or will it potentially cause problems? In my app I have added static properties to my Global.asax to serve as a sort of central entry point for accessing certain values, for example I store the current client like this:
public static string CurrentClient {
get {
return HttpContext.Current.Session[Constants.SESSION_CURRENT_CLIENT] as string;
}
set {
HttpContext.Current.Session[Constants.SESSION_CURRENT_CLIENT] = value;
}
}
Note how I am not setting any static variables in my get/set, I am merely referencing the current session.
The application is setup so that it is installed as a single webapp in IIS but it will service multiple different 'instances'. Basically depending on what subdomain you come in on, it will then set all these Session variables as required. So for example:
client1.mydomain.com will set:
Global.CurrentClient = "client1";
client2.mydomain.com will set:
Global.CurrentClient = "client2";
This seems like it should work fine and be thread safe and the two subdomains will not trip over one another because they should each have unique sessions but that's exactly what seems to be happening. I get requests to client1.mydomain.com using CurrentClient="client2" for some reason.
What's going on here gang?
You seem to have a bad case of static-phobia. You shouldn't listen to people who spread FUD just because they don't understand what they're doing.
Static properties are essentially static methods. They do not store any state by themselves. Auto-properties are of course an exception, but you don't seem to be using them.
As long as you access any shared state in your static properties in a thread-safe manner, you won't have any problems.
What comes to your sessions getting "mixed up", are you sure the session cookie is being set at the correct level? If you set it at the mydomain.com level, it's going to be shared across all the subdomains. Also, are you sure it's even necessary to store this stuff in the session? Wouldn't it be the easiest to just compare the current domain with your list of clients on every request?

Resources