Passing sensitive data as NotifyWidget message

Passing sensitive data as NotifyWidget message

  

Hello, forum.


I have the following scenario:


  1. A WebBlock creates a record and notifies the Id of that new record using NotifyWidget and passing the Id as message.
  2. The parent WebScreen executes an OnNotify Screen Action which retrieves the Id using NotifyGetMessage and creates new records associated to that Id.


Is it safe to pass sensitive data (like internal Ids and keys) through a NotifyWidget message?


Since NotifyWidget creates an Ajax request, I am not sure whether the notification message passes through the user's browser, in which he/she could potentially modify the message contents before sending back to the server.


I am worried about any possible vulnerabilities that might be involved.


Thank you.

Hello Caio,

To the extent of my knowledge, it is safe because the message is not sent through the browser. This is the reason why you need a NotifyGetMessage, that will be executed server side.

So, the message is sent in server, and retrieved in server.

Cheers,

Eduardo

Hum... Caio, just to clarify... Which version of OutSystems are you using? Because I am thinking in the "Notify", in versions 9.1 and higher...

Actually it depends on the platform version. In the current version NotifyWidget is triggered and executed server side (mostly for performance reasons, to avoid client round trips, not security).

The old behavior can still exist on upgraded modules, using the "NotifyWidget_Deprecated" that forces it to pass on the client side.


That said, a OnNotify action can always be triggered from javascript, so you should validate any data obtained with a NotifyGetMessage since it may have been called manually on the client side with any value. 

Personally I would try to avoid to pass any sensitive information in notifies in favor of using other techniques like local variables, database or session.


Regards,
João Rosado

João Rosado wrote:

Actually it depends on the platform version. In the current version NotifyWidget is triggered and executed server side (mostly for performance reasons, to avoid client round trips, not security).

The old behavior can still exist on upgraded modules, using the "NotifyWidget_Deprecated" that forces it to pass on the client side.


That said, a OnNotify action can always be triggered from javascript, so you should validate any data obtained with a NotifyGetMessage since it may have been called manually on the client side with any value. 

Personally I would try to avoid to pass any sensitive information in notifies in favor of using other techniques like local variables, database or session.


Regards,
João Rosado


João,


I've sucessfully called the JavaScript function OsNotifyWidget passing any parameter as I like as message.


In my scenario, that's even worse than what I expected since it's very simple to inject different Ids.


In the end, I guess I should expect from the notification system the same vulnerabilities we have using GET parameters, which are easily manipulated by the end user.

Solution

Yes, in terms of security it's the same as using inputs in the screens.

Permissions and data validation needs to be done near the operations that do the data modifications.


In cases that the validation is hard there are alternatives like the ones I mentioned in my last post.

Also another alternative that is useful is to also pass a hash of the id/value that is being passed. We use that technique a lot in internal components (ex: ServiceCenter) to avoid inputs from being manipulated.
For example a screen that directly displays a message that needs to be passed as text input. Without any validation an attacker could use that input to do a "semi-"phishing attack by sending a user that url with a modified message. So when redirecting to that screen we add an extra input with a hmac hash of the text (calculated with a private key and if possible some user/session information) and in the screen we can validate if the text was tampered or didn't even belong to that user/session.


Regards,
João Rosado

Solution

João Rosado wrote:

Yes, in terms of security it's the same as using inputs in the screens.

Permissions and data validation needs to be done near the operations that do the data modifications.


In cases that the validation is hard there are alternatives like the ones I mentioned in my last post.

Also another alternative that is useful is to also pass a hash of the id/value that is being passed. We use that technique a lot in internal components (ex: ServiceCenter) to avoid inputs from being manipulated.
For example a screen that directly displays a message that needs to be passed as text input. Without any validation an attacker could use that input to do a "semi-"phishing attack by sending a user that url with a modified message. So when redirecting to that screen we add an extra input with a hmac hash of the text (calculated with a private key and if possible some user/session information) and in the screen we can validate if the text was tampered or didn't even belong to that user/session.


