Secure URL parameters when an application delegates the user (concept) - security

Context
We have an application A that guides our customer consultants throught a workflow based process. Part of this process has been outsourced to a own webapplication - lets call it application B.
Wenn calling application B the certificate of the current user is used for the HTTPs connection (since it just delegates the HTTP GET to a new browser window).
Application A has the required data to autorize users to perform certain actions while application B expects the autorization to be done once a URL is called.
Application A must as well deliver certain data such as IDs to enable application B to know for example what customer is beeing processed.
Requirements
That application B can expect the autorization to have been done it must be ensured that only application A was the source of the call and the user has not changed the parameters of the URL (which he can as it is his certificate that is used for the HTTPS connection).
What have we done
We thought of building a hash over the parameters, encrypt it with the private key of application A and submit it as additional parameter with any request. Application B uses the public key of application A to decrypt the hash, build a hash over the received parameter and check that parameters have not been changed.
My Question
What would be other possibilities to ensure the source of the call was application A and the parameters have not been changed by the user?
(If not clear please leave a comment i am currently painting some grafics and can overwork the question).
Regards
JBA

So A signs the parameters for B, which is a step in the right direction.
A few more things to consider:
Replay attacks. A malicious user of B might observe a desired set of parameters signed by A. He can replay those anytime in the future, along with the valid signature from A, even if A did not intend to call B with those parameters anymore (say the authorization information changed). To mitigate this, a nonce or a timestamp should also be signed in the request and checked by B when validating the signature (the nonce should be checked for uniqueness, the timestamp for not being too old).
Participants (who's messaging whom). When A signs the message, the signed data should contain the intended recipient, so that an attacker cannot take a message from A to C, and send it to B. Of course if all of your components have a single instance, that's less of an issue, but still A should include something like the message is for B's url, and B should check that the url signed is actually the right one. Similarly, A should include the information that it was signed by A (his own url or IP address for example), and B should validate that the apparent and signed sender are the same.
Not creating a signing oracle. You should make sure that a user cannot use A as a signing oracle for making signatures. The less data a user of A can choose himself for A to sign, the better.
By the way (and apart from all of this), wouldn't it be simpler if B could just query A over some kind of an API request for all the information it needs? That way you wouldn't have to bother with all the relatively complex crypto stuff and would not have to pass sensitive info through the user.

Related

How to Verify Whether Request Headers were Added by a Specific Web Application

Currently I am working on a project which requires high security. Because of some recent requirement changes, we have added some special headers to each request using a front-end http intercepter(otherwise it would become a drastic change in front-end modules) and they are very critical for the system.
Recently we have observed that these headers can be modified using some browser plugins which is a critical issue. Hence I need a way to identify whether these headers contain the original values added from my front-end and they are not modified.
Exposure of these header values is not a big concern. But modification is.
.
.
My Solution:
1) Generate a RSA key pair each time module initializes and send the public key to a backend service with a unique id for that tab.
2) Keep the private key in a service in my front-end and create a public function to generate signature for a given input.
3) Each time the front-end intercepter is called, it will calculate a signature value based on the respective header values and append it as another header value.
4) When each request hit api gateway, it will verify the signature using the public key saved at the app initializing phase.
.
Are there concerned security risks for my above solution. If there is a better way of solving the above problem, suggestions are warmly welcomed :)
Consider using JWT for sending those headers... You may use symmetric signing (eg: HS256) or asymmetric signing (eg: RS256) depending on the whether you have ownership of both frontend and backend or front end is public...
For more details on creating JWT and Verifying it, please refer to https://jwt.io/
From the details, you had provided, this is the idea I got... For exact working, you have not provided whether it's web api or web application, etc.

How to implement expiring to the account activation link?

