Applicationinsights-js: Security of InstrumentationKey in Client Side Code

Created on 27 Jul 2016  Â·  19Comments  Â·  Source: microsoft/ApplicationInsights-JS

Is there a more secure alternative to providing the InstrumentationKey directly in client-side code? I'd be concerned about a malicious user being able to easily add garbage telemetry data to my logs.

enhancement

Most helpful comment

Can we get an api for Application Insights that can validate a time-limited and tagged temporary insturmentation key/signature? Like SAS but for AI instead of blob storage. An Instrumentation Signature instead of Instrumentation Key. If the Instrumentation Signature (IS) is expired, logging with it fails. All logs emitted by that temporary key are associated with the tag value from the signature. When the client wants to log, it requests an IS from a backend service with access to the "real" key, which generates a signature for the client and returns it, a la SAS.

This would have many benefits:

  • No publicly available instrumentation keys
  • Each client gets a unique 'key', and all logs that they emit are associated with their key, allowing very easy filtering out of logs from abusive clients post-collection
  • Handing out signatures can also be controlled based on your own custom logic like ip-blacklists etc
  • Custom tags allow you to reliably add metadata to all logs emitted by a specific client, and it would be impossible for them to emit things they shouldn't, like uploading spoofed server logs
  • Tags could go even farther: For example, you could have anon/user/admin tags that you add to the IS according a logged in user's role when they request the signature, which would give you even more metadata facets to filter on
  • Automatically detect when someone is fiddling with stuff. For example, if they upload two log entries with two completely different user agents with the same key, then you know someone was poking around in the frontend code or mitm-ing network traffic and extracted the key.
  • No centralized list of keys or central coordination needed to create them, just like SAS

All Application Insights would need to do is validate the generated signature and add metadata from valid signatures to the log entries.