Regards,
João Rosado


João,


Using a HMAC will solve the issue for me. Great tip!


Thanks.

I've created a module that deals with this issue.


http://www.outsystems.com/forge/component/2369/notifyparams/


It encodes the message appending a hashed version of the original message using GenerateSaltedSHA512Hash. Then a second Action decodes it and checks whether the given message has been compromised using ValidatePassword (in which case an Exception is raised).

This information is really interesting. I never saw the Notify mechanism as being vulnerable to client-side attacks, but obviously it is!

The problem with this is that, like myself, many others will not see any problem with the notification mechanism, and it would be really difficult to enforce that other developers have thought about all implications.

I guess that, if you have a business layer that makes business validations on the operations you are performing on your business entities (like the 4-layer advocates), then that would be a more robust defense against such attacks. But it would require much more development and test effort.

Caio Santana wrote:

I've created a module that deals with this issue.


http://www.outsystems.com/forge/component/2369/notifyparams/


It encodes the message appending a hashed version of the original message using GenerateSaltedSHA512Hash. Then a second Action decodes it and checks whether the given message has been compromised using ValidatePassword (in which case an Exception is raised).

Hi Caio, think you confusing some cryptographic concepts there.

Looking up the definition of HMAC: "In cryptography, a keyed-hash message authentication code (HMAC) is a specific type of message authentication code (MAC) involving a cryptographic hash function and a secret cryptographic key."

GenerateSaltedSHA512Hash produces a Hash, not a HMAC. Since it's missing the "secret" part, anyone with the text can generate a valid hash for it.

You need a secret stored somewhere in the server side only (generated any way you want) and then a function that takes both your input and secret/password. The CryptoApi component has methods for that.


Regards,
João Rosado


João Rosado wrote:

Caio Santana wrote:

I've created a module that deals with this issue.


http://www.outsystems.com/forge/component/2369/notifyparams/


It encodes the message appending a hashed version of the original message using GenerateSaltedSHA512Hash. Then a second Action decodes it and checks whether the given message has been compromised using ValidatePassword (in which case an Exception is raised).

Hi Caio, think you confusing some cryptographic concepts there.

Looking up the definition of HMAC: "In cryptography, a keyed-hash message authentication code (HMAC) is a specific type of message authentication code (MAC) involving a cryptographic hash function and a secret cryptographic key."

GenerateSaltedSHA512Hash produces a Hash, not a HMAC. Since it's missing the "secret" part, anyone with the text can generate a valid hash for it.

You need a secret stored somewhere in the server side only (generated any way you want) and then a function that takes both your input and secret/password. The CryptoApi component has methods for that.


Regards,
João Rosado


Hi, João,


I take the "Salted" part of the "GenerateSaltedSHA512Hash" as the "secret" part?? Since this function is used for storing passwords, I believe it should salt it with a private key so I don't have to do this part.


The salt is not private, it's just a random string. It is used to prevent rainbow table attacks, and to make sure that two users with the same password never end up with the same hash. More details in wikipedia.

The result of GenerateSaltedSHA512Hash returns the salt as a substring of its output (I believe it's the text preceding the = character). That's because, to validate a password, you must retrieve the salt value, and re-hash using the same salt.

Leonardo Fernandes wrote:

The salt is not private, it's just a random string. It is used to prevent rainbow table attacks, and to make sure that two users with the same password never end up with the same hash. More details in wikipedia.

The result of GenerateSaltedSHA512Hash returns the salt as a substring of its output (I believe it's the text preceding the = character). That's because, to validate a password, you must retrieve the salt value, and re-hash using the same salt.


Hi, Leonardo,


Okay, thanks for the clarification. I misunderstood what the Action did and thought it would do that for me. I'll update my HMAC method and use a private salt before hashing.

I've uploaded a new version in which I append a randomly-generated 60-character-long salt to the message before encrypting. That should solve that.


Thanks to all.