I am trying to implement expiring to the activation link I send to the user's email when they register a new account.
The link should expire after 24 hours if the user doesn't click on it.
Up until this point I am able to send the link to the user's email upon registration, the link looks like this 'http://localhost:3000/auth/activate/${verificationKey}', everything works smoothly.
But like I said, I want the link to expires after 24 hours and I just don't have any idea of how to do it.
From what I've gathered so far I think one way to do this would be to delete the verificationKey value from my User entity/model after 24 hours, then if the verificationKey value is falsy I need to send another link to the user.
Now my question is, how do I check if a value (in this case user.verification_key) has been generated for over 24 hours?
This is the relevant code to register a new user:
const user = new User();
user.username = username;
user.password = await bcrypt.hash(password, salt);
user.is_verified = false;
user.verification_key = cryptoRandomString({
length: 10,
type: 'url-safe',
});
Some people have suggested to use Redis for this, which I don't know anything about other than it's a in-memory store, and while I'm ok reading more about this tool, I would like to know if there are other ways to do this. I don't know if by installing Redis I would need extra configuration for the server when I host my app, I'd like to avoid that.
Since you already have some database set up, it makes sense to store some verification key and an expiration time for it. You don't need to actually delete that verification key... just need to store when it expires.
Perhaps you have a separate model for RegVerificationKey, with fields key (randomly generated string), expiration (set to a date/time 24 hours after you create it), and userId (the ID of the user this is associated with). Create this key. When you go to activate, just check to see if there is a key associated with the requested user that hasn't expired yet.
Some people have suggested to use Redis for this
No need here, you already have a database you can put data in.
I would like to know if there are other ways to do this
There's an alternative, where you cryptographically sign your URL. Basically, you would store the key and its expiration data in the URL itself, and include some calculated proof that you (the person with the private key) created this URL. When your system receives this URL, it can verify the URL was signed correctly without even having to consult a database. This method can be complicated and probably isn't useful in your case. I'm just mentioning it here as an alternative. Check out JWT for one possible implementation: https://jwt.io/
Recently I was needed to implement this kind of implementation in my web application. So I just followed the below points to achieve it.
1- Create the URL (web link) and append the current date and time along with an encrypted key which you would store in the database as mentioned below.
2- Create a column in the database table (the table where you store any user specific details) to store a randomly generated key which you have encrypted and appended in the URL.
3- When you would receive this URL on server you would check the encrypted date and time in the URL and would decide whether it is still valid depends on your criteria of retaining a link (e.g. 24 hours)
4- Next you would decrypt that key in the URL that you have appended in it at the time of creating it and would match it with what you have stored in the table.
So by implementing above logic you could achieve the desired functionality.
Hope its useful for any one who wants similar type of implementation
I understood that you already found a solution, by storing two fields in the database: one for the key and another one for he expiration timestamp. Everything depends on the use cases and it is definately one way to do it. However I will explain Redis and JWT as a solution in comparison to yours.
Redis is an in-memory datastore (that also allows persistence to disk) as you pointed out and I think the reason why people suggested it is, that you can define an expiration time for a record. Redis will remove that record automatically for you then. Reference: https://redis.io/commands/expire
Redis would take the work off of your shoulders to check if the 24hrs already passed. If you can’t fetch the key anymore, the key probably expired. Another benefit of Redis is, that is super quick compared to your normal database query. But if you only need it for the activation link, which is a one-time-action for the user, the time benefit is negligible. Also you would introduce a new technology just for that use case.
#Brad already suggested using JWT (Json Web Token) instead of implementing your own token solution and I would also suggest that for the following reasons.
A JWT is a self-contained token consisting of three parts: Header, Payload, Signature. The header contains the name of the algorithm that was used to create the token. The paylod contains some standardized fields (e.g. creation date, expiration date, subject the token was issued for like username) and you can also add custom fields. The third part is a signature that ensures that no one changed the payload after it was issued by your token service.
Self-contained means that the token contains everything to validate it, including the expiration timestamp. In your case the expiration time is not part of your token but stored in the database. If you create another microservice that needs to verify your token, that service needs to contact your main service which contains the logic to check the expiration database field.
With JWT the Microservice would only need to know the secret key that was used to sign the token and then you can just import some standard JWT library to verify the token. These libraries validate the signature as well as the expiration timestamp which is an optional field in the payload of the token.
By the way, the payload can be read without knowing the secret key from the signature. So it is even possible to read the payload for example on client side to check the expiration time.
With your solution you have additional database calls, which are potentially slow. For an activation link that is acceptable, but for tokens with recurring use within a short timespan (i.e. API requests that require authentication) additional database calls should be avoided. Also you need to implement token generation and verification yourself, whereas JWT provides standard libraries. This is a benefit when you want to have another Microservice in Java instead of NestJS for example. You can quickly knit them together by using standard libs instead of porting your implemtation or being forced to decide for a centralized token verification service.
One limitation of JWT you have to workaround yourself, is the use case where you want to have a „one time token“. You can only define an expiration date but you can not say that a token can only be used x times. Here you need a centralized service again, which keeps track of how often a token was used (by making use of some datastore) and all other services around need to contact that service.
A good starting point for JWT with NestJS is the official NestJS documentation.

