Guids, QueryStrings and Authentication - c#

I have a number of locations in a number of applications I have built where a page accepts a QueryString in the following format: http://localhost/MySite.aspx?ID=ab1cbabe-42e2-4d15-ab11-17534b829381
These pages will then take the query string, attempt to parse it and display the data that matches the guid using a database call with strongly typed values.
Example:
Guid value;
if (Guid.TryParse(Request.QueryString["ID"], out value))
{
SomeControl.Datasource = DatabaseCall(value);
SomeControl.Databind();
}
What this obviously means is that any user (provided they have the guid for the data) can technically access any other users data. Obviously predicting guids is next to an impossibility but I'm still uneasy about it.
How does everyone else deal with this problem? Is there a "correct" way? Is it even worth worrying about?

In various circumstances it absolutely is worth worrying about.
People tend to post or email URIs without stripping away the query strings
Most browsers store the whole uri including the query string in a history
Most browsers even offer autocomplete in the address bar which lets you try through already visited resources
The http request can be intercepted pretty much anywhere on its way from client to server, exposing the query string
I'd recommend some kind of user-based authentication mechanism like asp.net's membership provider.
In case you already are using some authentication, linking resource guids to their respective user ids in an association table might do the trick.

You answered your own question: "Obviously predicting guids is next to an impossibility"
However, the proper way to implement user access, is to build and manage an ACL. You can't simply rely on a unique string for that, because even if users don't guess the string, an attacker can still sniff the traffic and reuse the GUIDs they found.

I agree with #Laurent.
But - it depends on your type of business. For extreme security-related contexts such as banking, money transactions, sensitive personal data etc., I would go to an encrypted cookie, or simple - a unique key that is passed in the query string (as you asked about), but not a guid but something far longer (just make sure it's randomness is fairly hard to predict), along with a background task on the server that invalidates "tokens" that are older than X minutes, to mitigate the risk of stealing URLs.
Consider resorting to some standard mechanism such as ASP.NET Membership.

Related

How to create a short readable UUID in a microservices distributed environment

I am working in breaking a super monolith web service into a microservices approach using CQRS and Event Sourcing. With that and considering previous architecture depending in SQL Server incremental identity numbers for each table it is unacceptable for a distributed system to rely in a database since we will now have various projections of the events in the system.
But we still have to keep relations and transfer ids around for analytics, API calls etc. The obvious option is GUID, and that looks fine until you come to the point of a GET request, http://awesomedomain.com/users/98e3b2ab-3c69-4077-aea1-38d22e79b007, hmm not that pretty and kind of cumbersome but it will work. It is also known that having GUID as index keys in a database can be a performance hit.
After looking some answers here to try and generate ids based on EPOCH UNIX timestamp ticks, shorten the GUID, or this interesting approach (but finding out not global solution), every solution will not really guarantee global uniqueness, except the short GUId one, but still not clear.
Another option would be to have a Guid Service with a distributed lock (Redis) to generate EPOCH UNIX tick id but that can give us a performance hit if you have thousands of concurrent "create" requests.
Should we really bother to shorten a GUID or find another solution that is more "human readable"?
Are there any other solutions for global unique identifiers that we could implement?
What you have is good.
It may not be humanly readable but that is exactly what it should be. Sequential IDs are easily guessable and bad for security. GUIDs fill this gap pretty good.
Depending on how your system is structured you can actually have int IDs as primary keys while keeping your GUIDs too and they don't have to be primary keys. This is however not always possible.
It is very important to measure and research this requirement first. You definitely don't want to implement complex, hardly maintainable logic for object creation just to be able to handle more requests than your system would ever have.
I personally would say that database auto-increment keys and microservices are not mutually exclusive. You can have lots of instances of a lightweight service, all working with single microservice-specific database behind it. Even though it can make the DB connection a bottleneck or single point of failure, it is still viable and many services in the Internet work fine this way. If you design the database correctly and keep it "micro", then it should work fine, at least for "thousands of create requests".
It also really depends on the data you are working with.
If you create users, then I think that using IDs or user-specified usernames is more natural, than GUIDs.
If you create a platform where people upload content, which is not related to each other, then you might want to look into how YouTube implemented ID generation for its videos - just random IDs encoded as base-something, shorter than GUID and more readable for human eye.
There are a couple of options you can pick from:
don't care
Why bother about the GUID. Nobody is going to see it. It's only used for service to service communication or technical api calls.
Downside: can look ugly.
use natural keys
Things can have ISO standards, like countries, or currencies. They are human readable in most cases. Some other things can have another natural identifier, like ships.
Some things don't. That's annoying. No downsides (beside speed of db calls), but not always available.
reformat ID locally
Some UI web part might store some super fast searchable entries in it's own search optimised database. Here you can have a local ID. But, this communicates badly with the other services.
Downside: integration complexity.
shorter guids
We can generate a random number can we? Better human readable. Nicer URLs. Cool.
Downsides: not much, just; no relation with actual entity. But, since you where using GUIDs you hadn't have it to begin with.
Of course I left some options out of the equation. Basically; all depends on your requirements. Speed, security, replication possibilities, etc. :-)
Enjoy!

