12 ms·
Remote code execution in cdnjs of Cloudflare
- ffjffsfr 5y agoGreat work finding this out, it was really fascinating read. Just wondering how do you publish compromised package to npm? CDN had to install some npm package right? Publishing some package is easy, but how do you publish something that is downloaded by Cloudflare? If it is so easy to publish compromised npm package and it ends up in cloudflare CDN it is quite scary, even if underlying security loophole related to overriding paths by tar is fixed.
- SahAssar 5y agocdnjs and similar CDNs should be considered mirrors of what they are serving, so they don't do any security checks on it. It is best not to use these services, especially since cache-partitioning and http2 makes them obsolete.
- sudhirj 5y agoThe vulnerability is the ability to poison the cache of some popular library once I steam the WORKERS_KV token. I could choose the most popular library, say Bootstrap, and change it to something else. People who loaded the script with SRI on browsers that support SRI would notice a problem, but could still target millions of others.
- klohto 5y agoI’m amazed on how many websites today still don’t use script hash or nonce and happily reference random CDNs with unsafe-inline. Not saying this then wouldn’t be an issue, but at least you have a failsafe.
- raxxorrax 5y agoOr just "vendor" your dependencies. Advantages and disadvantages...
- plasma 5y agoCould anyone recommend BugCrowd vs HackerOne (vs others?) from the view of a company wanting to a formal have pentesting and ongoing bounty program? I've read the pricing models are different between the two and pentesters seem to work with both.
- alfiedotwtf 5y ago> Wait for the cdnjs library update server to process the crafted .tgz file. I'm a bit confused... how did they get their updates pushed to a repo they didn't control?
- lalaland1125 5y agocdnjs will mirror any npm package They didn't update any part of cdnjs itself. Instead, they triggered cdnjs on their package.
- jtsiskin 5y agoDo they? Their website https://cdnjs.com/libraries https://cdnjs.com/libraries says "Couldn't find the library you're looking for? You can make a request to have it added on our GitHub repository." Amusingly you can see the "hey-sven" library they added to test the fix: https://github.com/cdnjs/packages/pull/695 https://github.com/cdnjs/packages/pull/695 If you download the tarball directly, https://registry.npmjs.org/hey-sven/-/hey-sven-1.0.2.tgz https://registry.npmjs.org/hey-sven/-/hey-sven-1.0.2.tgz, then tar -ztvf hey-sven-1.0.2.tgz, you can see -rw-r--r-- 0 ryotak staff 204 Jun 2 16:21 package/package.json -rw-r--r-- 0 ryotak wheel 10 Jun 2 16:21 ../../../../../../../../../../tmp/ryotak -rw-r--r-- 0 ryotak wheel 10 Jun 2 16:22 ../../../../../../../../../../tmp/ryotak.sh both which just have the contents "Retesting"
- aylux2121 5y agoI'm just trying to find the root cause. I see that is PR is merged by a contributor "xtuc". Root question is that why was this PR merged? Apart from reading/writing to other files in the build pipeline instance (which is a really good catch), primary problem I see here is that anyone is able to deploy any arbitrary code/javascript to serve it from cdnjs. Just send a PR, then some contributor will merge it without checking the release package content. Don't you think that is open to a lot of issues?
- alfiedotwtf 5y agoAh. Nice.
- alexlur 5y agoGreat job on finding the vulnerability. Anyone who uses a CDN link should use the integrity attribute, which can be generated by https://www.srihash.org/ https://www.srihash.org/.
- fulafel 5y agoWhat would likely happen if the SRI hash check triggered? The devs would have to be pretty savvy to suspect CloudFlare has actually been breached and refrain from just remaking the hash for the new updated content, in the middle of a production outage.
- robin_reala 5y agoWhat other conclusion could you come to apart from a CDN breach? That’s the entire point of SRI. What’s harder is persuading devs to architect systems with reasonable fallbacks in case CDN loading fails.
- l33tman 5y agoI think the issue is that a lot of devs won't care, they are contractors and some project leader calls and says something is down, they see a failed hash, download it again and restart.. and the hash check in the first place was probably a copy/paste from a SO question.. I'm sorry for the cynicism but I'm pretty sure this is the reality for the bulk of internet companies out there.. :/
- meowface 5y ago>What other conclusion could you come to apart from a CDN breach? "Ah fuck, hundreds of users are suddenly calling/emailing/tweeting at us saying they can't load the site, and I see a bunch of errors in the console while testing from a fresh browser. Looks like it's only affecting browsers that don't currently have this CDN JS file in cache. The CDN must have broke something, but things seem to work okay when including the script with a standard script tag. I'll just remove this SRI attribute thing for now to stop the bleeding." Or, if they have a bit more knowledge/do a bit more research: "Looks they might have pushed a change that minifies the JS file slightly differently or something, or maybe the script got upgraded to patch some issue? And I guess the change probably broke the SRI thing? I don't know if the file is going to change again in the near future so I'll just remove this annoying thing for now until they provide some recommendations." (Or: "I'll just hash the current version of the file and change it to that, and prepare to change it again ASAP if the errors re-appear.") Someone more experienced/knowledgeable would obviously not operate that way, but given how popular cdnjs is, seems fairly likely at least a few administrators would do something like that. Especially if they don't fully understand what the intitialism really means or what a hash is or how integrity is defined in this context and what the implications might be. Their instinct might just be to see something breaking the site for lots of users and to "fix the problem" as quickly and easily as possible.
- hannob 5y agoOne aspect that I think isn't common knowledge: You shouldn't use javascript libraries from CDNs. It's less secure, has less privacy and is slower than selfhosting. Why is it less secure? You're adding an additional point of attack. Someone could compromise the CDN or they could stop operating and the domain will fall to someone else. (And it doesn't really matter if your CDNs security is better or worse than your own hosting security - if you use a CDN it adds security risk and does not take away the risk from whatever other hosting you're using.) Why privacy? Your CDN can at the very least read the IPs of your visitors (+ they could add cookies, which will usually not happen but still is a possibility) and you may need to worry about legal issues (e.g. adding it to your GDPR statement). Finally performance: I guess many people will use a CDN "because it's faster" - except it's not. In the past there used to be the argument that the JS may already be cached. However that's no longer the case as for security reasons browsers partition the cache based on the origin. It's always faster to fetch a resource over the same connection compared to opening up a new connection to a different host. So: Don't fetch your JS from CDNs, just put it in your webspace and fetch it from there.
- SahAssar 5y agoOn performance it is also good to mention that these sort of cdns where mostly conceived before http2, so then you ran into the risk of filling your connection quota to the origin server. Nowadays with http2/http3 that is no longer a problem.
- xiwenc 5y agoWell said! Times has indeed changed. Today we have access to: - http2 - broadband internet - clients have large local caches/storage Privacy and security are gaining traction.
- jhgg 5y agoStill can't beat the speed of light...
- robin_reala 5y ago
- mcraiha 5y ago"archives that contain filename like ../../../../../../../tmp/test may overwrite arbitrary files on the system" Maybe paths like that and symlinks should be behind flags that are disabled by default? Specially if you are extracting content that you didn't generate.
- deleted 5y ago[deleted]
- TheDong 5y agognu tar does disable extracting paths like that by default. You need to explicitly add the '--absolute-names' flag to gnu tar in order to extract such a malicious archive. I think all tar utilities that are in common usage disable extracting those sorts of paths by default. It just happens that the go stdlib includes a tar implementation that was written from scratch (the go authors are allergic to re-using any C code and will NIH as much as they can).. and they probably don't want to fix it now because the go1 promise heavily discourages making changes like that, even if security is an exception to it. As a random data point, since go and rust are often compared, the most popular tar extraction library in rust has a secure default for this: https://docs.rs/tar/0.4.35/tar/struct.Archive.html#method.unpack https://docs.rs/tar/0.4.35/tar/struct.Archive.html#method.un...
- q3k 5y ago> It just happens that the go stdlib includes a tar implementation that was written from scratch (the go authors are allergic to re-using any C code and will NIH as much as they can).. and they probably don't want to fix it now because the go1 promise heavily discourages making changes like that, even if security is an exception to it. It's not about NIH, it's about this being a low-level tar parsing library, not a ready-to-use unpack tool or even a library with unpack functionality. I would never expect such a library to do any sort of automagic path mangling for me unless explicitly stated! I see the same behaviour in libarchive (C library), microtar (C library), and calccrypto/tar (C _tool_ that is vulnerable to this). How would have re-using any C code helped here, if the top three (from Google search results) C tar libraries have the exact same behaviour? The same behaviour is in Python's tarfile, too. Plus, even with Go1 stability guarantees, there's nothing preventing the Go standard library from adding a struct method like .SafePath() if it's deemed necessary - standard library types regularly get new fields/methods added to them. > the most popular tar extraction library in rust has a secure default for this ... only on the high-level unpack methods. The low-level unsafe stuff is still there: https://docs.rs/tar/0.4.35/tar/struct.Entry.html https://docs.rs/tar/0.4.35/tar/struct.Entry.html (.path, .unpack). And that's basically the API level which Go's archive/tar provides. If that crate didn't provide unpack functionality, it would have been the exact same kind of footgun.
- Aissen 5y agoAfter checking the contents of the file to send the report, I was surprised. Surprisingly, clearly sensitive information such as GITHUB_REPO_API_KEY and WORKERS_KV_API_TOKEN was displayed. I couldn’t understand what happened for a moment, and when I checked the command log, I found that I accidentally put a link to /proc/self/environ instead of /proc/self/maps. […] It seems that GitHub notified Cloudflare immediately because GITHUB_REPO_API_KEY (API key of GitHub) was included in the repository, and Cloudflare started incident response immediately after the notification. […] April 6, 2021 20:30 cdnjs processed the file At the same time GitHub sent an alert to Cloudflare At the same time Cloudflare started an incident response Within minutes Cloudflare finished revocation of credentials April 6, 2021 20:40 I sent an initial report This a nice Github feature. Also kudos to Cloudflare for quickly reacting to this.
- mschuster91 5y ago> This a nice Github feature. Indeed. See https://docs.github.com/en/code-security/secret-security/about-secret-scanning https://docs.github.com/en/code-security/secret-security/abo... for more details on how it works.
- wallscratch 5y agoIs there a reason github can’t just have a setting to prevent you from pushing secrets in the first place? Is it really that processing heavy?
- nomoreplease 5y agoI assume they could. Meanwhile, I’ve used the git-secrets tool
- psanford 5y agoYou might have strings that match one of their secrets regex's that are not an actual secret. It would be extremely annoying if they blocked you from pushing a commit in that case.
- brainzap 5y agoHow much was paid out?
- ortekk 5y ago$0. Their page on Hackerone is a "Vulnerability Disclosure Program", not "Bug Bounty Program".
- lima 5y agoCloudflare, in some ways, still has a startup mindset when it comes to security and operations (both in good and bad ways).
- swiley 5y agoBut they're terminating people's TLS?
- miou 5y agoIt is possible they received a reward, it just isn't publicized. "The decision to pay a reward is entirely at our discretion. You must not violate any law. You are responsible for any tax implications or additional restrictions depending on your country and local law. We reserve the right to cancel this program at any time." (https://www.cloudflare.com/disclosure/ https://www.cloudflare.com/disclosure/)
- uyt 5y agoI was curious if the offending commit is still there but I didn't see anything that looked like it: https://github.com/cdnjs/cdnjs/commits/master?after=6901ec1013898b017734de9c5c4b46f668bf0919+6000&branch=master https://github.com/cdnjs/cdnjs/commits/master?after=6901ec10... That commit log should give you a better sense of what happened if you (like me) didn't understand how cdnjs works. Apparently robocdnjs will just pull arbitrary packages and unzip and commit them into the cdnjs repo which then gets served all over the internet. Crazy!
- shoo 5y agore: the timing reported in the article > April 6, 2021 20:30 [JST] cdnjs processed the file you can see commits in the cdnjs/cdnjs git log adding an absurdly named test package from one of the maintainers to test packages containing symlinks within 24 hours after the exploit
- imvetri 5y agoCloudflare is well known for vulnerabilities. kinda looks sketchy.
- Crazyontap 5y agoThere is probably no good reason to use such CDNs nowadays: 1) The biggest benefit of using cdn was that scripts stylesheets were often loaded from cache. This is no longer the case anymore. 2) It's adding an unnecessary vulnerability as seen from this case. 3) CDN scripts can be (possibly) used to track your website traffic. 4) They often drop third party cookies which decreases your website load speed among other things. It's best to just host your script on Digital ocean spaces or S3 and use a Cloudfront proxy.
- cryptonym 5y agoCDN can protect your servers from DDOS and countless attacks, bots, vulnerabilities. It tends to be patched pretty quickly when there is an issue. It can reduce cost by offloading, improve performance by distributing content (with or without computing) from a closer location, optimise delivery in many ways, scale with limited cost... Extra cookies and scripts are related to specific features. A good CDN will let you configure exactly what you want. Cloudfront is a CDN. EDIT: The issue is more related to using a third party domain in order to load assets on you website. I agree, that should be done from first party when possible.
- judge2020 5y agoYes, I think OP meant “cdnjs” when he was talking about CDNs, not reverse proxies like Cloudflare, Cloudfront or Akamai.
- hansel_der 5y agoi think op was referring to the practice of using a separate cdn for specific resources (like fonts and scripts), not using a cdn per se.
- tobr 5y agoIt’s often the lowest-friction way to include a library in a project. You’ll often see “getting started“ documentation using cdnjs.com because it’s so easy. That’s not a good reason, but probably a very real one.
- 5y ago
- piaste 5y agoFor users: Decentraleyes (https://decentraleyes.org/ https://decentraleyes.org/) is a browser extension that will intercept requests to common CDN library services and serves them from local storage instead if at all possible, kinda like enforcing aggressive Cache-Control for all CDN resources. It's a privacy-oriented extension first, but it may still protect from an eventual zero-day like this.
- mvolfik 5y agoi'm very confused about what it actually does. does it reintroduce shared cache for CDN resources?
- deepCelibate 5y agoGreat article! So, let me see if I get this straight... cdnjs is a CDN for javascript libraries. cdnjs has a "library update server", in which an "auto-update script" runs periodically to update the libraries that the CDN offers. If it finds a new version of a library, it downloads the files from the library's git repository, and it publishes them on the CDN. There can be symlinks in git repositories, but the "auto-update script" doesn't handle them correctly. And that's the core of the vulnerability. If you own the git repository of a library published by cdnjs, you could add a symlink to the git repository. The symlink could point to a file that you want to access on the cdnjs "library update server". Then, as soon as the "auto-update script" runs, the file's contents will be public to everyone on the CDN. But how would you manage to create a malicious library and have it approved by cdnjs? That's the part of the exploit that sounds the hardest, and I don't see a reasonable way to go about it.
- MattIPv4 5y ago> But how would you manage to create a malicious library and have it approved by cdnjs? That's the part of the exploit that sounds the hardest, and I don't see a reasonable way to go about it. 1. Hijack an existing library to publish the malicious version 2. or, Have us approve what looks like a legitimate library, which later publishes a malicious version
- teddyh 5y ago> 1. Hijack an existing library Hijack or buy outright an existing library. IIRC, there have been many such instances where existing projects have been sold for large sums to questionable parties.
- NotEvil 5y agoAs I understand it. Every library in npm registry (they library you can install using npm) are also automatically approved ( which sounds reasonable you don't want to approve every library by hand). And that's what the author exploits by registering a library that have a symlink in it. Which then got excuted.
- dmos62 5y agoI was really excited for a moment, because I thought this was cjdns https://github.com/cjdelisle/cjdns https://github.com/cjdelisle/cjdns.
- jasongill 5y agoI was a bit disappointed by Cloudflare's HackerOne-based disclosure / bug bounty program. I submitted a working proof-of-concept that would allow you to use Cloudflare's page-customizing preview function to create a Cloudflare phishing site. The issue was closed as "accepted as the nature of the cloudflarepreview playground". Then they went ahead and fixed the issue. Not the end of the world, but definitely didn't inspire confidence in the program.
- Tenoke 5y agoI find this is extremely common. Last year I submitted a working proof of concept with detailed explanations of how you can steal passwords and details of users as an app maker on Shopify, and it got denied for a similar reason (though I dont think it's been fixed). I've since stopped wasting my time on such pursuits.
- azemetre 5y agoNo joke, have you thought about selling your exploits to other actors? Exploitation has such a rich history between sellers, buyers, and users; the marketplace is way more sophisticated than what it was in the 90s. You can probably get $5k to $20k for the exploit to Shopify. There are plenty of nationstate actors that create honeypots for a variety of targets. I'm sure Shopify exploits are worth something to someone.