Nodejs: How do you differentiate between users?

I am new to backend. Only way i can think of is this:
at visit if doesn't have cookie then do next step
generate unique id and then set it as cookie
then upon every request check if that id is present in database and if not go to step 1.
if it's present then fetch data under that id and respond as needed.
Now is it safe?, Is it logical. What does actually happen.
Scenario to use in:
This is meant for not logged in users. Basically, users visit my site, click something that takes time.. so user is redirected to a page with waiting gif all the while using ajax (long polling) server is requested for results. Now to differentiate between requests from multiple users i am thinking this will work. It's important because data i'm going to be sending back is going to be private from 3rd party.
You have to decide up front if you want a:
Temporary session for a given browser that will only work for that user in one specific browser and may be reset at any time
or
A longer term session associated with a particular user that they user can use any time and from any browser.
The first can be done with a server or client generated cookie that is any globally unique value. You can then use that id as a key into your database to get the user's server-side settings/data on any given request. In node.js, there are a number of session related NPM modules that will handle the generation of a sessionID for you automatically. The problem with this first method is that it relies on the preservation of a cookie value in the user's browser. Not only can cookies be temporal (they can be cleared), but they are only set in one specific browser.
If you're only planning on using it for the duration of one session, then this first method should work just fine. It is common to use a time value (e.g. Date.now()) combined with a random number for a unique id. Since no two requests can be processed in the same ms, this guarantees a unique id value. Add the random number to make it not be predictable. Other NPM session modules offer further features such as an encryption key, etc...
The second method requires some sort of identifier that the user must enter in order to know which user it is (often an email address). If you don't want other people to be able to impersonate a user by only knowing their user id, then you also need to require a password. This essentially requires a sign-up process on your site where the user ends up with a userID and password that they use to login to your site.
It is not uncommon to see the first method used for short term storage on behalf of the user. For example, a shopping cart on a site that you are not registered for.
The second method is used by all the sites that have a user login.

Is this safe for client side code?

