When to not require

Supply chain attacks are all the rage.

  1. Compromise a popular upstream repository
  2. New version of the repo is published containing your malware
  3. Downstream users update their code & dependencies
  4. Compromise spreads through normal auto-update routines
  5. Profit?

There’s a bunch of ways to reduce the risk of this vulnerability but there’s only one way to completely remove it.

One simple solution is that you don’t use any unnecessary third party packages, and you do what you can with what you already have, usually with a little extra effort (or code).

This is one of the foundational principles I’ve observed throughout my software engineering career; when you only need a small piece of functionality from a large library, don’t install the library, just write the functionality yourself. You learn more, you reduce your risk exposure, and reduce your reliance on third parties to do things properly.

This process might be a bit harder in the short run, because you’re having to actually write code to do something, instead of installing a library that someone else already wrote, but you really should see this as a golden learning opportunity.

You’re not re-inventing the wheel; you’re learning how to make a wheel that perfectly suits your needs, and you then own that wheel, it’s yours, forever.

Here’s an example. Recently I was trying to implement in Python the ability to call docker compose up -d in my code, so that the code itself can make changes to a docker-compose.yml file and implement the changes procedurally.

I’ve been using the docker-py library for some time and find it really useful – the main advantage of this is that the docker-py library only needs access to the docker socket, so I don’t need any of the docker binaries locally accessible to my code, which is very handy because my code runs inside a Python-only docker container – all I have to do is mount the docker socket into the container, and my code has all the access it needs.

Here’s some code which is the equivalent of calling ‘docker image prune’, which deletes all unused and un-linked container images:

from typing import Dict
import docker

client = docker.from_env()
output: Dict[str, int] = client.images.prune(filters={'dangling': True})

So the functionality I wanted to implement is the equivalent of docker compose up -d, but since that functionality is part of ‘docker compose’ and not native to docker itself, I can’t easily use the docker-py library, without re-writing loads of code just to do what docker-compose itself already does with docker.

There’s an easy option – I just mount or install the docker and docker-compose binaries from the underlying host system into the docker container. I’ve done this before and it works well, and is a fairly common practice for controlling docker from within a container running inside docker, but it has security issues, and I would rather just use the docker socket, because it ‘smells a lot better‘ for a machine to be using a socket intended for machine use, rather than calling a binary executable via shell, which is intended for human use.

(I’m acutely aware there are security issues around having a docker container managing the host docker eco-system, but that topic is outside the scope of this discussion.)

The alternative package suggested by Gemini is python-on-whales – which allows programmatic access to docker compose commands. It has 700+ stars in GitHub so seems like a moderately popular library.

First of all, the containers I write are often deployed into resource-constrained environments, so I have to be mindful about how much space, bandwidth, CPU and memory these containers consume, so I always pay attention to those factors. When I included this library into my code, the docker layer grew by around 12MB. That’s a pretty big uplift compared to typical packages, there are a very limited number of reasons for this:

  1. The python-on-whales has a huge amount of functionality, 99% of which I will not be using, and I can’t get rid of without forking the library and doing nasty things to eliminate most of the positive reasons to use a third party library in the first place
  2. The library is bloated, and includes a bunch of third party libraries which aren’t already in my system, because I build very lean and compact apps.
  3. Or a mixture of both, which is most likely.

12MB wouldn’t be a problem for most people, but when you consider that all I’m trying to do is run docker compose up -d in my host docker environment, and I can achieve that with 2 lines of code in Python and a couple of extra mount points into my docker-compose.yml file, the 12MB starts to feel a bit unjustified.

It was only after I discovered the 12MB layer addition that I also found out that the python-on-whales library doesn’t work unless it has access to the docker and docker-compose binary executables, so it’s not even reducing complexity on that side either. It doesn’t even use the docker socket!

Not only do I have an additional 12MB in my stack, it doesn’t even work without me making further changes to my container, or the compose mounting config. In the end, python-on-whales seems to be little more than a binary wrapper, calling instructions the same way an end user would, and parsing the output into something object-oriented.

Now back to security.

By including the python-on-whales library into my code (which is at version v0.81.0 at time of writing) we have to spend some of our time doing due-diligence into that package, to check that they are following good practices with regards to supply-chain security, and that it’s being kept up to date.

This is a process that 99% of developers have no interest in, or time to spend on. We already have huge amounts of stuff we “should” be doing in this area, we should be aiming to minimise it, not contribute to the pile and continue to ignore it, or chuck the quality/security assurance problem over the fence to the next chump.

If I have the choice of

a) investigate the third party library for vulnerabilities, research their CICD strategies and contributors, bloat my deployment by 12MB, and repeat that process at regular intervals to comply with patch-release strategies,
or
b) write a few extra lines of code, and be a bit more mindful about my dependencies.

I know which one I’ll go for, every single time.

password generator progressive-web-app

 

Back in 2015 I wrote a javascript-based password generator that I turned into a drag-and-droppable bookmarklet, which is a tool that I still use today.

However, as we move forward I found myself signing up for more and more accounts using my mobile device, which doesn’t have support for bookmarklets in the same way that a desktop does.

I also got fed up with having to sign into my password manager on my mobile every time I wanted to generate a new password.