ASP .NET Core: How to cache data which depend on user input?

We are building a new ASP.Net Core WebService which will provide data from existing Database.
To reduce to load on the database and improve response times I thought about caching certain objects and configurations from the database.
I found this for caching in ASP.Net Core: https://learn.microsoft.com/en-us/aspnet/core/performance/caching/memory?view=aspnetcore-2.2
What seems to be the way to go. The Article also says: Do not use external input as cache keys
My Problem now is that basically all data are depending on the user or a user input.
I am aware that caching makes only sense with objects that get often used but rarely changed.
Here an simplified example when I might want to use caching: We do have holiday / workday configuration which can by per state different. So it can vary depending on the user but 100s of users might use the same configuration.
Also there are some shared components which a lot of users share but which components are returned is depending on what is requested.
So what would be the best approach to cache such entities?
I am also open for any Idea that helps me reduce the calls to the database.
Thanks and best regards,
Marc
I think you're misunderstanding. The caution is against using external user input as cache keys. In other words, you should not take some input from the user and the set something in the cache via that:
_cache.SetString(userInput, "foo");
It's not talking about setting user input as the value, i.e.:
_cache.SetString("my cache key", userInput);
It's also not talking about segregating the cache by user:
_cache.SetString($"cache key for user {userId}", "foo");
Both of the latter scenarios are fine. It's just that allowing the user to set the key itself opens yourself up to things like potential SQL injection attacks, depending on your cache store.
Also, note that it's mostly talking about unsanitized user input. If it's something like an enum where the user can pick only from a set of defined values, then you're fine. Or, if you otherwise know that the input is not going to cause issues. For example, a zip code that you've validated only contains numbers and maybe a single dash. There's nothing a malicious user can do with that, so it's fine. However, a free form text field like "Name" would be problematic to say the least.
The documentation discourages external input as cache keys, because it might lead to too many cache entries and consume quite a lot of RAM, which will in turn have negative impact on the performance.
You need to experiment. Maybe you will not end up with too many different user input variations.
You can also consider an external caching service like Memcached, where you can use additional servers as cache. This will allow you to cache many more values and reduce your load on the db.

Will having a pseudo-incremental number for bug ID be a problem?

Note that when I say "client", I mean businesses or organizations that have signed up for the service.
I am creating a bug tracking application. I have decided to go with multi-tenant approach with respect to both the application instance and the database.
Hence, there is one huge bugs table with entries from all clients. The bug ID is an identity specification. Because of this, when any user under any client adds a bug, it gets incremented. For a client who has added just 3 tasks, the task IDs could be #45, #49, #53 because users from other clients may have added some in between!
Is this acceptable from a use-case point of view?
Sometimes clients may take the latest bug ID to be a rough measure of the number of bugs. But in fact it will be the TOTAL bugs in the system. Or they will be plain surprised if their first bug starts from #51134!
On the other hand, if I have this particular ID "behind the scenes", and calculate a "visible" ID for each client separately, they will see the numbers in order. But, when passing a reference bug ID as parameters in URLs I cannot use the user-visible ID because it is not unique. I don't think a ClientID - BugID combo will be elegant. I am afraid using the original identity specification value will cause confusion because the user will see one ID in the UI and another ID in the URL. And no need to say developers will try to use the URL by altering the ID and watch it fail.
How can I solve this issue? I do not want to go to a multi-database approach as I am kind of scared of the maintenance and upgrade process.
I think the principle of least surprise applies here: you need to be consistent with whatever you do. If you are unable to modify the URL scheme then that just leaves non-sequential ID's as the only viable solution. I don't personally see an issue with this, most bug trackers will be able to generate reports of how many bugs were reported in a given period, or how many on a specific project, etc.
On a slightly unrelated note, at work we use a single bug tracking system for all our projects. The system as a whole has a single incrementing ID for bugs in any project. We've never had an issue.
As a general rule of thumb don't show your surrogate keys (IDENTITY values) to your users if you can at all help it. Humans eventually want to change something that they know about so they need not know the primary key values...
The idea about generating a human-consumable identifier would solve your problem best, as you mention, just don't use it like a key in your system. Use your surrogate keys as the keys. (There are usually ways around passing keys in the url string...) Rather, treat your human consumable key as a display field after its initial generation.
Consider concatenating client name abbreviation or client company abbreviation or a portion of the date/time or other counter that you determine with a separate query against context (SELECT MAX(?) FROM q) or a combination these...
Good luck!
One special case I wanted to mention: if this is a public facing website, i.e. public support page or similar, where the customer gives you the support ticket number by phone (i.e. break of the communication medium) then it would be wise to construct an "intelligent" id. For example 5 numbers + checksum. Then the operator (or the system) can more easily check for misread ticket numbers.