The only cost to the client is that it has to request the insturmentation key/sig from a backend service first. (I'm doing that today anyway.)

The backend service can be trivially simple: just tag and sign requests with the fixed insturmentation keys. It could be a 4-line function.

All 19 comments

Currently this is the only supported way. We are reviewing other options, but we don't have any timeline yet.

The problem is that even if the instrumentation key is not present in the client-side code, the JS SDK will need to get it somehow to send telemetry. There are multiple ways to send it more securely, e.g. the key can encoded, the backend can issue a one-time token, etc.
If the JS SDK can send genuine telemetry events, there is nothing stopping a malicious user from opening a browser console and sending garbage data.

You may consider:

  • enabling instrumentation only for authenticated users
  • sending all telemetry over https (JS SDK does that by default - #258)

@kamilszostak This would be much less concerning if the instrumentation key wasn't shared by secure environments (e.g server-side telemetry) that are not limited in this way.

@ramijarrar it is not a requirement to share the same instrumentation key. You can collect telemetry into two different applications and then combine information on a custom dashboard in Azure.

you could also do a separate client&server side key and have no further checking, then atleast nobody can put garbage on the server side of the telemetry

on top of that you could also add a check that makes sure a matching server generated correlation id exists for the client telemetry event to stop the most of the garbage that is a actual issue for people using google analytics (and may leak over to app insights in the future)

for more about that just bing it https://www.bing.com/search?q=google+analytics+bad+data
TL;DR spammers\hackers inject malicious referrals or other url's to lure site admin's and try to hack them

Any timeline on when this will be done?

Cross apps query has strong support in the portal today. So, splitting up client side to a separate ikey is recommended here. Have you considered dropped data on client where authenticated user id is not setup?

Thanks @jpiyali . Any examples/pointers how to achieve this? (i.e. for splitting up client side to a separate ikey is recommended here)

What kind of app do you have? You can create a second application insights resource in the azure portal. Update instrumentation key that is used in javascript and redeploy your client binaries.

Its javascript react web app. Problem is that instrumentation key is visible on browser source.

Can we get an api for Application Insights that can validate a time-limited and tagged temporary insturmentation key/signature? Like SAS but for AI instead of blob storage. An Instrumentation Signature instead of Instrumentation Key. If the Instrumentation Signature (IS) is expired, logging with it fails. All logs emitted by that temporary key are associated with the tag value from the signature. When the client wants to log, it requests an IS from a backend service with access to the "real" key, which generates a signature for the client and returns it, a la SAS.

This would have many benefits:

  • No publicly available instrumentation keys
  • Each client gets a unique 'key', and all logs that they emit are associated with their key, allowing very easy filtering out of logs from abusive clients post-collection
  • Handing out signatures can also be controlled based on your own custom logic like ip-blacklists etc
  • Custom tags allow you to reliably add metadata to all logs emitted by a specific client, and it would be impossible for them to emit things they shouldn't, like uploading spoofed server logs
  • Tags could go even farther: For example, you could have anon/user/admin tags that you add to the IS according a logged in user's role when they request the signature, which would give you even more metadata facets to filter on
  • Automatically detect when someone is fiddling with stuff. For example, if they upload two log entries with two completely different user agents with the same key, then you know someone was poking around in the frontend code or mitm-ing network traffic and extracted the key.
  • No centralized list of keys or central coordination needed to create them, just like SAS

All Application Insights would need to do is validate the generated signature and add metadata from valid signatures to the log entries.

The only cost to the client is that it has to request the insturmentation key/sig from a backend service first. (I'm doing that today anyway.)

The backend service can be trivially simple: just tag and sign requests with the fixed insturmentation keys. It could be a 4-line function.

@infogulch SAS or similar seems to be an interesting approach, also for other services. However there should be a mechanism, which is responsible to generate the "SAS" and "inject" it in the JS code, semantically similar to managed identity.

Yes, you could replace "client make a request to the backend service to get the token" with "server-side rendering of index.html (etc) embeds a unique key in the page that client js finds and uses". This capability can just be an addition in your server side code that uses the same SAS-like mechanism.

Just thinking aloud here: What if AI collection requests can be restricted to specific domains?

Eg, Requests using key abc-xyx can only be made from configured domain example.com.

Together with using a separate server-side key, this would also secure the user-agent key.

@NoelAbrahams Presumably an attacker would just make calls from within the console while breakpointing into code on your website?

What on the Application Insights server-side could be done to ensure a call is made from the configured domain? CORS only works inside a browser, so an attacker could use Postman or cURL. The IP address of the caller is the user's machine, not that of the hosting domain, because it's code running the browser.

@rikkiprince that's what would make a SAS-like token the best possible solution. The key point is that each client gets a unique short-duration instrumentation key, that's all you can control, you can't control what happens to the keys once's they are off your servers. However, since each unique key leaves its mark on all of it's data, if a key gets stolen and starts providing bogus data that you can detect, you can completely and accurately filter out that abusive client key without affecting data from other customers.

You can't stop someone from abusing a key, but a SAS token-like instrumentation key authorization system would give you a sharp tool to manage what data made it into reports based on your logs and metrics.

@rikkiprince, I'm just going on the basis of what's already implemented for OAuth authentication. For example Facebook authentication. Calls to their API only seem to work from domains that you configure on their developer console. Same with Google Maps.

I haven't tried hacking into this by setting a breakpoint and altering the payload, but clearly that will limit hacking to nutcase scenarios rather than industrial scale hacking, which is what we're worried about.

The problem I have with the SAS solution is the added maintenance — having to deal with expiry. I may have misunderstood that.

If a website Client-Side Code discloses InstrumentationKey is there a risk?

It's not really a security risk as the iKey itself doesn't provide any permissions of any kind.

The only real "risk" is that if a bad actor grabs and reuses your iKey, which would cause your ingested events (data in Azure Monitor) to contain a mixture of you real user and this "extra" data. Depending on the amount of these events and how this data is constructed would determine what the real level of the risk is for your subscription (this would directly affect your application).

Details: As there is no event to request a per-session key to provide CSRF style equivalent of validation of the iKey (this would require your service to fetch this and provide this to every page (instead of the iKey)), so there is currently no-easy solution beyond some type of whitelisting (based on the referrer or origin headers) of the requests to block the event(s) from getting ingested, but even these could be spoofed by constructing a raw TCP packet by a determined actor.

It's not really a security risk as the iKey itself doesn't provide any permissions of any kind.

Write permissions are permissions. A malicious user could inject data that the owner is not allowed to store.

Was this page helpful?
0 / 5 - 0 ratings