So, after seeing a talk at Brighton PHP on progressive web-apps by Rowan Merewood, I decided to create a new password generator, specifically for mobile devices.

Check it out here. Source code available here.

Check out my original post from 2015 here.

Here is the original bookmarklet, drag it into your bookmarks to use it: [PwGen].

See the PwGen app on securityheaders.io.

Screenshot from PwGen on a mobile device

phones: don’t be complacent with your trust

We trust our phones to connect us to the world, and they allow us to prove our identity.
They are an authentication factor in themselves – proving we have the phone, is one measure of proving we are the owner of an account (via Email, SMS, Google Authenticator, etc).
Proving we can unlock the phone is itself another measure. (Mostly just to prove we didn’t recently steal the phone.)

So why do so many of us who also use our phones for work, agree to trust our employers with complete control over our phones?

I recently wanted to access my work email on my phone, so I installed the email app, and it told me I must have an administrator allow the connection.
So I contacted my friendly local sysadmin, and they said:

You need to install the policy tool on your phone before we can allow you to access work email on your phone.

Fine. So let’s look at the permissions this “policy” tool is requesting:


Notably, the app wants these permissions:

  • Erase all data on the phone by performing a factory reset.
  • Change the screen lock.
  • Lock the screen.
  • Enforce storage encryption.

I understand these requirements from a security perspective; they are all administrative functions I would want to have control over, if I owned the phone – which I do. The problem is that the company who I work for does not own my phone. I will never trust them to the same degree that I trust myself.

When I spoke to my colleagues about this, they all said the same thing to me:

But the company will never actually _use_ any of these permissions. – They just want to be able to delete your email from your phone if it’s lost or stolen.

This completely misses the point.

I refused to place my trust in this app for two reasons:

  1. Apps should not be granted more permissions than they need to fulfil their purpose.
    If I agree to these permissions, then it has the power to use them, regardless of any good intentions.
  2. Whether I trust the SysAdmins of my company is irrelevant.
    If a SysAdmin in my company can control my phone – then I’m also entrusting this control to a string of black-box processes and procedures that I have no control over.
    I treat my phone security very seriously – *Nobody else* has the same motives to protect my phone, as I do.

If my company gets hacked – or if any one of the SysAdmin’s accounts gets hacked (and there are probably multiple Sysadmins that have the same access to control my phone) – then a malicious actor now has the ability to lock out my phone, or wipe it with no warning.

This may have the following side-effects:

  • Loss of personal files/photos stored on the device (assuming they aren’t all backed up to the cloud somewhere)
  • Loss of 2-factor login codes (because you don’t have a U2F device)
  • Loss of 2-factor backup codes (unless you keep them stored somewhere safe, and not in a text file on your phone)
  • Loss of other account passwords that you keep in an encrypted text file that you keep on the encrypted SD card in your phone (which isn’t in the cloud, for “security”…)
  • Inability to contact anyone (because you don’t actually remember anyones phone number anymore)
  • Inability to buy things (because you rely on Apply|Android Pay and no longer carry cash or cards)
  • Inability to use public transport (because you use an App for that)
  • Inability to control your house heating/lighting/door-locks (because you can’t get enough of those IoT devices)

But these issues aren’t limited to you. This policy is something that everyone in the company who wants access to their email on their phone, has to agree with and accept.

So if I’m a hacker and I’ve compromised just one SysAdmin account – I have the ability to wipe the phone of everyone in the company who has placed their trust in this app.

Does this include the CEO or board of directors?
Does this include all of the security staff?

Desired Outcomes

A malicious actor might choose to disable these devices for the following reasons:

  • To destabilise a company during a critical period of business, causing financial harm.
  • As part of a campaign to cause as much damage to the company as possible.
  • To inhibit security personnel from countering the actions of the malicious actor.
  • To restrict the short-term management of company stocks and shares.

General Motives

  • Individual victimisation.
  • Retribution against the company.
  • Competitor motivated or financed.
  • Foreign government de-stabilisation.

Victim / Target

The intended victim in this attack can vary a lot. As a user, I might intentionally be the only victim in a directed attack, but I could also just be one of billions of victims.

  • Single targeted user.
  • A group of users within a company who share a common function. (eg. Security Personnel)
  • The company itself (All users of the app in the company)
  • All users of the app (If the app or app company is targeted)
  • All users in a specific country (In a state-sponsored attack on a foreign government, as part of a de-stabilisation process)

Mitigation

  • Any app you require your users to install on their devices, should only have the permissions required to serve its purpose.
  • The ability to perform actions on users’ personal devices must be restricted to those who absolutely need it.
  • Multiple SysAdmins should be required to act as a “group action” to carry out a non-reversible process such as ‘wiping a device’.

Summary

As a company, we need to be less cavalier about what we ask our users to trust us with.

As an employee, we need to be more protective of our own devices, our data, and our privacy.

As system designers, we need to allow for multi-admin safeguards, to ensure any action that results in any action against a user’s device can only be carried out as the collective actions of an authorised group of administrators.

As system engineers, we need to ensure any actions that are carried out are recorded and audited, so that misuse of the system can be identified, reported, and investigated thoroughly.