Malicious software libraries found in PyPI posing as well known libraries
nbu.gov.sk
nbu.gov.sk
Last year someone wrote his thesis describing python typosquatting and standard library name squatting: http://incolumitas.com/2016/06/08/typosquatting-package-mana...
However after that the packages used in this thesis - the most successful one being urllib2 - weren't blocked, they were deleted. Benjamin Bach was able to register urllib2 afterwards. Benjamin and I decided that we'd now try to register as many stdlib names as possible.
See also: https://www.pytosquatting.org/
I think it's also on app developers to rethink the culture of randomly grabbing packages to build applications quickly. This is already a security problem even with approved repos. Having a rat's nest of packages makes it hard to upgrade quickly when those repos post updates to address vulnerabilities.
Edit: Removed confusing statement about return connections
I think it's clear at this point that you should be using internal mirrors of both programming language and OS package repos, so there is no need for build or production machines (other than those responsible for syncing the mirrors) to have outbound internet access at all.
That breaks down very quickly with the combination of public CDNs and TLS. I suppose you could do SNI based firewalling, but that is bit ugly, and afaik you can't do that easily with common firewalls (like netfilter).
Unfortunately most real world systems that have internet access are created in far from ideal conditions.
Unless you're super gung-ho about using Service Control Policies _and_ your service doesn't otherwise need to access s3, then there isn't really a way to block this.
If your application implements webhooks, then there's a valid use case? I'm in complete agreement however that you should default to deny and open up as required.
Without trying to downplay the seriousness, I think that's a less-than-charitable take on the bind they felt they were in. It also sounds like there's a crack team of dedicated devs sitting around waiting for something to work on.
https://caremad.io/posts/2013/07/packaging-signing-not-holy-...
I get the impression they don't care about security at all. They seem like children plugging their ears and shouting "nah nah nah" while putting repo users at risk. They've obviously done nothing since that post was made four years ago.
In contrast, Maven central requires signing. Unsurprisingly, Maven central doesn't have typosquatting problems. That's not a coincidence. That's also a strong reason why Java still dominates the enterprise.
If you (the reader) are a PyPi/NPM user, I challenge you to watch this,
https://www.youtube.com/watch?v=pBJafU0p_Nk
and tell me why you shouldn't use a repository manager like Sonatype Nexus which validates package signatures, checks licenses, and does vulnerability scanning.
By itself, package signatures aren't the holy grail? That's not the point. Security is achieved in layers. Too bad they aren't mature enough to understand that.
I had the absolute pleasure of working with dstufft for 6 or 7 months years ago and learned a ton from his breadth of knowledge and willingness to teach (and I had more than a decade of experience at the time). I can appreciate being unhappy with the situation and not agreeing with the approach, but personal attacks and assuming ill intent don't help. It is, of course, possible the developers actually do pay attention to the details and just see the issue better than you do.
I read that link at the time and I do wonder how you would address the issues he raises. The concern seems not so much not wanting to apply security but actually thinking about the underlying issues. Which is worse: an open but dangerous Pypi or one with a bunch of security theater around keys and hashes and other stuff everyone pays lip service to but never actually checks?
PyPi needs moderators to sit in the middle and remove anything that is obviously malicious, whether the packages are signed or not. Bad guys can sign packages just as easily as good guys.
Software should also be used to correct likely typos, perhaps including checking against a blacklist of known-bad package hashes, before the package is installed.
Yes, these approaches are imperfect, but they are better than doing nothing. "Perfect is the enemy of good".
Like Anaconda and Enthought? And countless internal departments? Or are you suggesting folks donate to the PSF and they hire a team?
There are already privately-maintained repositories and that's great, but IMO it's not an excuse for PyPi to leave this vulnerability open.
forgive my ignorance and my lack of 56 minutes to watch the entire youtube video, but who are the identities behind these signatures? The blog post you reference discusses the problem both of users signing their own packages (anyone can make a signature and any malicious package author can point people at a maliciously-owned signature as well) as well as having a central key (used by organizations with employees and known contributors, does not scale to pypi's model).
I'm also ignorant of a vulnerability scanner for Python (haven't looked). Does such a tool exist and have you proposed it as part of pypi's infrastructure? I am sure they'd be interested in that.
I'm not sure how the license file of a product impacts the issue of it being malware or not.
Took a look at https://www.sonatype.com/ and it appears to be a closed-source, commercial product - it appears to have a database of vulnerabilities in some format, but it appears to use hashes of some kind. I'm not sure how that would work against arbitrary Python source code, but again, I am ignorant. I would encourage you to write a comprehensive rebuttal to the blog post you refer towards.
https://maven.apache.org/guides/mini/guide-central-repositor...
"we require you to provide PGP signatures for all your artifacts (all files except checksums), and distribute your public key to a key server like http://pgp.mit.edu."
>anyone can make a signature
The article flip flops on this.
any hacker can do it
it's too much burden for developers
>any malicious package author can point people at a maliciously-owned signature as well
Anyone can also verify ownership of the key before accepting packages signed by it. This is something professionals do. This is something institutions do. This is something three letter agencies do.
>Does such a tool exist
There are CVEs for python. One could even scan a repository using those. Java has prebuilt tools for this. OWASP has the dependency-check plugin for Maven. Nexus uses the same information in their repository health checks.
>have you proposed it as part of pypi's infrastructure? I am sure they'd be interested in that.
Why would I? Given their response to signed packages, I would expect a response along the lines of "Too much burden. Too hard. Not perfect. Not worth it. Security theater. Go away. Ur dumb."
>I'm not sure how the license file of a product impacts the issue of it being malware or not.
It's one of those nice features of good repository management. Do python packages even list licenses? I mean, I assume they would, but then, they actively resist implementing other basic things which I would just assume they could do.
Licenses change over time. Some enterprises treat GPL like a virus. Knowing ReactJS changes from Apache to BSD + Patents in a new version is as important to someone in the business as knowing if a package is compromised.
>it appears to be a closed-source, commercial product
Nexus OSS is open source, Nexus Professional is commercially licensed. The later has a few nice features the former does not. Both can manage PyPi, NPM, Ruby, Docker, Maven, and Nuget repos to name a few.
https://www.sonatype.com/nexus-repository-oss
>I would encourage you to write a comprehensive rebuttal to the blog post you refer towards
It's easier to fool people than to convince them that they have been fooled. -- Mark Twain
Of course they do and it goes into the package classifiers.
Thanks, that's actually a great article that explains very well why you can't just throw signatures at the problem and claim that fixes everything.
As other commenters have pointed out, the reason Maven central doesn't have this problem has nothing to do with signatures, and everything to do with the fact that all new packages must undergo manual review, which is unfortunately a solution that doesn't scale. (See the "Linux Has Packaging Signing, Let’s Steal Theirs" section from the article you linked.)
Maven Central, to my knowledge, does not have typo squatting problems because Sonatype has a manual review process for all new projects. It has absolutely nothing to do with the fact that they allow projects to upload PGP signatures and it could not have anything to do with that, because PGP does not provide any mechanism to prevent that.
For example, there may be `urllib3` which is a valid project that must be signed by key X. We'll ignore how a tool like pip would find out that key X is the right key (although this is actually the most important part of a package signing solution) and just grant that we've solved that problem. Someone then comes and registers another project, `urlib3` which must be signed by key Y. The attack that is being described here is that a user would erroneously say ``pip install urlib3`` when they meant to type ``pip install urllib3`` and pip would then fetch that and download the package and install it. I think it is pretty obvious that signing doesn't help here, because pip doesn't know that the user really wanted urllib3 and not urlib3, so it can only determine that urlib3 is supposed to be signed by key Y (which of course, the hypothetical malicious person controlling urlib3 would have), fetch the package and verify it's signature.
There is only one tried and true method for preventing across the board this kind of human introduced error collision (aka typo squatting), and that is manual review of all new projects. The problem with manual review then becomes one scale. There are as of this time of writing 117,226 unique projects on PyPI with an average growth of around 100 new projects a day. In addition there are zero full time developers or operations or support people working on PyPI. There is one part time paid person (me), plus my unpaid time, plus one other part time unpaid developer/ops person who do the vast bulk of the work. There is simply not enough available bandwidth to process 100 new projects every day and to validate them for typo squatting/confusion possibilities.
Beyond that, there are a number of possible heuristic based approaches that can try to reduce the chance of this from happening such as using levinstein distance, unicode confusables, attempting develop "reputation", etc. Most of these are either so broad as to catch a lot of projects which are not typo squatting but are real, actual different things or are so narrow as to be trivially defeated. That's not to say they aren't worthwhile or there isn't an idea that would make sense but focusing on that has not been a priority for a largely volunteer based organization because there are lower hanging fruit that are more impactful , because at the end of the day without a manual review system individual end users are still ultimately responsible for ensuring they're asking for the correct thing (and even beyond that, they're responsible for ensuring that the thing they're asking be installed is something that satisfies their own security constraints).
Security is achieved by layering multiple secure systems on top of each other, not by randomly rubbing crypto on things because it makes you feel good to have crypto involved.
Key X is on the company approved key list, key y is not. Your argument just fell apart.
>The problem with manual review then becomes one scale. There are as of this time of writing 117,226 unique projects on PyPI with an average growth of around 100 new projects a day.
You're not dealing with projects. You're dealing with keys. It's not one key per project. It's one key per contributor. This has the added bonus that if a contributor goes rogue, you can revoke the one key and all the suspect projects are are invalidated at once.
>There is one part time paid person (me), plus my unpaid time, plus one other part time unpaid developer/ops person who do the vast bulk of the work.
Sonatype has turned this into a rather nice business. It's not a volunteer project for them. You expect me to believe it's impossible despite solid examples to the contrary?
>at the end of the day without a manual review system individual end users are still ultimately responsible for ensuring they're asking for the correct thing
Blaming the victims.
>Security is achieved by layering multiple secure systems on top of each other, not by randomly rubbing crypto on things because it makes you feel good to have crypto involved.
It's also not achieved by doing absolutely nothing at all.
My rough guess is that for the Python community, these are roughly proportional; there are a lot of different people maintaining approximately one library each, not a small number of people (or companies) maintaining large parts of the ecosystem. There's nothing directly like org.apache for Python.
I think the only way your key-signing mechanism would actually solve the problem is if we made it actively hard for new developers to upload projects to PyPI without a long vetting process. Some projects work this way (Debian, notably; I've had upload rights for a few Debian packages for years and still don't feel ready to apply for full access), but I think it's a poor match for PyPI's actual goal.
You know who does this sort of thing? Politicians. They can't just look at a working system, single payer for instance, and copy it. No, they have to make silly arguments about why it will never work, despite a concrete, working example, right in front of their own eyes.
If Python introduced manual review of new packages, it would either need a massive amount of resources that no-one is offering to provide, or it would immediately be a huge bottleneck on people making new packages, which the community doesn't want to do.
Lipstick on the pig, still covered in mud.
The key difference is the regular occurrence of malware finding its way into PyPi and NPM due to the lack of multilayered security on those repos.
You guys keep trying to prop up the straw man that ONLY package signing is needed. It's not. It's a start. Nobody is making that argument but you. You not only repeatedly beat that dead horse, but you carry it to the illogical extreme that package signing is somehow harmful. Not only do you see no value in that layer of security, but you actively resist any talk or attempts at implementing it.
Meanwhile, your repo is infested with hackers and malware. Big surprise.
you cannot locate said rogue contributor without regularly manually reviewing 117,226 packages.
Herd immunity. Someone is out there reviewing it. Most users won't need to lift a finger beyond verifying signatures.
More likely everyone assumes someone else is reviewing it, and nobody actually does.
A minuscule amount of people are going to bother to do something like approve keys. Security for the minority can already be achieved by those companies mandating their developers use DevPI and mirroring trusted projects from PyPI to DevPI (or similar system).
Complicating the system further for something that, for practical purposes, does not improve the security of the vast bulk of people is not a trade off we're willing to make. Package signing will come to PyPI, likely in the form of TUF which is strictly superior to the trust model provided by PGP for package signing. It hasn't done so because nobody has had the time to do it yet.
What you seem to be missing about my statement both in blog post and here is not that package signing is not worthwhile, but that a lot of people like yourself seem to think that all you need to do is add signatures to a system and suddenly poof it's secure! That view point is common among inexperienced developers or people who don't commonly think too hard about how secure systems are designed/made.
The reality of the situation that adding signatures is painfully easy, but that without a coherent trust model backing those signatures you've achieved nothing but adding more complexity. Determining a trust model (particularly one that works for the majority) is the hard part, and you can't just wave your hand and wish it better.
> Sonatype has turned this into a rather nice business. It's not a volunteer project for them. You expect me to believe it's impossible despite solid examples to the contrary?
Is it impossible to turn PyPI into a business? I don't suspect it is no. However I don't want to do that because my personal risk tolerance doesn't have room for giving up a stable job with health benefits for something that may or may not fail. Others are free to try that if they want of course, but given the lack of people stepping forward to do that, it doesn't seem like anyone else is interested either.
> Blaming the victims.
Stating reality. PyPI is not a curated repository and the end users is responsible for their own security while using it. If they wish to outsource that responsibility there are a number of Linux distributions that are happy to do that for them as well as companies like Enthought and Continuum Analytics who provide curated repositories.
> It's also not achieved by doing absolutely nothing at all.
Good thing we're not doing nothing at all then. Luckily for the Python community we have actual experts and not arm chair cryptographers who fail to understand even the basic fundamentals of developing secure software.
This is the weakest argument. Are Python devs somehow dumber than Java devs? Are they dumber than Android devs? Are they dumber than iOS devs? Everyone knows how to sign a dependency/app/project except python devs? I don't believe that. I honestly think that's the most insulting aspect of this argument.
The rest of this post seems to have turned to hand waving and personal attacks, so I won't bother responding to that. I'm just glad I got to share this perspective with you. Once you cool down, I hope you look harder at the problem. All I care about is improved security. I'm not here for the imaginary internet points.
Nope, I think they're perfectly capable of signing things. I also think it's silly to ask them to do that when the proposed system hasn't been designed to provide any benefit. Properly designing that system is hard, and 99% of people who go "just use PGP!" or "just use X" have spent exactly zero amount of time doing that. Particularly when the proposed solution doesn't actually solve the problem at hand (though it does solve other problems if it's correctly designed).
Ultimately your "suggestions" are nothing new, they're the same generic, cargo culting, suggestions that folks who haven't looked really hard at the problem tend to make.
Is your project the author of the packages identified by NBU? If so:
(1) Why is the tracking pingback obfuscated?
(2) Why does the code include a cheeky hello instead of a link to https://www.pytosquatting.org/ ?
(3) Why is there not a visible warning when installing one of these packages?
=================
edit:
Reading through the linked blog post [0], it appears these researchers used different code that DID provide visible warning and an cleartext pingback. It also collected command history and hardware information.
[0] http://incolumitas.com/2016/06/08/typosquatting-package-mana...
1. We're not obfuscating pingbacks.
2./3. We're raising an exception with an explanation and a link.
Just look at the code of one of our packages: https://pypi.python.org/pypi/codecs
The research in 2016 was done by someone else. The kinda crazy thing is: Some of the package names he used were made available again after that instead of being blocked... And now we own them.
html = urllib_request.urlopen(
"https://www.pytosquatting.org/pingback/pypi/{}/".format(package_name)
)
raise Exception(
"This is a bogus package that should not be installed\n\n"
"Please read https://www.pytosquatting.org"
)"Far from scary or obfuscated" reads more clearly.
Ugh. Yes, you are being jerks. The ethical way to collect statistics would be to ask the victim to click the pingback link.
It's only a matter of time before something like this happens. A big part of the problem is that application package managers, like pip or npm, are far less sophisticated than those of operating systems, like aptitude or yum. It needs to be easy for developers to open source their code, and to mark dependencies with precise commit hashes, but the download also needs to be secure and verifiable. There are many difficult tradeoffs to consider in terms of usability, centralization, security and trust.
OPAMv2 also exposes sufficient hooks during the build process for using OS sandboxing during builds, and disconnecting network access/etc. It would be nice to factor this out to be more OS independent (e.g. for all the `unshare` tricks on Linux, or the sexp-format for sandboxing on OSX) in the future.
Whilst a package manager repo. compromise would be the biggest bang in terms of attack, compromising the credentials of the developers of popualar libraries would be an easier attack (and indeed is already happening https://twitter.com/chrispederick/status/892768218162487300)
Also, even without sudo there's absolutely nothing stopping you (for example) downloading a cryptocurrency miner, or DDOS tool, or something, and starting it up to run in the background.
Running "pip install" as a user that has access only to the virtualenv directory is sounding like a good strategy.
One scenario that worries me is where apps age and use popular trusted dependancies (e.g. gems on Github).
When those gems stop being maintained but need to be updated to work (say with latest OSX) - it's common to quickly look at the latest forks available and select the one that now works correctly - but without a detailed inspection of the new code it's potentially kryptonite for a production datacenter.
The problem is one of scale. npm has over 500,000 packages, so no manual review will address their scale over the whole repository.
Until the developer market shows that they'll pay for a more secure service (e.g. package signed, reviews done etc) I doubt much will change.
There's a precedent for curated subsets of package ecosystems. Stackage for Haskell is an example, although it doesn't have security as the primary goal.
I don't think we should focus on actual audits of packages. Just checking that packages seem basically credible seems like a better approach because it's doable.
I'd agree that a curated small package repository would be a better way to address the problem, but the market doesn't seem very interested in that as a solution.
I don't think IRL identities are necessary for what I imagine. It's more like establishing a basic set of packages that have been around, have communities of committers, reverse dependencies, etc.
Maybe we would even make a starting assumption that the transitive closure of dependencies originating with a set of high profile packages are "approved".
I'm thinking aloud but I think there could be a reasonably pragmatic way to get this started...
it's been at least 5 years since npm started getting scrutiny relating to security weaknesses https://blog.andyet.com/2012/03/08/compromising-the-integrit...
and 4 years since Rubygems was compromised http://blog.rubygems.org/2013/01/31/data-verification.html
and yet, I don't see substantial movements relating to package security and trustability in these repo's. To be clear I'm not suggesting these two are any worse than others, they're just large repo's who have had incidents in the past.
The problem here (to my view) is that increasing the security of package repo's will slow down releases (additional checks take time) and cost money (additional security, hosting etc) and until there's a market demand for those service, they won't happen.
In general, Conda does more package verification than pip, and the packages in the Anaconda distribution are more thoroughly vetted than PyPi. Conda-Forge [2] provides an escape hatch for less-vetted community code.
[0] https://conda.io/docs/index.html [1] https://www.anaconda.com/distribution/ [2] https://conda-forge.org/
Also, they are not vetted and there are much more opportunities for an attacker to sneak in a backdoored lib on the edge of the dependency graph.
Finally, due to vendoring there's no way to receive timely drop-in security fixes for all dependencies from a trusted source.
The thing with node is that AFAIK it requires you to have libraries for what in most languages would be in the standard library. Maybe someone should start a "stdnode" project where the most popular / successful libraries for generic tasks are integrated into a dependable, maintained de-facto standard library, with an eye on quality and sanity, and community / Joyent funding.
They solved the issue 2 decades ago by heavily vetting packages before accepting them into repositories. Users are allowed to add and use packages from 3rd party repositories.
Maybe solution to this is creating curated repositories based on publicly open ones and using them by default (and requiring opt-in for using other repositories). Conda for Python and Stackage for Haskell seems like relevant solutions.
Each commit that went into trusty required a team to submit and a team to approve. That costs money. ;-)
Stable/lts/enterprise distributions have other concerns like preventing regressions and configuration or behavior changes during lifetime of release.
Rolling distributions like Arch and OpenSuse Tumbleweed on the other hand can move a lot faster but still provide basic vetting wrt security and sanity of new/updated packages.
Distro repositories are a great example of 'secure for ideal users'. They give you security if you can put up with a small selection of software and older versions. In practice, we end up working around distro repositories by installing stuff with pip, or PPAs, or downloaded from websites.
Yet Amazon and other big tech companies have a very similar process of packaging open source software for internal use and relying on "outdated" libraries.
> I sincerely doubt that Debian can provide adequate security to its almost 50,000 packages.
There's a security tracker where you can see how quickly packages are assigned CVEs and patched - sometimes even before the upstream patch is ready.
On the contrary, on distributions that perform security updates the level of security of a package can only increase over time.
It might sound obvious but vulnerabilities are created in new releases, while vulns in existing packages can be only be found and fixed, not created.
(Of course I'm talking only about vulnerabilities here and excluding removal of obsoleted crypto or addition of new security features)
For popular packages perhaps, but for many more obscure and niche python packages Ubuntu is often a several releases behind, and that is if there even exists a package to begin with
https://www.schneier.com/blog/archives/2008/05/random_number...
A.K.A., the Debian openssl Fiasco.
Just one example of distros fucking up the packages from upstream and causing major havoc.
Also the project pioneered reproducible builds and implemented build hardening for most packages.
Arguably. The issue with typosquatting on PyPi has been known and demonstrated for a long time, but nothing has been done about it. Considering there are ways of closing this attack vector, even though it would require some serious work, I'd consider this a bug. It's just a bug that's being exploited now.
Not really, PPAs (and equivalents like copr or obs or aur etc etc) are mostly vulnerable to similar problems. People do want to install upstream software for various reasons, blaming language package managers for the reduced security of that is imho disingenuous.
Language package managers solve the problem that we don't have neither an universal package format that works across all programming language requirements and all sort of OSes, nor the time to create an OS specific package for all sort of OSes.
There is nothing wrong with inventing their own solution if they're solving other problems, what is wrong is not learning from previous examples and fucking up creating problems that have been already solved in the process.
IP: 121.42.217.44 Decimal: 2032851244 Hostname: 121.42.217.44 ASN: 37963 ISP: Hangzhou Alibaba Advertising Co.,Ltd. Organization: Hangzhou Alibaba Advertising Co.,Ltd. Services: None detected Type: Broadband Assignment: Static IP Blacklist: Click to Check Blacklist Status Continent: Asia Country: China cn flag State/Region: Zhejiang City: Hangzhou Latitude: 30.2936 (30° 17′ 36.96″ N) Longitude: 120.1614 (120° 9′ 41.04″ E)
"Hi bro :)
Welcome Here!
Leave Messages via HTTP Log Please :)"
Fundamentally, the reason this is different from how thinks like Linux distos work is because Linux distros have maintainers who are in charge of making sure every new update to one of their packages is legit. I am sure you can try to sneak malicious code in, but it isn't going to be easy.
I am not advocating that PyPI (and npm) adopt the same model. That would be too restrictive. But maybe just showing the number of downloads isn't the best way to assure whether the package is legit. Perhaps some kind of built in review system would be nice.
If people want a more trusted solution the likely outcome is that they'll need to use a smaller more static set of libraries and then either do the audits themselves, or outsource that to a 3rd party.
Ofc with current speeds of change and deployments, it doesn't seem likely that many companies will adopt that model.
But at least the modules with the most downloads (webpack, react, or stuff like left-pad) could be vetted, and especially npm could implement a 2-or-more person model - basically, everyone with publish access can upload a new artifact, but to actually have it distributed to endusers, a second person would be required to sign off.
I worry about the most popular, and there the small and next-to-unmaintained. Just think back to the left-pad desaster that broke builds all over the world and imagine it was not a deleted package but an update containing malware. I assume there are lots of such "hidden gems" where the maintainer has gone away... the consequences of hacking just one improperly secured account are severe.
The fact it hasn't been done despite the obvious risks indicates how much demand there is for this feature...
That's what stable Linux distributions do.
How is that different?
IME the problem will continue unless the customers (e.g. companies making use of the libraries hosted) are willing to pay more for a service with higher levels of assurance.
The budget required to implement additional security at scale is quite high, and probably not a good match with a free (at point of use) service.
Here's an idea: make it similar to Kickstarter, where customers can commit a certain amount of funds towards a specific package. If the package doesn't "tilt" in a certain amount of time money goes back. Otherwise you vet a point release and add it to your repo. you could offer subscriptions to keep packages updated or handle each update as its own project (with presumably lower costs if a recent release has been audited). Handling dependencies is key as an exercise for the reader
What happens if a vulnerability nevertheless sneaks through?
The whoever did the vetting could conceivably get sued. So then they might want to take out insurance or try to protect themselves from lawsuits in some other way -- all of which is likely to make such a service even more expensive.
Can you? Positively identifying people seems a pretty tricky and easily screwed up business.
ID's can be forged, and a web of trust requires, well, trust.
I guess such a service could say something like "we got this person's ID (and/or address)" or "here's this key's web of trust", and that would probably be a bit better than what we have today (which is virtually nothing), but it would still be a far cry from "guaranteeing it is published by someone who is who they say they are".
Bitcoin trading platforms have shown that compliance with AML/KYC regulations can be performed virtually by manual verification of a valid government ID, timestamped photo, handwritten note, and other mechanisms.
A company offering this service would go outside of the keyserver and verify the ID independently. It'd be much more of a "notarized packages" paradigm rather than just "published by 1337PyHax0r-88".
It is true that even extensive manual verification processes dependent on government-issued IDs can be faked, but there's a much higher bar involved.
When you make the next big thing, consider this approach.
I have encountered the case "the package has an important bugfix but is not yet published on PyPI" way more than once or twice.
With the intermediate maintainers, that's going to get worse.
I believe namespaces and signatures are the way to go. With a special privileged namespace for the curated widely known packages (e.g. SciPy or Django) - a little like it's on the Docker Hub, where curated mainstream images are just "debian" or "python" but anyone can upload e.g. "jdoe/debian" if they need some customization.
I do wish that `--user` was the default for pip.
It is also a pity that trivial Debian bugs like this block adoption of non sudo pip installs weren't ignored.
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=839155
Although Debian/Ubuntu default to --user on pip people resort to sudo because the current standard user bin directory isn't in the default path due to a regression.
I may start a project to create a apparmor/selinux wrapper for pip to audit and restrict access to sensitive resources. I actually have a fairly heavyweight version in place on my build pipeline to detect new dependencies. I add the files/network resources that a build accesses outside of the testing stage to the build artifacts. But it wouldn't be cross platform enough for Windows/Mac.
2. I don't think `pip install --user` adds any significant security. A little bit - sure, but not much. A trivial injection into ~/.*shrc or ~/.profile (I don't think anyone would notice the file was changed until it's too late) would result in full system compromise on the next login and sudo invocation. Same goes if you have ~/bin or ~/.local/bin (or anything user-writeable) in $PATH.
And even with non-root access, malicious software can do a lot of undesirable things (e.g. send spam or steal user data).
---
I believe, signature-based trust (with mandatory code signing) is the way to go. On the first `pip install` ever ask "The package not-expect (1.2.3) is signed by The Spanish Inquisition (key: ...) and was audited by The Python Developers (key: ...). Have you verified the keys and do you trust a) this vendor, b) this auditor or c) both?", then it gets recorded in ~/.pip (for this machine) and ./requirements.txt or ./setup.{py,cfg} (for distribution) so future installations don't ask anything.
To get non-interactive mode (for CI or something), on must either pass something like --insecure-skip-signature-checks (so they mean it) or pre-supply all the trusted keys.
(Not ideal, of course - just a quick idea. Surely, it has a lot of rough edges to polish.)
On 2) even if you ignore the much larger attack surface due to running ALL installs as the root user, consider the one-shot opportunities by disabling the protections of capabilities(7) # capsh --print -- -c 'pip list > /dev/null' Current: = cap_chown,cap_dac_override,cap_dac_read_search,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_linux_immutable,cap_net_bind_service,cap_net_broadcast,cap_net_admin,cap_net_raw,cap_ipc_lock,cap_ipc_owner,cap_sys_module,cap_sys_rawio,cap_sys_chroot,cap_sys_ptrace,cap_sys_pacct,cap_sys_admin,cap_sys_boot,cap_sys_nice,cap_sys_resource,cap_sys_time,cap_sys_tty_config,cap_mknod,cap_lease,cap_audit_write,cap_audit_control,cap_setfcap,cap_mac_override,cap_mac_admin,cap_syslog,cap_wake_alarm,cap_block_suspend,cap_audit_read+ep
And if --user was the norm, it would be trivial to write an apparmor/selinux policy to protect files like ~/.*shrc or ~/.profile
It is just the basic principle of least privilege. Heck if irssi can bother with an apparmor profile, the maintainers of pip or the package should be able to.
Some security-sensitive packages are maintained by teams to share the workload.
However, source code can be signed and then used to make a package signed by a distro.
Code package management is different. The author writes their software specifically to conform to the one code package management system. There's no wrapper glue needed, so you don't need a maintainer. Just release your new code and it fits into the system, and other code/tools/etc can just pick it up and use it.
This works if you constantly update all the software you use everywhere, and is pretty much guaranteed to become a nightmare if you don't. CPAN is probably the most mature software package management system in existence and it's still a nightmare if you don't keep a private repo and tightly manage releases, and you absolutely need a maintainer.
Trust isn't an issue in reviewed/maintained repos because you have eyeballs on everything. When anyone can just ship an app/library and release it automatically you get these malicious software issues.
Even that minimal amount of work is enough to prevent such a ridiculous attack like typo squatting.
def get_command_history():
if os.name == 'nt':
# handle windows
# http://serverfault.com/questions/95404/
#is-there-a-global-persistent-cmd-history
# apparently, there is no history in windows :(
return ''
elif os.name == 'posix':
# handle linux and mac
cmd = 'cat {}/.bash_history | grep -E "pip[23]? install"'
return os.popen(cmd.format(os.path.expanduser('~'))).read()I checked:
https://pypi.python.org/security
https://twitter.com/pythoninsider
https://plus.google.com/+Python
https://mail.python.org/pipermail/python-dev/2017-September/...
Honestly, I am impressed that the information gone so quick! The National Security Authority of Slovakia contacted the PSRT 10 days ago. All packages were removed 1h10 after we got their email. We were discussing how to communicate about this issue, while they published an advisory. A few hours after the advisory was published, I saw the information on IRC, Twitter, LWN, etc. I didn't expect that the advisory would be published so quickly. FYI last week there was also a CPython sprint attended by more than 20 Python core developers. We were busy on discussing Python enhancements.
`pip list –format=legacy | egrep '^(acqusition|apidev-coop|bzip|crypt|django-server|pwd|setup-tools|telnet|urlib3|urllib) '`
This incorrectly lists `urllib3` or the `cryptography` package for example, which are perfectly valid packages.
[UPDATE]
Read "tobltobs" comment below. I incorrectly removed a trailing space from the regex.
https://gist.github.com/osteele/198b50a2a208e5bc7e5fb8d010cf...
Many batteries-included packages are also maintained outside of CPython. This is because: (1) in many cases they existed outside prior to being included in CPython, (2) they can experiment with new features before they're included in the CPython version of their package.
grep: alabaster: No such file or directory
grep: appdirs: No such file or directory
grep: arandr: No such file or directory
for dozens and dozens of packages. Are those errors benign?How about package manager managers accept their enourmous responsabilty? urllib vs urllib2, one is a virus? Sorry but that is not "negligence of the developer"
Another easy thing to implement would be a popularity check: "This package was only installed nnn times. Did you mean xxx, or do you want to proceed with the installation of yyy by author dev@g00gle.com?"
Email verification is a must.
PyPI is not a curated distribution.
People who upload packages often leave organizations, who are then stuck with a package they can't update because the password went with the person, and the email reset link points to a now-defunct email address.
Petitioning the package management team is sometimes fruitless, forcing a needless new instance of typosquatting.
There are so many shoulds in the world that don't make it to dids, it reminds me of the joke about the salesman trying to sell farming improvement techniques and being turned down by the old farmer, who says, "Son, I don't farm half as good as I know how to already."
Unfortunately, I have not found the PyPI group as helpful as you have. Perhaps I have been looking in the wrong places.
Because packages tend to be small and many, and each of those has their own dependencies, you can end up with hundreds of packages installed which is simply impractical to manually review.
It is not node, but we do in fact manually review each package we utilize for our given language because it's feasible and worthwhile as the dependency tree is small in this ecosystem. Each and every package is a possible attack vector whether that be intentionally or just because it's poorly written and we can't simply ignore that because it's the done thing and "the community reviews them".
Is Node is used in government and military solutions? If so then the NPM ecosystem is likely targeted by state actors, and it is a sitting duck.
Pypi actually blocks that name from being a package!
When a dependency changes, all the projects that directly depend on it should get notified immediately and their maintainers should rush to test the new changes, to see if they break anything.
There is no shortcut around this, because if B1, B2, ... Bn depend on A1, the consequences may be different for each Bk.
The only real secure optimization that can be done is realizing that some of the Bk use A1 the exact same limited way and thus make an intermediate A1b that depends on A1 which those Bk's depend on. These "projection" builds may be automated by eg the set of methods called by the B's.
Anyway, this is the way that iOS does it before iOS 11 comes out to users. They release a beta to all developers. And they even fix bugs in the beta before releasing to the public.
Without beta testing periods, you can get laziness and just auto-accepting of whatever cane out.
There is be an "alpha release" feature in git where maintainers might put out the next version to be tested by all who depend on it. THIS FEATURE SHOULD NOTIFY THE MAINTAINERS SUBSCRIBED TO THE REPO. THE BUILD ITSELF SHOULD GET ISSUES AND RATINGS FROM MAINTAINERS AS THEY TEST THE NEW BUILD. And releases should not be too frequent.
This is the way to prevent bad things from happening. But that also means that the deeper the dependency is, the more levels this process could take to propagate to end-users.
Knowing today's internet, programmers from cheap-labour nations (India & Co.) would soon start offering "trusted PyPi accounts" for sale on hacker forums.
Also http://evilpackage.fatezero.org/ / https://github.com/fate0/cookiecutter-evilpy-package
That one has neutered the call-home code by now, though.
That includes Java (Maven), Ruby (Gems, Bundler), Node (npm), Haskel (stack) etc etc.
Installing code via package managers is the coders equivelant of opening up an exe sent to you in an email.
Code downloaded from the internet is not to be trusted.
Signing packages helps against typosquatting about as much as SSL certificates help against phishing. Or in other words, not at all, especially if we don't have the certificates rooted in real world identities (like EV SSL certs).
https://pypkg.com/pypi/xml/f/setup.py
Dork: site:https://pypkg.com intext:"just toy, no harm"
Come back maintainers & packagers, all is forgiven!
I felt a bit curmudgeonly but we have a responsibility at https://qbix.com/platform for all our apps being secure. I wanted to use repos for each package and manually git pull or hg pull them when they changed.
I was finally convinced by our developers to just use package managers with version pinning. Honestly it's really hard to avoid package managers, especially for all the newer functionality such as Payment Requests or Web Push. Luckily there is version pinning.
We want our clients to feel secure that we vetted ALL the code that went into the platform. So our package json (and composer.json) uses version pinning. We'd rather take a bug report and manually fix it than NO bug report and have a SHTF moment.
pip list –format=legacy | egrep -e '^acqusition$' -e '^apidev-coop$' -e '^bzip$' -e '^crypt$' -e '^django-server$' -e '^pwd$' -e '^setup-tools$' -e '^telnet$' -e '^urlib3$' -e '^urllib$'
to see if you have any projects in a given directory that require them:
cat $(find /path/to/dir -name 'requirements.txt') | egrep -e '^acqusition==' -e '^apidev-coop==' -e '^bzip==' -e '^crypt==' -e '^django-server==' -e '^pwd==' -e '^setup-tools==' -e '^telnet==' -e '^urlib3==' -e '^urllib=='
Wonder what is an effective form of protection against such attack vectors?
Do digitally signed certificates fit into this usage scenario??
No, because either the package author would have to sign them, in which case you have to choose to trust each package author, or the repository would sign them, in which case there would be no improvement for this current issue, since the repo would sign the fake packages as well.
The best way to handle this is whitelists of trusted package maintainers and/or code authors.
https://mail.python.org/pipermail/python-dev/2017-September/...
find . -maxdepth 3 -name requirements.txt | xargs egrep '^(acqusition|apidev-coop|bzip|crypt|django-server|pwd|setup-tools|telnet|urlib3|urllib)'
pip list --format=legacy | cut -d' ' -f1 | xargs egrep '^(acqusition|apidev-coop|bzip|crypt|django-server|pwd|setup-tools|telnet|urlib3|urllib)$'
Deployed Maven artifiacts from Central are to required to be signed with a PGP key and are only supposed to come from approved hosts. I don't know how strictly that is enforced and how hard it is to become a host, but at least there is some kind of process.
Maven Central also doesn’t allow the removal of artifacts after they've been published, and every artifact requires a unique version and name. And the names are namespaced. So you don't have the issues that you see with npm, where someone can pull a package and break everything people are using, and then some third party can come in and publish anything under the exact same name.
Is this model perfectly secure? No, you still have to trust that the artifact was signed by a non-malicious person from a host that was not compromised.
In your POM file do you have a checksum?
edit:
get current working directory
get username
get hostname
concatenate the last 3 together
obfuscate(/encrypt?) this string
send the result as a http request to 121.42.217.44 (the value of the base64 string)# just toy, no harm :)
Yes, it might put a higher burden on the publisher if they don't host on github/gitlab, etc.
But it strips the "magic" part and makes sure the dev knows where the code is coming from.
And since most package managers eventually resolve packages to a URL somewhere, the issues you mention are probably present in other package managers, albeit hidden behind abstractions.
"packagename" instead of a full URL is quite a difference. And you are not addressing the other risks.
> On the other hand, with a URL, you can actually inspect the code directly
You can do that with most package managers as they show you the upstream URL.
Expecting every developer and every system engineer to verify every package and every dependency they install is not "just a tradeoff". It's simply impossible.
> since most package managers eventually resolve packages to a URL somewhere, the issues you mention are probably present in other package managers
Some check for the SSL certificate, some use package signing (e.g. APT). Also if the pypi domain expires everybody will know, unlike a random library.
It is more characters, and therefore easier to misspell, but a URL also gives you a domain and probably a namespace for the developer, each of which can act as indicators of trustworthiness and help disambiguate packages with the same or similar names.
If you can't double check your spelling for a package name or you just pick the first Google result, or paste from SO, then you deserve what you get. Domain hijacking, MITM, Unicode shenanigans and such are real risks, but not of URLs as package identifiers per se, so much as risks of distributing packages over the internet, which most if not all do anyway.
>You can do that with most package managers as they show you the upstream URL.
But if you don't have to deal with the URL, chances are you won't, and it's less likely you'll bother to follow it. I'm arguing that, if URLs are dangerous because of their length, then package names alone are dangerous because of their abstraction. I know that I can probably trust including "https://github.com/symfony/symfony" but "symfony" or even "symfony/symfony" alone tells me nothing useful.
>Expecting every developer and every system engineer to verify every package and every dependency they install is not "just a tradeoff". It's simply impossible.
True, but Linus' Law is still basically the security model that's supposed to underpin open source software, even it it's proven not to scale as well as assumed. Someone, somewhere has to know the code is safe, and that's either you or someone you trust, or (as is likely the case with most developers) someone you just assume exists.
>Some check for the SSL certificate, some use package signing (e.g. APT). Also if the pypi domain expires everybody will know, unlike a random library.
There's no reason a package manager using URLs can't also require package servers (which, let's face it, are probably going to be Github and Bitbucket in almost all cases) or maintainers to do something similar. Or at the very least put out warnings the way browsers do about invalid or untrusted certificates or unknown domains. You would lose the freedom of the "wild west" model in its purest form but still not be tied down to a single source of authority.
Package managers need to do more. If they had an enterprise version that you could subscribe to monthly/annually invoice that you would get enterprises onboard, they are concerned about security and will pay. Developers like us will help encourage it. I'd rather not see some third-party "secure" package managers but make them part of PyPi and send funding to the Python foundation. They are seeking donations but that doesn't work well with businesses. Make it a monthly/yearly service.