I'm making an API call from one app to another. I handle authorization by passing an md5ed shared secret + timestamp...
$token = md5( $secret . time() );
Then at the API endpoint, I check the authenticity of the request like this...
if ( md5($shared_secret . time() ) == $token )
...do stuff
This works. But it isn't as reliable as I'd like. I suspect the reason is due to latency in the network (or my slow localhost server) causing the timestamps to be mismatched by a second or so.
I worked around this in a lazy way by dropping the last digit of the timestamp, thus creating up to a 10 second window for my slowpoke server to make the call. However, I'm not satisfied with this because if the call happens to fall at the very end of the 9th second, I'll have the same problem again (send at #######49 != received at ########50).
There must be a better way to do this. What is it?
Consider using token = time || MAC(time, shared_secret) where || is concatenation and MAC is a Message Authentication Algorithm such as HMAC, that takes a secret key and some data and produces an authentication tag. On the server end, check the MAC is valid and the time (received in plaintext) is within an acceptable window.
This is more secure than your current solution (md5 makes a poor MAC) and also solves your window problem.
Note that this scheme is susceptible to replay attacks within the error window that you allow (e.g. the same token could be sent ten times in a one second window, and the server has no way of telling).
Use a nonce instead? Save the nonce to a DB or some persistent storage to make sure the same one isn't used.
Conversely to your '9th second problem' you have a similar problem for seconds ###...0 to ###...9 hashing to the same value when you cut off the trailing 0 through 9. It would allow replay in that 10 second time frame.
Seems like that would be more of a problem for guaranteeing/checking authenticity.
You'd have to send the plaintext and hashed text together for the server to check it but that seems a little better than the time stamp method.
Either way, with those two parameters alone you're only checking that it's not a duplicate request as opposed to authenticating anything.
Using a timestamp is not the correct way because the time is not reliable across systems. Perhaps you can use the length/hash of the message as a parameter instead. It does not, unfortunately, prevent playback from an attacker.
Correct me if I'm wrong, but it seems as though you're dealing with authentication (ie, the sender is who they say they are) rather than authorization. I would suggest that you use SSL/TLS to secure the transmission to know whether or not the transmission is being proxied.
Related
I know that GET is used to retrieve data from the server without modifying anything. Whereas POST is used to add data. I won't get into PUT/PATCH, and assume that POST is always used to update and replace data.
The theory is nice, but in practice I have encountered many situations where my GET calls need to be replaced with POST calls. This is because the response often gets incorrectly cached. Where I work there are proxy servers for security, caching, load balancing, etc., and often times the response for GET calls is directly cached to speed up the call, whereas POST calls never get fully cached.
So for my question, if I have an API call /api/get_orders/month. Theoretically, this should be a GET call, however, the number of orders might update any second. So if I call this API at any moment it may return for example 1000, and calling it just two seconds later should return 1001. However, because of the cache, and although adding a version flag such as ?v=<date_as_int> should ensure that the updated value is returned, there seems to be some caches in the proxy servers that might ignore this.
Basically, I don't feel safe enough using GET unless I know for certain that the data will not be modified or if I know for a fact that the response is always the updated data.
So, would you recommend using POST/GET in the case of retrieving daily/monthly number of orders. And if GET, with all the different and complex layers and server set-ups, how can one be certain that the data is always updated?
If you're doing multiple GET request and something is caching the data in between, you have no idea what it is or how to change it's behavior then POST is a valid workaround.
In any normal situation you would take the time what sits in between your browser and your server, and if there's something that's behaving in a way that doesn't make sense, I would try to investigate and fix that.
So you work at a place where some of that infrastructure exists. Maybe talk to the people that maintain it? But if that's not an option and you just want to find the 'ignore every convention and make my request work'-workaround, then you can use POST.
IdentityModelEventSource has a property called ShowPII that means that Personally Identifiable Information will be added to the logs (in relation to security). This value is used to decide when to log some OAuth2 sensitive data.
I am trying to understand what kind of Personally Identifiable Information will be logged:
Client ID? (aka Client Key, Consumer Key)
Client Secret? (aka Consumer Secret)
Json Web Tokens? (aka JWT)
Access Tokens?
Refresh Tokens?
Kerberos Tickets?
PKCE Values?
Authorization Codes?
I know it cannot get access to usernames and passwords because they are only exchanged directly with the IDP.
But but I need to know if I need to find a way to lock down my log files because it will have data that constitutes a security vulnerability.
This is possible log messages of IdentityModel: LogMessages.cs
About
I am trying to understand what kind of Personally Identifiable Information will be logged
I won't copy-paste log messages from there (especially, as they can change at any moment). You can check them yourself and decide what should be considered as the PII.
But here's an interesting example:
"IDX10615: Encryption failed. No support for: Algorithm: '{0}', SecurityKey: '{1}'."
and this is how it's used:
throw LogHelper.LogExceptionMessage(new SecurityTokenEncryptionFailedException(LogHelper.FormatInvariant(TokenLogMessages.IDX10615, encryptingCredentials.Enc, encryptingCredentials.Key)));
If you'll follow the track you'll find out that encryptingCredentials.Key will be logged if ShowPII = true and won't be logged if ShowPII = false.
Of course, depending on your use case, this particular message may never appear in your logs. And not all messages so outrageously leaky. But you never know:
your use case may change
you may be mistaken about the set of messages IdentityModel can emit for your use case
IdentityModel code may change, and you may forget to check if messages' set is still secure
So about
if I need to find a way to lock down my log files
Yes, you definitely need to.
Or better yet - don't use ShowPII = true in production for monitoring, use it only in development environment for debugging purposes.
Looking at the source, it appears that when ShowPII is on - it will do two things:
Replace all parameters passed to library-specific exceptions with their data type names
For all system exceptions - replace inner message with exception type name
In this context "library-specific" is an exception that is of type Exception and its full type name starts with "Microsoft.IdentityModel." (library defines a few)
Depending on your use case you'd see a variety of parameters that can be logged with custom exceptions. A quick search for FormatInvariant yields quite a few for your consideration.
Again, depending on how you use it, you might get a better idea of what the error messages are by looking through relevant LogMessages.cs file on your specific namespace.
P.S.: on a side note, it appears that default ShowPII setting is GDPR-compliant
ClientSide Sending Key Example: tabc-xkaf-gaga-gtax to the Server
Server Checks if Key Exists in Database if YES then return TRUE as Response
ClientSide IF RESPONSE = TRUE THEN
OPEN FORM1
But thats not a Secure way to do it cause they can change the Response of the ServerSide check and then get the Product for free cause it will open Form1 anyone has a better way to do it?
Signed server side response and verify server response at client side to check whether response was altered or not.
Refer this article for how to digitally signed and verify
Moreover this will be a typical solution and suit for very complex security .
For simple solution, You can send hash of response along with server response and convert response to hash at client side. compare both hash , if they match it means response was not changed.
As you indicated, professional attackers can see and decode VB.Net applications, and hence, as an initial conclusion, you cannot reliably protect your code. In the first step, you must encrypt your code by using several encryption techniques such as the one mentioned by #Always_a_learner. However, this will not 100% protect your code from reverse-engineering (A good discussion could be found here).
A good trick in such cases is to make some intentional dependencies. For example, some core calculations should be done by the server (if possible) and only the result should be returned to the client. More explanation, for core calculations, the client should send a request to the server, and the server first verifies the requester (the sender) validity state, and if she is a valid user, then runs calculations and returns results to the user.
This solution is fine only if you can trade-off between speed and security.
I came to think about this question a few days ago when I desinged an HTML form that submits data via php to an SQL database. I solved my problem, but I am asking here a computer-theoretical question, which might help me (or others) in the future.
I want to protect myself from SQL-injection, and I thought that instead of validating the data by the php on the server side, I can have the javascript validate the data on the client side (I am much more fluent in JS than in PHP) and then send it.
However, a sophisticated user might inspect the javascript (or the HTTPrequest) and then alter it to send his own vicious request to the server.
My question:
Is it theoretically possible to do a computation on the clinet side, where the code is visible to him, and have it sent with some way that ensures that the data was sent from my program and not from an altered code?
Can this be done by an RSA-scheme with public and private keys?
I want to protect myself from SQL-injection, and I thought that instead of validating the data
Don't validate data to protect yourself from SQL Injection. Validate data to make sure it is in the format you want.
Escape data to protect yourself from SQL Injection (and do that escaping via prepared statements and parameterized queries).
Is it theoretically possible to do a computation on the clinet side, where the code is visible to him, and have it sent with some way that ensures that the data was sent from my program and not from an altered code?
No. The client side code can be bypassed entirely. In this arena, it is useful only to quickly tell the user that their data would be rejected if it was submitted to the server.
Can this be done by an RSA-scheme with public and private keys?
No. You have to give one of the keys to the client. It can then be extracted and used independently of your code.
I am using NSRULConnection to make http request on my iphone application. All works just fine.
The problem is after logged in I need to keep the same session to get data from the server.
I read a few posts saying all I need was using the same instance of NSURLConnection and it would use the same session... if that is true, that doesn't make sense to me, cause the NSURLConnection is not mutable and there is no method to change the request since I have to access different pages.
Is there anyway simple way to keep a session using NSURLConnection.
If you are managing sessions using cookies, there is no need to do anything special to achieve session management.The URL loading system automatically sends any stored cookies appropriate for an NSURLRequest. unless the request specifies not to send cookies. So, your sessions should be managed automatically for you.
However, as the Apple's doc says, if someone has set the cookie-acceptance policy to reject all cookies or only accept cookies selectively, you might be in a fix (you can change the cookie acceptance policy yourself too). In such a case, you might resort to URL based session-management; in which you append a session-identifier to the URL as a parameter (You can get this identifier as a part of the successful log-in response), which can be extracted on the server-side. This, however, is considered really bad practice.
Another way, which I have come across more often, is to get a session-identifier as part of the response for a successful log-in and include that identifier in all your subsequent requests as a parameter. Although this would require a major change in the way the server handles the sessions.