I'm writing a GWT application where users login and interact with their profile. I understand that each form entry needs to be validated on the server, however, I am unsure about potential security issues once the user has logged in.
Let me explain. My application (the relevant parts) works as follows:
1 - user enters email/pass
2 - this info is sent back to the server, a DB is queried, passwords are checked (which are salted and hashed)
3. if the passwords match the profile associated w/ the email, this is considered success
Now I am unsure whether or not it is safe to pass the profile ID back to the client, which would then be used to query the DB for information relevant to the user to be displayed on the profile page.
Is there a possibility for a potential user to manually provide this profile ID and load a profile that way? My concern is that somebody w/ bad intentions could, if they knew the format of the profile ID, load an arbitrary amount of information from my DB without providing credentials.
-Nick
What you are dealing with here is a session management issue. Ideally, you want a way to keep track of logged in users (using random values as the session key), know how long they have been idle, be able to extend sessions as the user is using the site, and expire sessions.
Simply passing the profile ID to the client, and relying on it to send it back for each request is not sufficient - you are correct with your concern.
You want to keep a list of sessions with expiration times in a database. Every time an action is executed that needs user permissions (which should be pretty much everything), check to see if the session is still valid, if it is, extend it by however long you want. If it is expired, kill the session completely and log the user out.
You can store your session keys in a cookie (you have to trust the client at some point), but make sure they are non-deterministic and have a very large keyspace so it cannot be brute forced to get a valid session.
Since you're logging a user in, you must be using a backend that supports sessions (PHP, .Net, JAVA, etc), as Stefan H. said. That means that you shouldn't keep any ids on your client side, since a simple id substitution might grant me full access to another user's account (depending on what functionality you expose on your client, of course).
Any server request to get sensitive info (or for any admin actions) for the logged in user should look something like getMyCreditCard(), setMyCreditCard(), etc (note that no unique ids are passed in).
Is there a possibility for a potential user to manually provide this profile ID and load a profile that way? My concern is that somebody w/ bad intentions could, if they knew the format of the profile ID, load an arbitrary amount of information from my DB without providing credentials.
Stefan H is correct that you can solve this via session management if your session keys are unguessable and unfixable.
Another way to solve it is to use crypto-primitives to prevent tampering with the ID.
For example, you can store a private key on your server and use it to sign the profile ID. On subsequent requests, your server can trust the profile ID if it passes the signature check.
Rule 1 - Avoid cooking up your own security solution and use existing tested approaches.
Rule 2 - If your server side is java then you should be thinking along the lines of jsessionid. Spring Security will give you a good starting point to manage session ids with additional security features. There will be similar existing frameworks across php too (i did not see server side language tags in the question).
Rule 3 - With GWT you come across javascript based security issues with Google Team documents and suggests XSRF and XSS security prevention steps. Reference - https://developers.google.com/web-toolkit/articles/security_for_gwt_applications

evaluating the security risk of exposing a row's identity in the querystring

Is it a security risk to expose the ID number of a SQL row?
For example, there is an event with an ID of 12.
Is it a security concern if someone accesses it via http://example.com/events/12, or someone makes a POST to http://example.com/events/12 in order to update that record (assuming I allow this of course)?
The problem of exposing ID's to users is often referred to as "insecure direct object references" in a web security context.
From OWASP:
Preventing insecure direct object references requires selecting an approach for protecting each user accessible object (e.g., object number, filename):
Use per user or session indirect object references. This prevents
attackers from directly targeting unauthorized resources. For
example, instead of using the resource’s database key, a drop down
list of six resources authorized for the current user could use the
numbers 1 to 6 to indicate which value the user selected. The
application has to map the per-user indirect reference back to the
actual database key on the server. OWASP’s ESAPI includes both
sequential and random access reference maps that developers can use
to eliminate direct object references.
Check access. Each use of a direct object reference from an
untrusted source must include an access control check to ensure the
user is authorized for the requested object.
A defense in depth approach would be to do both 1 & 2.
Whether to display or not, it doesn't matter.
What matters is that you check that the caller is authenticated and is authorized to perform the operation being requested.
Someone may have a bot spitting out requests to http://example/events/x where x is an incrementing number. Perhaps it's a snoopy employee trying to view http://payroll/employee/x.
Authenticate the user to ensure that they are who they say they are. Forms authentication, LDAP, what have you.
Ensure the user has authorization to perform each action when called. Usually the user belongs to a group that has permission to update the boss' salary, create a shipment, or cancel a credit card.
If you implement measures as above, the source of the id won't matter, whether it's on the cookie, hidden form element, querystring, session variable, etc.
URLs and querystrings are particularly insecure when you're using integer identifiers. After all, if there is a 12, there is almost certainly an 11 or a 10. GUIDs make it harder to guess another item, but still shouldn't be considered secure IMJO.
Bottom line: You need some sort of authentication mechanism to ensure that the user is who he claims to be, and authorization mechanism to ensure that he is allowed to see what you are about to show him.

Resources