Asp MVC 2: Obfusicate Entity-IDs

Project type: Asp MVC 2/NHibernate/C#
Problem
If you have an edit page in an web application you will come to the problem that you have to send and then receive the id of the entity you're editing, the IDs of sub-entities, entities that can be selected by dropdownmenus,...
As it is possible to modify a form-post, an evil user could try to send back another ID which maybe would grant him more rights (if i.e. that ID was related to a security entity).
My approach
Create a GUID and associate it with the ID
Save the association in the http session
Wait for the response and extract the real ID out of the received GUID.
Question:
What techniques do you use to obfusicate an entity-ID?
If you're doing that much for GUIDs, why not just use GUIDs for the identity of the entity itself that's actually stored in the database (though I'd advise against it)?
Or you could have a server side encryption scheme that encrypts and then subsequently decrypts the id (this is a long the same lines as what you're doing except you're not storing anything random like this in the session (yuck :) ).
You could even forget trying to do this at all since a lot of sites are "affected" by this issue, and it's obviously not a problem (StackOverflow for example). The overhead is just too much.
Also, if you're worried about security, why don't you have some sort of granular permissions set on the individual action/even entity level. This would solve some problems as well.
EDIT:
Another problem with your solution is inconsistent unique identifiers. If a user says "ID as23423he423fsda has 'invalid' data", how do you know which ID it belongs to if it's changing on every request (assuming you're going to change the id in the URL as well)? You'd be much better of with an encryption algorithm that always hashes to the same value therefore, you can easily perform a lookup (if you need it) and also the user has consistent identifiers.
Your controllers should be immune to modified POST data. Before displaying or modifying records belonging to a user, you should always check whether the records in question belong to the authenticated user.

Checking/Reading/Writing cookies in .NET, please help me understand

So I have never had to use cookies before but now I am making a Shopping Cart that they can keep coming back to and leaving but I want it to store what they added.
What I am wondering:
How do check if a cookie exists and then create or update it, is that the best way to think about using a cookie?
How exactly would I store the data, in particular I want to store a list of IDs like "5,6,7,8", should I just use one string for this or is there a faster/better way than reading/parsing/writing something like that? I mean I suppose I would just keep adding new_value + ',' to the end, is there an append for cookie variables?
Does the cookie have some unique identifier that I would use to be sure I don't write duplicates or something?
Note: It's easy to look up 'HOW' like for seeing the syntax but I'm really trying to grasp the 'BEST WAY' or most ideal, how it was meant to be used, or how all you programmers found is the most fruitful way to utilize them in this type of scenario.
The winning answer to this similar question suggests that you only store the user ID in the cookie. The rest goes in the database.
If you can consider other approaches besides cookies, many folks prefer using session over using cookies. For one thing, you don't always have a lot of room in a cookie.
Storing the shopping cart in a cookie means that you will have no record of what people were shopping for but didn't purchase.
OTOH, using the cookie is using the shoppers' storage space and preserving your own. That could be significant over time and a lot of shoppers.
I solved this in the past by creating a class to manage the cookies (e.g.CookieManager) with static methods I passed an HttpRequest object to.
I was trying to solve a very similar problem, so I created a Count cookie and then a cookie which stored the information I wanted to save (in your case an ID number). I only wanted to save the last 5 items a user viewed, so I would manage this in my CookieManager class, dequeuing the oldest cookie and queuing up latest. The Count cookie kept track of how many cookies I had. Obviously, this isn't very high tech or secure, but for this project that was completely unnecessary. Anything you want to be robust should be saved on a database, or elsewhere server-side.
I want to further explain why you only store a guid that maps to a userid in a cookie. There are two main reasons:
Performance. As slow as it may seem to pull data from a database, you have to remember that cookie data is not free. It has to be uploaded from the user's browser to your web server, and even high-speed broadband connections tend to have much slower upload speeds. By contrast, your database likely has a gigabit link (sometimes even faster) directly to the web server. So what you really want in your cookie for best performance is a guid that maps directly to the primary key of your database table.
Security. Data in cookies is stored in a plain text file on the user's computer. You never know where a user will access your site from; it could be a very public place that's not appropriate to keep such data.
So is there any data you can use cookies for directly? As it happens, there is. Cookies have the nice property of sticking with a particular machine and browser. These days a lot of people will access the web from more than one place. Perhaps a work computer, a home computer, a smart phone, a netbook... all of which may have different screen sizes and other peculiarities. So what you can do with a cookie is store information specific to that combination of user+location.

Categories

Resources